king
2025-01-02 88290b40164b2e153a59751445b1879b06a9f170
Merge branch 'master' into positec
23个文件已修改
6个文件已添加
1536 ■■■■■ 已修改文件
public/index.html 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/manifest.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/paste/index.jsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/balcony/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/card/cardsimplecomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastebasetable/index.jsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/pastecomponent/index.jsx 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/base-table/columns/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/edit-table/columns/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/table/normal-table/columns/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/debug/index.jsx 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/custom/components/card/prop-card/index.jsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/index.jsx 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tabviews/zshare/mutilform/mkPopSelect/index.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/billcodeform/index.jsx 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/index.jsx 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/zshare/verifycard/voucherform/index.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils-custom.js 110 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/utils.js 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/filtermenu/index.jsx 518 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/filtermenu/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/views/rolemanage/index.jsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/syscheck/header/index.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/syscheck/header/index.scss 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/syscheck/index.jsx 513 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/syscheck/index.scss 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html
@@ -60,7 +60,11 @@
      }
      window.mkInfo = function(value, color = '') {
        console.info(value, color)
        if (color) {
          console.info(value, color)
        } else {
          console.info(value)
        }
      }
    </script>
  </head>
public/manifest.json
@@ -6,5 +6,5 @@
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "mk_version": "20241202"
  "mk_version": "20250101"
}
src/api/index.js
@@ -771,7 +771,11 @@
          if (res.mksqls) {
            res.mksqls.forEach(n => {
              n = n.replace(/(UNION ALL\s+)?SELECT obj_name='[\S\s]+sub_field=''\s+/ig, '')
              window.mkInfo(n)
              if (!res.status) {
                window.mkInfo('%c' + n, 'color: #f5222d')
              } else {
                window.mkInfo(n)
              }
            })
          }
          delete res.mksqls
@@ -1090,7 +1094,11 @@
          if (res.mksqls) {
            res.mksqls.forEach(n => {
              n = n.replace(/(UNION ALL\s+)?SELECT obj_name='[\S\s]+sub_field=''\s+/ig, '')
              window.mkInfo(n)
              if (!res.status) {
                window.mkInfo('%c' + n, 'color: #f5222d')
              } else {
                window.mkInfo(n)
              }
            })
          }
          delete res.mksqls
src/components/paste/index.jsx
@@ -1,8 +1,10 @@
import React, {Component} from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Modal, notification } from 'antd'
import { SnippetsOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import MenuUtils from '@/utils/utils-custom.js'
import asyncComponent from '@/utils/asyncComponent'
const PasteForm = asyncComponent(() => import('@/templates/zshare/pasteform'))
@@ -17,6 +19,49 @@
    visible: false
  }
  resetconfig = (item, appType) => {
    if (item.copyType === 'action') {
      MenuUtils.resetBtn(item, item.uuid)
    } else if (item.copyType === 'cardcell') {
      item.setting = item.setting || {}
      item.setting.width = item.setting.width || 6
      delete item.$cardType
      if (item.elements) {
        item.elements = item.elements.map(cell => {
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, item.uuid)
          }
          return cell
        })
        if (appType === 'mob') {
          item.elements = item.elements.filter(cell => {
            if (cell.eleType === 'button' && ['excelIn', 'tab'].includes(cell.OpenType)) {
              return false
            }
            return true
          })
        }
      }
      if (appType === 'mob') {
        item.backElements = []
      } else if (item.backElements) {
        item.backElements = item.backElements.map(cell => {
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, item.uuid)
          }
          return cell
        })
      }
    }
    return item
  }
  pasteSubmit = () => {
    const { options } = this.props
    this.pasteFormRef.handleConfirm().then(res => {
@@ -24,6 +69,12 @@
        notification.warning({ top: 92, message: '配置信息格式错误!', duration: 5 })
        return
      }
      let appType = sessionStorage.getItem('appType')
      res.uuid = Utils.getuuid()
      res = this.resetconfig(res, appType)
      this.props.updateConfig(res, (result) => {
        if (result.status) {
          notification.success({
src/menu/components/card/balcony/index.jsx
@@ -213,7 +213,7 @@
      MKEmitter.emit('cardAddElement', card.uuid, res)
    } else {
      res.eleType = 'button'
      res.width = res.width || 12
      res.width = typeof(res.width) === 'number' ? res.width : 12
      MKEmitter.emit('cardAddElement', card.uuid, res)
    }
    resolve({status: true})
src/menu/components/card/cardcomponent/index.jsx
@@ -400,7 +400,7 @@
    if (element.copyType === 'action') {
      element.eleType = 'button'
      element.width = element.width || 12
      element.width = typeof(element.width) === 'number' ? element.width : 12
    }
    element.uuid = _uuid
src/menu/components/card/cardsimplecomponent/index.jsx
@@ -289,7 +289,7 @@
    
    if (element.copyType === 'action') {
      element.eleType = 'button'
      element.width = element.width || 12
      element.width = typeof(element.width) === 'number' ? element.width : 12
    }
    element.uuid = _uuid
src/menu/components/share/pastebasetable/index.jsx
@@ -4,6 +4,7 @@
import { SnippetsOutlined } from '@ant-design/icons'
import Utils from '@/utils/utils.js'
import MenuUtils from '@/utils/utils-custom.js'
import asyncComponent from '@/utils/asyncComponent'
// import './index.scss'
@@ -52,6 +53,10 @@
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              if (cell.eleType === 'button') {
                MenuUtils.resetBtn(cell, cell.uuid)
              }
              return cell
            })
          }
@@ -69,6 +74,8 @@
        cell.uuid = _uuid
        MenuUtils.resetBtn(cell, cell.uuid)
        return cell
      })
src/menu/components/share/pastecomponent/index.jsx
@@ -6,6 +6,7 @@
import Utils from '@/utils/utils.js'
import MKEmitter from '@/utils/events.js'
import MenuUtils from '@/utils/utils-custom.js'
import asyncComponent from '@/utils/asyncComponent'
// import './index.scss'
@@ -28,7 +29,9 @@
      item.uuid = _uuid
    }
    if (item.copyType === 'cardcell' && config.subtype === 'datacard') {
    if (item.copyType === 'action') {
      MenuUtils.resetBtn(item, _uuid)
    } else if (item.copyType === 'cardcell' && config.subtype === 'datacard') {
      item.setting = item.setting || {}
      item.$cardType = 'extendCard'
      item.setting.width = item.setting.width || 6
@@ -39,6 +42,10 @@
            cell.datatype = 'static'
          }
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, _uuid)
          }
          return cell
        })
      }
@@ -48,6 +55,10 @@
            cell.datatype = 'static'
          }
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, _uuid)
          }
          return cell
        })
      }
@@ -64,12 +75,18 @@
      if (item.elements) {
        item.elements = item.elements.map(cell => {
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, _uuid)
          }
          return cell
        })
      }
      if (item.backElements) {
        item.backElements = item.backElements.map(cell => {
          cell.uuid = Utils.getuuid()
          if (cell.eleType === 'button') {
            MenuUtils.resetBtn(cell, _uuid)
          }
          return cell
        })
      }
@@ -87,6 +104,9 @@
          } else if (col.type === 'custom' && col.elements) {
            col.elements = col.elements.map(cell => {
              cell.uuid = Utils.getuuid()
              if (cell.eleType === 'button') {
                MenuUtils.resetBtn(cell, _uuid)
              }
              return cell
            })
          }
src/menu/components/table/base-table/columns/index.jsx
@@ -391,7 +391,7 @@
    if (!cell.eleType) {
      if (cell.copyType === 'action') {
        cell.eleType = 'button'
        cell.width = cell.width || 12
        cell.width = typeof(cell.width) === 'number' ? cell.width : 12
      } else {
        cell.eleType = 'text'
      }
src/menu/components/table/edit-table/columns/index.jsx
@@ -386,7 +386,7 @@
    if (!cell.eleType) {
      if (cell.copyType === 'action') {
        cell.eleType = 'button'
        cell.width = cell.width || 12
        cell.width = typeof(cell.width) === 'number' ? cell.width : 12
      } else {
        cell.eleType = 'text'
      }
src/menu/components/table/normal-table/columns/index.jsx
@@ -381,7 +381,7 @@
    if (!cell.eleType) {
      if (cell.copyType === 'action') {
        cell.eleType = 'button'
        cell.width = cell.width || 12
        cell.width = typeof(cell.width) === 'number' ? cell.width : 12
      } else {
        cell.eleType = 'text'
      }
src/menu/debug/index.jsx
@@ -1157,17 +1157,6 @@
  
    // 唯一性验证,必须存在表单(表单存在时,主键均为单值),必须填写数据源,多行拼接时不可用
    if (formdata && verify.uniques && verify.uniques.length > 0 && btn.Ot !== 'requiredOnce') {
      let dateForms = []
      let numForms = []
      formdata.forEach(form => {
        let _key = form.key.toLowerCase()
        if (form.type === 'date') {
          dateForms.push(_key)
        } else if (form.type === 'number' || form.type === 'rate') {
          numForms.push(_key)
        }
      })
      verify.uniques.forEach(item => {
        let _fieldValue = []                     // 表单键值对field=value
        let _value = []                          // 表单值,用于错误提示
@@ -1177,21 +1166,26 @@
        item.field.split(',').forEach((_field, index) => {
          let _key = _field.toLowerCase()
          let _val = ''
          let _val2 = ''
  
          arr.push(_key)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
          if (_key === 'bid') {
            _val = BID
          } else if (numForms.includes(_key)) {
            _val = '1'
          } else if (dateForms.includes(_key)) {
            _val = '1949-10-01'
          } else {
            _val = `@${_field}`
          }
          _fieldValue.push(`${_key}='${_val}'`)
          _value.push(`${_labels[index] || ''}:${_val || ''}`)
          if (_key === 'bid') {
            _val2 = `' + ${BID} + '`
          } else {
            _val2 = `' + @${_field} + '`
          }
          _fieldValue.push(`${_key}=${_val}`)
          _value.push(`${_labels[index] || ''}:${_val2}`)
        })
  
        if (!arr.includes(primaryKey.toLowerCase())) {
        if (!arr.includes(primaryKey.toLowerCase()) && btn.Ot !== 'notRequired') {
          _fieldValue.push(`${primaryKey} !='${primaryId}'`)
        }
  
src/router/index.js
@@ -24,6 +24,7 @@
const RoleManage = asyncLoadComponent(() => import('@/views/rolemanage'))
const SystemFunc = asyncLoadComponent(() => import('@/views/systemfunc'))
const SystemProc = asyncLoadComponent(() => import('@/views/systemproc'))
// const SystemCheck = asyncLoadComponent(() => import('@/views/syscheck'))
const MkIframe = asyncLoadComponent(() => import('@/views/mkiframe'))
const routers = [
@@ -53,7 +54,8 @@
  {path: '/iframe/:menuId/:loginUid/:bid', name: 'iframe', component: MkIframe},
  {path: '/view/:menuId', name: 'iframe', component: MkIframe},
  {path: '/view/:menuId/:bid', name: 'iframe', component: MkIframe},
  {path: '/interface', name: 'interface', component: Interface}
  {path: '/interface', name: 'interface', component: Interface},
  // {path: '/syscheck', name: 'syscheck', component: SystemCheck}
]
export default class RouteConfig extends Component {
src/tabviews/custom/components/card/prop-card/index.jsx
@@ -399,7 +399,9 @@
    this.autoTimer && clearTimeout(this.autoTimer)
    if (btn) {
    if (config.setting.supModule && config.wrap.datatype === 'static' && !data.$$BID) {
    } else if (btn) {
      MKEmitter.emit('triggerBtnId', config.wrap.autoExec, data.$$empty ? [] : [data])
    } else if (!times || times < 20) {
      times = times ? times + 1 : 1
@@ -526,11 +528,11 @@
      this.setState({
        data: _data,
      }, () => {
        if (!btn) {
          this.autoExec()
        }
      })
      if (!btn) {
        this.autoExec()
      }
      return
    } else if (config.setting.supModule && !BID) { // BID 不存在时,不做查询
      this.setState({
src/tabviews/zshare/mutilform/index.jsx
@@ -297,6 +297,9 @@
        } else {
          item.showValue = ''
        }
        if (window.backend && action.uuid) {
          item.formSqlId = md5(action.uuid.replace(/_pop$/, '') + item.uuid)
        }
      } else if (item.type === 'brafteditor') {
        if (window.backend && newval && /<\/span>/.test(newval) && item.encryption === 'true') {
          try {
src/tabviews/zshare/mutilform/mkPopSelect/index.jsx
@@ -122,8 +122,8 @@
    })
    let param = null
    if (window.backend && window.GLOB.CacheData.has('sql_' + config.uuid)) {
      let ex = window.GLOB.CacheData.get('sql_' + config.uuid)
    if (window.backend && window.GLOB.CacheData.has('sql_' + config.formSqlId)) {
      let ex = window.GLOB.CacheData.get('sql_' + config.formSqlId)
      let sysvals = {
        time_id: Utils.getguid(),
        mk_departmentcode: sessionStorage.getItem('departmentcode') || '',
src/templates/zshare/verifycard/billcodeform/index.jsx
@@ -91,6 +91,7 @@
      }, () => {
        this.props.form.setFieldsValue({
          field: record.field,
          Type: record.Type || 4,
          TypeCharOne: record.TypeCharOne,
          ModularCode: record.ModularCode,
          ModularDetailCode: _modularDetailCode,
@@ -174,7 +175,7 @@
          // 设置流水号位数
          let _detail = this.state.modularDetail.filter(item => item.ModularDetailCode === values.ModularDetailCode)[0]
          values.Type = _detail.Type
          values.Type = values.Type || _detail.Type
        } else {
          let _billField = billFields.filter(item => item.field === values.linkField)[0]
          values.linkFieldName = _billField ? _billField.label : ''
@@ -231,8 +232,8 @@
              })(
                <Select>
                  {this.state.funFields.map(option =>
                    <Select.Option title={option.label} id={option.uuid} key={option.uuid} value={option.field}>
                      {option.label}
                    <Select.Option key={option.uuid} value={option.field}>
                      {`${option.label}(${option.field})`}
                    </Select.Option>
                  )}
                </Select>
@@ -240,7 +241,7 @@
            </Form.Item>
          </Col>
          <Col span={7}>
            <Form.Item label={'类型'}>
            <Form.Item label="类型">
              {getFieldDecorator('TypeCharOne', {
                initialValue: 'Lp',
                rules: [
@@ -260,7 +261,7 @@
            </Form.Item>
          </Col>
          {type === '1' ? <Col span={7}>
            <Form.Item label={'关联字段'}>
            <Form.Item label="关联字段">
              {getFieldDecorator('linkField', {
                initialValue: '',
                rules: [
@@ -270,10 +271,10 @@
                  }
                ]
              })(
                <Select>
                <Select showSearch filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>
                  {this.state.billFields.map(option =>
                    <Select.Option title={option.label} id={option.uuid} key={option.uuid} value={option.field}>
                      {option.label}
                    <Select.Option key={option.uuid} value={option.field}>
                      {`${option.label}(${option.field})`}
                    </Select.Option>
                  )}
                </Select>
@@ -281,7 +282,7 @@
            </Form.Item>
          </Col> : null}
          {type === '2' ? <Col span={7}>
            <Form.Item label={'凭证类型'}>
            <Form.Item label="凭证类型">
              {getFieldDecorator('ModularCode', {
                initialValue: this.props.modular[0] ? this.props.modular[0].ID : '',
                rules: [
@@ -297,7 +298,7 @@
                  onChange={(value) => {this.voucherChange(value)}}
                >
                  {this.props.modular.map(option =>
                    <Select.Option title={option.NameNO} id={option.ID} key={option.ID} value={option.ID}>
                    <Select.Option key={option.ID} value={option.ID}>
                      {option.NameNO}
                    </Select.Option>
                  )}
@@ -310,7 +311,7 @@
              保存
            </Button>
          </Col>
          {type === '1' ? <Col span={7}>
          <Col span={7}>
            <Form.Item label="位数">
              {getFieldDecorator('Type', {
                initialValue: 4,
@@ -322,7 +323,7 @@
                ]
              })(<InputNumber min={1} max={10} precision={0} onPressEnter={this.handleConfirm}/>)}
            </Form.Item>
          </Col> : null}
          </Col>
          {type === '2' ? <Col span={7}>
            <Form.Item label="凭证标识">
              {getFieldDecorator('ModularDetailCode', {
@@ -339,7 +340,7 @@
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                >
                  {this.state.modularDetail.map(option =>
                    <Select.Option style={{whiteSpace: 'unset'}} title={option.CodeName} id={option.ModularDetailCode} key={option.ModularDetailCode} value={option.ModularDetailCode}>
                    <Select.Option style={{whiteSpace: 'unset'}} key={option.ModularDetailCode} value={option.ModularDetailCode}>
                      {option.CodeName}
                    </Select.Option>
                  )}
src/templates/zshare/verifycard/index.jsx
@@ -848,7 +848,7 @@
      colfields: colfields.join(', '),
      uniqueColumns: this.state.uniqueColumns.map(col => {
        if (col.dataIndex === 'field') {
          col.options = _fields
          col.options = unionFields
        }
        return col
      }),
@@ -1353,21 +1353,26 @@
        item.field.split(',').forEach((_field, index) => {
          let _key = _field.toLowerCase()
          let _val = ''
          let _val2 = ''
  
          arr.push(_key)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
          if (_key === 'bid') {
            _val = BID
          } else if (numForms.includes(_key)) {
            _val = '1'
          } else if (dateForms.includes(_key)) {
            _val = '1949-10-01'
          } else {
            _val = `@${_field}`
          }
          _fieldValue.push(`${_key}='${_val}'`)
          _value.push(`${_labels[index] || ''}:${_val || ''}`)
          if (_key === 'bid') {
            _val2 = `' + ${BID} + '`
          } else {
            _val2 = `' + @${_field} + '`
          }
          _fieldValue.push(`${_key}=${_val}`)
          _value.push(`${_labels[index] || ''}:${_val2}`)
        })
  
        if (!arr.includes(primaryKey.toLowerCase())) {
        if (!arr.includes(primaryKey.toLowerCase()) && btn.Ot !== 'notRequired') {
          _fieldValue.push(`${primaryKey} !='${primaryId}'`)
        }
  
@@ -2671,7 +2676,7 @@
          } key="uniques">
            <UniqueForm
              btn={card}
              fields={card.Ot !== 'requiredOnce' ? fields : columnsFields}
              fields={card.Ot !== 'requiredOnce' ? unionFields : columnsFields}
              uniqueChange={this.uniqueChange}
            />
            <EditTable actions={['edit', 'move', 'del', 'status', 'sql']} data={verify.uniques} columns={card.Ot !== 'requiredOnce' ? uniqueColumns : onceUniqueColumns} onChange={this.changeUniques}/>
src/templates/zshare/verifycard/voucherform/index.jsx
@@ -196,7 +196,7 @@
                  onChange={(value) => {this.voucherSChange(value)}}
                >
                  {this.state.voucher.map(option =>
                    <Select.Option title={option.NameNO} id={option.ID} key={option.ID} value={option.ID}>
                    <Select.Option key={option.ID} value={option.ID}>
                      {option.NameNO}
                    </Select.Option>
                  )}
@@ -221,7 +221,7 @@
                  onChange={this.contentChange}
                >
                  {this.state.voucherDetail.map(option =>
                    <Select.Option title={option.CodeName} id={option.ModularDetailCode} key={option.ModularDetailCode} value={option.ModularDetailCode}>
                    <Select.Option key={option.ModularDetailCode} value={option.ModularDetailCode}>
                      {option.CodeName}
                    </Select.Option>
                  )}
@@ -246,8 +246,8 @@
                  onChange={this.contentChange}
                >
                  {columns.map((option, index) =>
                    <Select.Option title={option.label} id={index + option.uuid} key={index + option.uuid} value={option.field}>
                      {option.label}
                    <Select.Option key={index + option.uuid} value={option.field}>
                      {`${option.label}(${option.field})`}
                    </Select.Option>
                  )}
                </Select>
src/utils/utils-custom.js
@@ -652,7 +652,7 @@
   */
  static resetBtn (btn, commonId) {
    if (btn.OpenType === 'pop' || (btn.OpenType === 'funcbutton' && btn.execMode === 'pop')) {
      if (btn.modal && btn.modal.fields.length > 0) {
      if (btn.modal && btn.modal.fields && btn.modal.fields.length > 0) {
        btn.modal.fields = btn.modal.fields.map(m => {
          m.uuid = this.getuuid()
          return m
@@ -684,6 +684,10 @@
        return md5(commonId + m)
      })
    }
    if (btn.OpenType === 'popview' && btn.config && btn.config.components) {
      btn.config.components = this.resetConfig(btn.config.components, commonId)
    }
  }
@@ -771,14 +775,7 @@
            if (cell.eleType === 'button') {
              cell.uuid = md5(commonId + cell.uuid)
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (cell.modal && cell.modal.fields.length > 0) {
                  cell.modal.fields = cell.modal.fields.map(m => {
                    m.uuid = this.getuuid()
                    return m
                  })
                }
              }
              this.resetBtn(cell, commonId)
            } else {
              cell.uuid = this.getuuid()
            }
@@ -792,14 +789,8 @@
          card.backElements = card.backElements.map(cell => {
            if (cell.eleType === 'button') {
              cell.uuid = md5(commonId + cell.uuid)
              if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                if (cell.modal && cell.modal.fields.length > 0) {
                  cell.modal.fields = cell.modal.fields.map(m => {
                    m.uuid = this.getuuid()
                    return m
                  })
                }
              }
              this.resetBtn(cell, commonId)
            } else {
              cell.uuid = this.getuuid()
            }
@@ -818,14 +809,8 @@
        item.elements = item.elements.map(cell => {
          if (cell.eleType === 'button') {
            cell.uuid = md5(commonId + cell.uuid)
            if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
              if (cell.modal && cell.modal.fields.length > 0) {
                cell.modal.fields = cell.modal.fields.map(m => {
                  m.uuid = this.getuuid()
                  return m
                })
              }
            }
            this.resetBtn(cell, commonId)
          } else {
            cell.uuid = this.getuuid()
          }
@@ -850,14 +835,7 @@
            col.elements = col.elements.map(cell => {
              cell.uuid = md5(commonId + cell.uuid)
              if (cell.eleType === 'button') {
                if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
                  if (cell.modal && cell.modal.fields.length > 0) {
                    cell.modal.fields = cell.modal.fields.map(m => {
                      m.uuid = this.getuuid()
                      return m
                    })
                  }
                }
                this.resetBtn(cell, commonId)
              }
              return cell
            })
@@ -902,14 +880,7 @@
      }
      item.action = item.action.map(cell => {
        cell.uuid = md5(commonId + cell.uuid)
        if (cell.OpenType === 'pop' || (cell.OpenType === 'funcbutton' && cell.execMode === 'pop')) {
          if (cell.modal && cell.modal.fields.length > 0) {
            cell.modal.fields = cell.modal.fields.map(m => {
              m.uuid = this.getuuid()
              return m
            })
          }
        }
        this.resetBtn(cell, commonId)
        return cell
      })
@@ -1963,6 +1934,10 @@
          })
        }
        let emptys = []
        if (cell.Ot !== 'notRequired') {
          forms.push(...columns)
        }
        cell.verify.uniques.forEach(m => {
          if (m.status === 'false') return
@@ -1974,7 +1949,11 @@
        })
        if (emptys.length) {
          errors.push({ level: 0, detail: `按钮“${cell.label}”唯一性验证字段${emptys.join('、')},在表单中不存在!`})
          if (cell.Ot === 'notRequired') {
            errors.push({ level: 0, detail: `按钮“${cell.label}”唯一性验证字段${emptys.join('、')},在表单中不存在!`})
          } else {
            errors.push({ level: 0, detail: `按钮“${cell.label}”唯一性验证字段${emptys.join('、')},在表单与字段集中不存在!`})
          }
        }
      }
@@ -3331,7 +3310,7 @@
          } else if (form.type === 'popSelect') {
            let msg = getPopSelectSql(form)
        
            sqls.push({uuid: form.uuid, type: 'popSource', ...msg})
            sqls.push({uuid: md5(cell.uuid + form.uuid), type: 'popSource', ...msg})
          }
        })
      }
@@ -3374,7 +3353,7 @@
            } else if (form.type === 'popSelect') {
              let msg = getPopSelectSql(form)
          
              sqls.push({uuid: form.uuid, type: 'popSource', ...msg})
              sqls.push({uuid: md5(cell.uuid + form.uuid), type: 'popSource', ...msg})
            }
          })
        }
@@ -3414,7 +3393,9 @@
          })
        }
        filterComponent(cell.config.components, _mainSearch, '-' + cell.label, true)
        let label = (item.name ? '-' + item.name : '') + '-' + cell.label
        filterComponent(cell.config.components, _mainSearch, label, true)
      }
    }
  }
@@ -3823,24 +3804,26 @@
          let _val2 = ''
  
          arr.push(_key)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
          if (_key === 'bid') {
            _val = BID
          } else {
            _val = `'@mk_${_key}_mk@'`
            // _val = `'@mk_${_key}_mk@'`
            _val = `@${_field}`
          }
          _fieldValue.push(`${_key}=${_val}`)
          if (_key === 'bid') { // 表单中没有bid则使用系统bid变量
          if (_key === 'bid') {
            _val2 = `' + ${BID} + '`
          } else {
            _val2 = `@mk_${_key}_mk@`
            // _val2 = `@mk_${_key}_mk@`
            _val2 = `' + @${_field} + '`
          }
          _value.push(`${_labels[index] || ''}:${_val2}`)
        })
  
        if (!arr.includes(primaryKey.toLowerCase())) {
        if (!arr.includes(primaryKey.toLowerCase()) && btn.Ot !== 'notRequired') {
          _fieldValue.push(`${primaryKey} !=${primaryId}`)
        }
  
@@ -6450,5 +6433,32 @@
  filterComponent(config.components, _mainSearch)
  let keys = sqls.map(item => item.uuid)
  if (keys.length > Array.from(new Set(keys)).length && !window.GLOB.syscheck) {
    if (window.backend) {
      let m = new Map()
      let n = new Map()
      sqls.forEach(item => {
        if (m.has(item.uuid)) {
          if (!n.has(item.uuid)) {
            window.mkInfo(m.get(item.uuid))
            n.set(item.uuid, true)
          }
          window.mkInfo(item)
        } else {
          m.set(item.uuid, item)
        }
      })
      notification.warning({
        top: 92,
        message: '存在重复的后端脚本ID!',
        duration: 5
      })
    }
    return []
  }
  return sqls
}
src/utils/utils.js
@@ -2176,18 +2176,27 @@
      item.field.split(',').forEach((_field, index) => {
        let _key = _field.toLowerCase()
        let _val = datavars[_key] !== undefined ? datavars[_key] : ''
        let _val = ''
        let _val2 = ''
        arr.push(_key)
        if (_key === 'bid' && !_val) { // 表单中没有bid则使用系统bid变量
        if (_key === 'bid') {
          _val = BID
        } else {
          _val = `@${_field}`
        }
        _fieldValue.push(`${_key}='${_val}'`)
        _value.push(`${_labels[index] || ''}:${_val || ''}`)
        if (_key === 'bid') {
          _val2 = `' + ${BID} + '`
        } else {
          _val2 = `' + @${_field} + '`
        }
        _fieldValue.push(`${_key}=${_val}`)
        _value.push(`${_labels[index] || ''}:${_val2}`)
      })
      if (!arr.includes(primaryKey.toLowerCase())) {
      if (!arr.includes(primaryKey.toLowerCase()) && btn.Ot !== 'notRequired') {
        _fieldValue.push(`${primaryKey} !='${primaryId}'`)
      }
src/views/rolemanage/filtermenu/index.jsx
New file
@@ -0,0 +1,518 @@
import React, { Component } from 'react'
import { Button, notification, Modal, Table } from 'antd'
import moment from 'moment'
import Api from '@/api'
import Utils from '@/utils/utils.js'
// import './index.scss'
const { confirm } = Modal
class AppMenuFilter extends Component {
  state = {
    visible: false,
    loading: false,
    unUseMenus: [],
    selectedRowKeys: [],
    columns: [
      {
        title: '菜单名称', dataIndex: 'MenuName', key: 'MenuName', align: 'center'
      },
      {
        title: '菜单参数', dataIndex: 'MenuNo', key: 'MenuNo', align: 'center'
      },
      {
        title: '修改时间', dataIndex: 'modifydate', key: 'modifydate', align: 'center'
      },
      {
        title: '操作',
        key: 'action',
        align: 'center',
        render: (text, record) => (
          <Button type="link" onClick={() => this.jumpApp(record)} style={{color: '#1890ff', marginLeft: '5px'}}>查看</Button>
        ),
      },
    ]
  }
  menus = []
  unchecks = []
  allmenus = []
  trigger = () => {
    this.menus = []
    this.unchecks = []
    this.allmenus = []
    this.setState({
      visible: true,
      loading: true,
      unUseMenus: [],
      selectedRowKeys: []
    })
    this.getAppViewList()
  }
  jumpApp = (item) => {
    const { app } = this.props
    let route = 'mobdesign'
    if (app.typename === 'pc') {
      route = 'pcdesign'
    }
    if (item.menus_rolelist) {
      item.type = 'view'
      try {
        let pageParam = JSON.parse(window.decodeURIComponent(window.atob(item.menus_rolelist)))
        if (pageParam.type === 'navbar') {
          item.type = 'navbar'
        }
      } catch(e) {
      }
    }
    if (item.type === 'navbar') {
      notification.warning({
        top: 92,
        message: '导航栏不可单独打开,请在含有导航栏的页面中查看。',
        duration: 5
      })
      return
    }
    window.open(window.location.href.replace(/#.+/ig, `#/${route}/${window.btoa(window.encodeURIComponent(JSON.stringify({...app, MenuID: item.MenuID, type: 'app'})))}`))
  }
  getAppViewList = () => {
    const { app } = this.props
    Api.getCloudConfig({
      func: 's_get_keyids',
      bid: app.ID
    }).then(result => {
      if (!result.status) {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
        return
      }
      let indexPage = ''
      result.data.forEach(item => {
        if (item.keys_type === 'index') {
          indexPage = item.keys_id
        }
      })
      if (!indexPage) {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: '应用未设置首页!',
          duration: 5
        })
        return
      }
      this.unchecks.push(indexPage)
      if (app.user_binding === 'true' && app.userbind && indexPage !== app.userbind) {
        this.unchecks.push(app.userbind)
      }
      this.getMenuList()
    })
  }
  getMenuList = () => {
    const { app } = this.props
    let param = {
      func: 's_get_app_menus',
      TypeCharOne: app.kei_no,
      typename: app.typename,
      LText: `select '${window.GLOB.appkey}'`,
      timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
      lang: app.lang
    }
    param.secretkey = Utils.encrypt(param.LText, param.timestamp)
    Api.getCloudConfig(param).then(result => {
      if (result.status) {
        this.setState({
          menulist: result.menus
        })
        this.allmenus = result.menus.map(item => item.MenuID)
        if (result.menus.length === 0) {
          this.setState({
            loading: false
          })
          notification.warning({
            top: 92,
            message: '子应用菜单为空!',
            duration: 5
          })
        } else if (result.menus.findIndex(item => item.MenuID === this.unchecks[0]) === -1) {
          this.setState({
            loading: false
          })
          notification.warning({
            top: 92,
            message: '请设置应用首页!',
            duration: 5
          })
        } else {
          this.getMenuParam()
        }
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  getMenuParam = () => {
    const { app } = this.props
    const { visible } = this.state
    if (!visible) return
    let MenuID = this.unchecks.shift()
    let param = {
      func: 'sPC_Get_LongParam',
      MenuID: MenuID,
      TypeCharOne: app.kei_no,
      typename: app.typename,
      lang: app.lang,
    }
    Api.getCloudConfig(param).then(result => {
      if (result.status) {
        let config = null
        try {
          config = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : null
        } catch (e) {
          console.warn('Parse Failure')
          config = null
        }
        this.menus.push(MenuID)
        if (config) {
          let menus = []
          if (config.type === 'navbar') {
            config.menus.forEach(k => {
              if (k.property === 'classify') {
                k.sublist && k.sublist.forEach(m => {
                  if (m.property === 'classify') {
                    m.sublist && m.sublist.forEach(n => {
                      if (n.property === 'menu') {
                        menus.push(n.MenuID)
                      } else if (n.property === 'linkmenu') {
                        menus.push(n.linkMenuId)
                      }
                    })
                  } else if (m.property === 'menu') {
                    menus.push(m.MenuID)
                  } else if (m.property === 'linkmenu') {
                    menus.push(m.linkMenuId)
                  }
                })
              } else if (k.property === 'menu') {
                menus.push(k.MenuID)
              } else if (k.property === 'linkmenu') {
                menus.push(k.linkMenuId)
              }
            })
          }
          config.components && this.resetConfig(config.components, menus)
          menus = Array.from(new Set(menus))
          menus.forEach(n => {
            if (this.allmenus.includes(n) && !this.menus.includes(n)) {
              this.unchecks.push(n)
            }
          })
        }
        if (this.unchecks.length > 0) {
          setTimeout(() => {
            this.getMenuParam()
          }, 200)
        } else {
          this.setState({
            loading: false
          })
          this.getUseMenus()
        }
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  resetConfig = (components, menus) => {
    components.forEach(item => {
      if (item.subtype === 'tablecard') { // 兼容
        item.type = 'card'
      }
      if (item.type === 'navbar') {
        menus.push(item.uuid)
      } else if (item.type === 'tabs') {
        item.subtabs.forEach(tab => {
          this.resetConfig(tab.components, menus)
        })
      } else if (item.type === 'group') {
        this.resetConfig(item.components, menus)
      } else if (item.type === 'menubar') {
        item.subMenus.forEach(cell => {
          if (cell.setting.type === 'linkmenu' && cell.setting.linkMenuId && typeof(cell.setting.linkMenuId) === 'string') {
            menus.push(cell.setting.linkMenuId)
          } else if (cell.setting.type === 'menu') {
            menus.push(cell.uuid)
          }
        })
      } else if (['card', 'carousel', 'timeline'].includes(item.type)) {
        item.subcards.forEach(card => {
          if (card.setting.click === 'menu' && typeof(card.setting.menu) === 'string') {
            menus.push(card.setting.menu)
          } else if (card.setting.click === 'menus') {
            card.menus && card.menus.forEach(n => {
              if (n.menu && typeof(n.menu) === 'string') {
                menus.push(n.menu)
              }
            })
          }
          card.elements && card.elements.forEach(cell => {
            if (cell.eleType === 'button') {
              if (cell.linkmenu && typeof(cell.linkmenu) === 'string') {
                menus.push(cell.linkmenu)
              } else if (cell.openmenu && typeof(cell.openmenu) === 'string') {
                menus.push(cell.openmenu)
              }
            }
          })
          card.backElements && card.backElements.forEach(cell => {
            if (cell.eleType === 'button') {
              if (cell.linkmenu && typeof(cell.linkmenu) === 'string') {
                menus.push(cell.linkmenu)
              } else if (cell.openmenu && typeof(cell.openmenu) === 'string') {
                menus.push(cell.openmenu)
              }
            }
          })
        })
      } else if (item.type === 'balcony') {
        item.elements && item.elements.forEach(cell => {
          if (cell.eleType === 'button') {
            if (cell.linkmenu && typeof(cell.linkmenu) === 'string') {
              menus.push(cell.linkmenu)
            } else if (cell.openmenu && typeof(cell.openmenu) === 'string') {
              menus.push(cell.openmenu)
            }
          }
        })
      } else if (item.type === 'table') {
        let loopCol = (cols) => {
          cols.forEach(col => {
            if (col.type === 'action') {
              col.type = 'custom'
            }
            if (col.type === 'colspan' && col.subcols) {
              loopCol(col.subcols)
            } else if (col.type === 'custom') {
              col.elements && col.elements.forEach(cell => {
                if (cell.eleType === 'button') {
                  if (cell.linkmenu && typeof(cell.linkmenu) === 'string') {
                    menus.push(cell.linkmenu)
                  } else if (cell.openmenu && typeof(cell.openmenu) === 'string') {
                    menus.push(cell.openmenu)
                  }
                }
              })
            }
          })
        }
        item.cols && loopCol(item.cols)
      } else if (item.type === 'form') {
        item.subcards.forEach(cell => {
          if (cell.subButton && cell.subButton.openmenu && typeof(cell.subButton.openmenu) === 'string') {
            menus.push(cell.subButton.openmenu)
          }
        })
      } else if (item.type === 'login') {
        if (item.wrap.linkmenu && typeof(item.wrap.linkmenu) === 'string') {
          menus.push(item.wrap.linkmenu)
        }
      } else if (item.type === 'topbar') {
        if (item.wrap.linkmenu && typeof(item.wrap.linkmenu) === 'string') {
          menus.push(item.wrap.linkmenu)
        }
        item.wrap.menus && item.wrap.menus.forEach(cell => {
          if (cell.menu && typeof(cell.menu) === 'string') {
            menus.push(cell.menu)
          }
        })
      }
      item.action && item.action.forEach(cell => {
        if (cell.linkmenu && typeof(cell.linkmenu) === 'string') {
          menus.push(cell.linkmenu)
        } else if (cell.openmenu && typeof(cell.openmenu) === 'string') {
          menus.push(cell.openmenu)
        }
      })
    })
  }
  getUseMenus = () => {
    const { menulist } = this.state
    let unmenus = []
    menulist.forEach(m => {
      if (!this.menus.includes(m.MenuID)) {
        unmenus.push(m)
      }
    })
    this.setState({
      unUseMenus: unmenus
    })
  }
  deletemenu = () => {
    const { app, getMenuList } = this.props
    const { selectedRowKeys, unUseMenus, loading } = this.state
    if (loading) {
      notification.warning({
        top: 92,
        message: '菜单解析中,请稍后!',
        duration: 5
      })
      return
    }
    if (unUseMenus.length === 0) {
      this.setState({visible: false})
    } else if (selectedRowKeys.length === 0) {
      notification.warning({
        top: 92,
        message: '请选择需要删除的菜单!',
        duration: 5
      })
    } else {
      let param = {
        func: 'sPC_MainMenu_Del',
        MenuID: selectedRowKeys.join(','),
        TypeCharOne: app.kei_no,
        typename: app.typename,
        lang: app.lang
      }
      const that = this
      confirm({
        content: '确定删除菜单吗?',
        onOk() {
          return new Promise(resolve => {
            Api.getCloudConfig(param).then(result => {
              if (result.status) {
                notification.success({
                  top: 92,
                  message: '删除成功!',
                  duration: 3
                })
                that.setState({visible: false})
                getMenuList()
              } else {
                notification.warning({
                  top: 92,
                  message: result.message,
                  duration: 5
                })
              }
              resolve()
            }, () => {
              resolve()
            })
          })
        },
        onCancel() {}
      })
    }
  }
  render () {
    const { visible, loading, columns, unUseMenus, selectedRowKeys } = this.state
    return (
      <>
        <Button className="mk-orange" onClick={this.trigger}>过滤菜单</Button>
        <Modal
          title="过滤菜单"
          visible={visible}
          width={800}
          onOk={this.deletemenu}
          onCancel={() => this.setState({visible: false, loading: false})}
          destroyOnClose
        >
          <div style={{fontSize: '16px', position: 'relative', top: '-15px', color: '#1890ff'}}>系统将自动过滤无关联关系的菜单,选择需要删除的菜单,点击确定。</div>
          <Table
            rowKey="MenuID"
            columns={columns}
            dataSource={unUseMenus}
            loading={loading}
            rowSelection={{
              selectedRowKeys,
              type: 'checkbox',
              onChange: (keys) => this.setState({ selectedRowKeys: keys })
            }}
            pagination={false}
          />
        </Modal>
      </>
    )
  }
}
export default AppMenuFilter
src/views/rolemanage/filtermenu/index.scss
src/views/rolemanage/index.jsx
@@ -15,6 +15,7 @@
const { Search } = Input
const Header = asyncComponent(() => import('./header'))
const FilterMenu = asyncComponent(() => import('./filtermenu'))
const TransferForm = asyncComponent(() => import('@/templates/zshare/basetransferform'))
class RoleManage extends Component {
@@ -925,6 +926,7 @@
            <div className="app-table">
              <div className="app-action">
                <Button className="mk-green" onClick={this.triggerThaw}>解冻菜单</Button>
                <FilterMenu app={app} getMenuList={this.getMenuList}/>
                <Search placeholder="综合搜索" onSearch={value => this.setState({ searchkey: value })} enterButton />
              </div>
              <Table
src/views/syscheck/header/index.jsx
New file
@@ -0,0 +1,34 @@
import React, { Component } from 'react'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import './index.scss'
class SysCheckHeader extends Component {
  state = {
    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
    userName: sessionStorage.getItem('CloudUserName'),
    logo: sessionStorage.getItem('CloudLogo') || MainLogo
  }
  render () {
    const { logo } = this.state
    return (
      <header className="sys-header-container">
        <div className="header-logo"><img src={logo} alt=""/></div>
        <div className="title">
          系统检查
        </div>
        <div className="header-user">
          <img src={this.state.avatar} alt=""/>
          <span>
            <span className="username">{this.state.userName}</span>
          </span>
        </div>
      </header>
    )
  }
}
export default SysCheckHeader
src/views/syscheck/header/index.scss
New file
@@ -0,0 +1,57 @@
.sys-header-container {
  width: 100%;
  height: 48px;
  color: rgba(255, 255, 255, 0.65);
  position: fixed;
  top: 0px;
  z-index: 10;
  padding-right: 0px;
  left: 0;
  background: #001529;
  border-bottom: 1px solid #000;
  .header-logo {
    float: left;
    width: 180px;
    line-height: 48px;
    text-align: center;
    padding-left: 5px;
    box-sizing: border-box;
    opacity: 1;
    img {
      max-width: 100%;
      max-height: 40px;
    }
  }
  .header-user {
    float: right;
    line-height: 48px;
    margin-right: 10px;
    img {
      width: 29px;
      height: 29px;
      border-radius: 30px;
      margin-right: 7px;
    }
    span {
      color: #ffffff;
      font-size: 0.95rem;
      .username {
        display: inline-block;
        height: 30px;
        max-width: 95px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
  }
  .title {
    position: absolute;
    left: calc(50% - 36px);
    top: 10px;
    color: #ffffff;
    font-size: 18px;
  }
}
src/views/syscheck/index.jsx
New file
@@ -0,0 +1,513 @@
import React, {Component} from 'react'
import { fromJS } from 'immutable'
import { Spin, notification, Button, Modal } from 'antd'
import moment from 'moment'
import { SwapOutlined } from '@ant-design/icons'
import Api from '@/api'
import Utils from '@/utils/utils.js'
import asyncComponent from '@/utils/asyncComponent'
import { getAllSqls } from '@/utils/utils-custom.js'
import './index.scss'
const Header = asyncComponent(() => import('./header'))
const { confirm } = Modal
class SysCheck extends Component {
  state = {
    stop: false,
    loading: false,
    menulist: [],
    activeMenu: null,
    remain: 0,
    lackmenus: [],
    outmenus: [],
    backmenus: [],
    appbackmenus: [],
    unablemenus: [],
  }
  sqlmap = null
  // delete _val.controlField 删除按钮控制字段
  UNSAFE_componentWillMount() {
    document.body.className = ''
    window.GLOB.syscheck = true
  }
  componentDidMount() {
    if (!sessionStorage.getItem('UserID')) {
      this.props.history.replace('/login')
      return
    }
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  getMenus = () => {
    this.setState({
      stop: false,
      activeMenu: null,
      remain: 0,
      menulist: [],
      lackmenus: [],
      outmenus: [],
      backmenus: [],
      appbackmenus: [],
      unablemenus: [],
      loading: true
    })
    Api.getCloudConfig({func: 's_get_pc_menus', systemType: window.GLOB.sysType, debug: 'Y'}).then(result => {
      if (result.status) {
        let menulist = []
        result.fst_menu.forEach(fst => {
          if (fst.snd_menu) {
            fst.snd_menu.forEach(snd => {
              if (snd.trd_menu) {
                snd.trd_menu.forEach(trd => {
                  if (trd.PageParam) {
                    let pass = false
                    try {
                      let PageParam = JSON.parse(trd.PageParam)
                      if (PageParam && PageParam.Template === 'RolePermission') {
                        pass = true
                      }
                    } catch (e) {
                    }
                    if (pass) return
                  }
                  menulist.push({
                    MenuID: trd.MenuID,
                    MenuName: trd.MenuName,
                    MenuNo: trd.MenuNo,
                    pName: fst.MenuName + '-' + snd.MenuName,
                  })
                })
              }
            })
          }
        })
        if (menulist.length === 0) {
          this.setState({
            loading: false
          })
          notification.warning({
            top: 92,
            message: '未查询到菜单信息!',
            duration: 5
          })
        } else {
          this.sqlmap = new Map()
          let errlist = sessionStorage.getItem('syscheck_main')
          errlist = errlist ? JSON.parse(errlist) : null
          if (!errlist) {
            this.setState({
              menulist
            })
            this.getMenuParam(fromJS(menulist).toJS())
          } else {
            const that = this
            confirm({
              title: '是否跳过检查合格菜单?',
              content: '',
              okText: '跳过',
              cancelText: '不跳过',
              onOk() {
                menulist = menulist.filter(item => errlist.includes(item.MenuID))
                that.setState({
                  menulist
                })
                that.getMenuParam(fromJS(menulist).toJS())
              },
              onCancel() {
                that.setState({
                  menulist
                })
                that.getMenuParam(fromJS(menulist).toJS())
              }
            })
          }
        }
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  getAppList = () => {
    let param = {
      func: 's_get_kei'
    }
    this.setState({
      stop: false,
      activeMenu: null,
      remain: 0,
      menulist: [],
      lackmenus: [],
      outmenus: [],
      backmenus: [],
      appbackmenus: [],
      unablemenus: [],
      loading: true
    })
    Api.getCloudConfig(param).then(result => {
      if (result.status) {
        let applist = []
        result.data.forEach(item => {
          if (!item.data_detail) return
          item.data_detail.forEach(cell => {
            applist.push({
              ID: cell.d_id,
              name: item.remark,
              typename: cell.typename,
              kei_no: item.kei_no,
              lang: cell.lang,
              menus: []
            })
          })
        })
        if (applist.length === 0) {
          this.setState({
            loading: false
          })
          notification.warning({
            top: 92,
            message: '未查询到菜单信息!',
            duration: 5
          })
        } else {
          let deffers = applist.map((app, i) =>
            new Promise(resolve => {
              let param = {
                func: 's_get_app_menus',
                TypeCharOne: app.kei_no,
                typename: app.typename,
                LText: `select '${window.GLOB.appkey}'`,
                timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
                lang: app.lang
              }
              param.secretkey = Utils.encrypt(param.LText, param.timestamp)
              setTimeout(() => {
                Api.getCloudConfig(param).then(result => {
                  if (result.status) {
                    app.status = true
                    app.menus = []
                    result.menus.forEach(m => {
                      if (m.menus_rolelist) {
                        try {
                          let pageParam = JSON.parse(window.decodeURIComponent(window.atob(m.menus_rolelist)))
                          if (pageParam.type === 'navbar') {
                            m.type = pageParam.type
                          }
                        } catch(e) {
                        }
                        if (m.type === 'navbar') return
                      }
                      delete m.menus_rolelist
                      app.menus.push(m)
                    })
                    resolve(app)
                  } else {
                    resolve(result)
                  }
                })
              }, 200 * i)
            })
          )
          Promise.all(deffers).then(response => {
            let error = response.filter(cell => !cell.status)
            if (error[0]) {
              notification.warning({
                top: 92,
                message: error[0].message,
                duration: 5
              })
              this.setState({
                loading: false
              })
            } else {
              let list = []
              response.forEach(item => {
                item.menus.forEach(cell => {
                  list.push({
                    ...cell,
                    lang: item.lang,
                    kei_no: item.kei_no,
                    typename: item.typename,
                    pName: `${item.name}(${item.typename} / ${item.lang})`,
                  })
                })
              })
              if (list.length === 0) {
                this.setState({
                  loading: false
                })
                notification.warning({
                  top: 92,
                  message: '未查询到菜单信息!',
                  duration: 5
                })
              } else {
                this.sqlmap = new Map()
                let errlist = sessionStorage.getItem('syscheck_app')
                errlist = errlist ? JSON.parse(errlist) : null
                if (!errlist) {
                  this.setState({
                    menulist: list
                  })
                  this.getMenuParam(fromJS(list).toJS())
                } else {
                  const that = this
                  confirm({
                    title: '是否跳过检查合格菜单?',
                    content: '',
                    okText: '跳过',
                    cancelText: '不跳过',
                    onOk() {
                      list = list.filter(item => errlist.includes(item.MenuID))
                      that.setState({
                        menulist: list
                      })
                      that.getMenuParam(fromJS(list).toJS())
                    },
                    onCancel() {
                      that.setState({
                        menulist: list
                      })
                      that.getMenuParam(fromJS(list).toJS())
                    }
                  })
                }
              }
            }
          })
        }
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  getMenuParam = (menus) => {
    const { lackmenus, outmenus, unablemenus, backmenus, appbackmenus, stop } = this.state
    let menu = menus.shift()
    let param = {
      func: 'sPC_Get_LongParam',
      MenuID: menu.MenuID
    }
    if (menu.kei_no) {
      param.TypeCharOne = menu.kei_no
      param.typename = menu.typename
      param.lang = menu.lang
    }
    this.setState({
      activeMenu: menu,
      remain: menus.length
    })
    Api.getCloudConfig(param).then(result => {
      if (result.status) {
        let config = null
        try {
          config = result.LongParam ? JSON.parse(window.decodeURIComponent(window.atob(result.LongParam))) : null
        } catch (e) {
          console.warn('Parse Failure')
          config = null
        }
        if (!config) {
          this.setState({lackmenus: [...lackmenus, menu]})
        } else if (!menu.kei_no && !['CustomPage', 'BaseTable'].includes(config.Template)) {
          this.setState({outmenus: [...outmenus, menu]})
        } else if (!menu.kei_no && config.Template === 'CustomPage' && config.version !== 2.0) {
          menu.version = config.version
          this.setState({outmenus: [...outmenus, menu]})
        } else if (!config.enabled) {
          this.setState({unablemenus: [...unablemenus, menu]})
        } else {
          let sqls = getAllSqls(config)
          let keys = sqls.map(item => item.uuid)
          if (keys.length > Array.from(new Set(keys)).length) {
            this.setState({backmenus: [...backmenus, menu]})
          } else {
            let repeat = false
            let premenu = null
            sqls.forEach(item => {
              if (this.sqlmap.has(item.uuid)) {
                window.mkInfo(item)
                if (repeat) return
                repeat = true
                premenu = this.sqlmap.get(item.uuid)
              } else {
                this.sqlmap.set(item.uuid, menu)
              }
            })
            if (premenu) {
              this.setState({appbackmenus: [...appbackmenus, [premenu, menu]]})
            }
          }
        }
        if (menus.length > 0 && !stop) {
          setTimeout(() => {
            this.getMenuParam(menus)
          }, 200)
        } else {
          this.setState({
            loading: false
          }, () => {
            this.record(menu.kei_no ? 'app' : '')
          })
        }
      } else {
        this.setState({
          loading: false
        })
        notification.warning({
          top: 92,
          message: result.message,
          duration: 5
        })
      }
    })
  }
  record = (type) => {
    const { lackmenus, outmenus, unablemenus, backmenus, appbackmenus } = this.state
    let menus = []
    lackmenus.forEach(item => {
      menus.push(item.MenuID)
    })
    outmenus.forEach(item => {
      menus.push(item.MenuID)
    })
    unablemenus.forEach(item => {
      menus.push(item.MenuID)
    })
    backmenus.forEach(item => {
      menus.push(item.MenuID)
    })
    appbackmenus.forEach(item => {
      menus.push(item[0].MenuID)
      menus.push(item[1].MenuID)
    })
    menus = Array.from(new Set(menus))
    if (type === 'app') {
      if (menus.length) {
        sessionStorage.setItem('syscheck_app', JSON.stringify(menus))
      } else {
        sessionStorage.removeItem('syscheck_app')
      }
    } else {
      if (menus.length) {
        sessionStorage.setItem('syscheck_main', JSON.stringify(menus))
      } else {
        sessionStorage.removeItem('syscheck_main')
      }
    }
  }
  render () {
    const { loading, activeMenu, menulist, remain, lackmenus, outmenus, unablemenus, backmenus, appbackmenus } = this.state
    if (!sessionStorage.getItem('UserID')) return null
    return (
      <div className="mk-app-check">
        <Header view="manage" />
        {loading ? <Spin size="large" /> : null}
        <div className="view-wrap">
          <div className="action">
            <Button disabled={loading} style={{marginRight: '15px'}} onClick={this.getMenus}>检查管理系统菜单</Button>
            <Button disabled={loading} style={{marginRight: '15px'}} onClick={this.getAppList}>检查子应用菜单</Button>
            <Button onClick={() => this.setState({stop: true})}>停止</Button>
          </div>
          {activeMenu ? <div className="menu-msg">当前菜单:{activeMenu.MenuName} <span></span> {activeMenu.pName} <span></span> 进度({menulist.length - remain} / {menulist.length})</div> : null}
          {lackmenus.length ? <div className="item-wrap">
            <div className="title">菜单配置不存在</div>
            {lackmenus.map((item, i) => {
              return <div key={i}>{item.MenuName} <span></span> {item.pName}</div>
            })}
          </div> : null}
          {outmenus.length ? <div className="item-wrap">
            <div className="title">菜单配置需要升级</div>
            {outmenus.map((item, i) => {
              return <div key={i}>{item.MenuName} <span></span> {item.pName}</div>
            })}
          </div> : null}
          {unablemenus.length ? <div className="item-wrap">
            <div className="title">菜单未启用</div>
            {unablemenus.map((item, i) => {
              return <div key={i}>{item.MenuName} <span></span> {item.pName}</div>
            })}
          </div> : null}
          {backmenus.length ? <div className="item-wrap">
            <div className="title">菜单后端脚本ID重复</div>
            {backmenus.map((item, i) => {
              return <div key={i}>{item.MenuName} <span></span> {item.pName}</div>
            })}
          </div> : null}
          {appbackmenus.length ? <div className="item-wrap">
            <div className="title">菜单后端脚本ID重复(菜单间)</div>
            {appbackmenus.map((item, i) => {
              return <div key={i}>{item[0].MenuName} <span></span> {item[0].pName} <SwapOutlined /> {item[1].MenuName} <span></span> {item[1].pName}</div>
            })}
          </div> : null}
        </div>
      </div>
    )
  }
}
export default SysCheck
src/views/syscheck/index.scss
New file
@@ -0,0 +1,52 @@
.mk-app-check {
  background: #fff;
  min-height: 100vh;
  padding: 70px 30px;
  .ant-spin {
    position: fixed;
    z-index: 2;
    left: calc(50% - 22px);
    top: 50%;
  }
  .view-wrap {
    width: 100%;
    position: relative;
    .action {
      .ant-btn {
        color: #fff!important;
        background-color: #1890ff!important;
        border-color: #1890ff!important;
      }
    }
    .menu-msg {
      margin-top: 15px;
      color: #1890ff;
      span {
        display: inline-block;
        width: 20px;
        height: 15px;
      }
    }
    .item-wrap {
      width: 50%;
      display: inline-block;
      margin-top: 30px;
      color: rgba(0, 0, 0, 0.85);
      vertical-align: top;
      .title {
        color: #1890ff;
        border-bottom: 1px solid rgba(0, 0, 0, 0.1);
        margin-bottom: 10px;
        margin-right: 20px;
        padding-bottom: 5px;
      }
      span {
        display: inline-block;
        width: 20px;
        height: 15px;
      }
    }
  }
}