king
2022-07-26 1e3e316b0d64a04fade0a006bec78475dddc06bd
2022-07-26
1 文件已重命名
36个文件已修改
8个文件已添加
1209 ■■■■■ 已修改文件
src/components/thawmenu/index.jsx 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/thawmenu/index.scss 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en-US/model.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh-CN/model.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/form/dragtitle/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/search/main-search/dragsearch/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/actioncomponent/dragaction/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/clockcomponent/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/clockcomponent/settingform/index.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/menu/components/share/searchcomponent/dragsearch/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/components/formdragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/searchconfig/groupdragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mob/searchconfig/searchdragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/formtabconfig/dragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/modalconfig/dragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/actioncomponent/dragaction/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/cardcomponent/dragdetail/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/editfirstmenu/dragelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/editfirstmenu/dragelement/index.jsx 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/editfirstmenu/dragelement/index.scss 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/editfirstmenu/index.jsx 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/editfirstmenu/menuform/index.jsx 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/index.jsx 172 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/header/index.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/index.scss 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/editsecmenu/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/editthdmenu/index.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/index.jsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/index.scss 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/menuelement/card.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/design/sidemenu/menuelement/index.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/history/index.jsx 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/interface/workspace/request/index.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/header/index.jsx 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/header/index.scss 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/index.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/sidemenu/config.jsx 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/sidemenu/index.jsx 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemfunc/sidemenu/index.scss 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/thawmenu/index.jsx
New file
@@ -0,0 +1,134 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Modal, notification, Spin } from 'antd'
import { UnlockOutlined } from '@ant-design/icons'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import TransferForm from '@/templates/zshare/basetransferform'
class ThawMenu extends Component {
  static propTpyes = {
    ParentId: PropTypes.string,
    Type: PropTypes.string
  }
  state = {
    visible: false,
    targetKeys: [],
    menulist: null,
    loading: false
  }
  trigger = () => {
    this.setState({
      visible: true,
      targetKeys: [],
      menulist: null,
      loading: false
    })
    Api.getSystemConfig({
      func: 'sPC_Get_FrozenMenu',
      ParentID: this.props.ParentId,
      TYPE: +this.props.Type
    }).then(res => {
      if (res.status) {
        this.setState({
          menulist: res.data.map(menu => {
            return {
              key: menu.MenuID,
              title: menu.MenuName
            }
          })
        })
      } else {
        this.setState({
          menulist: []
        })
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
      }
    })
    this.setState({visible: true})
  }
  submit = () => {
    const { targetKeys } = this.state
    // 三级菜单解除冻结
    if (targetKeys.length === 0) {
      notification.warning({
        top: 92,
        message: this.state.dict['form.required.select'] + this.state.dict['model.menu'],
        duration: 5
      })
      return
    }
    this.setState({
      loading: true
    })
    let defers = targetKeys.map(item => {
      return new Promise((resolve) => {
        Api.getSystemConfig({
          func: 'sPC_MainMenu_ReDel',
          MenuID: item
        }).then(res => {
          if (res.status) {
            resolve('')
          } else {
            resolve(res.message)
          }
        })
      })
    })
    Promise.all(defers).then(res => {
      let msg = res.filter(Boolean)[0]
      if (msg) {
        notification.error({
          top: 92,
          message: msg,
          duration: 10
        })
      } else {
        this.setState({
          loading: false,
          visible: false,
          targetKeys: [],
          thawmenulist: null
        })
        MKEmitter.emit('mkUpdateMenuList')
      }
    })
  }
  render() {
    const { visible, menulist, loading } = this.state
    return (
      <>
        <UnlockOutlined onClick={this.trigger} style={{color: 'orange'}}/>
        <Modal
          title="解冻菜单"
          visible={visible}
          width={600}
          onOk={this.submit}
          confirmLoading={loading}
          onCancel={() => this.setState({visible: false})}
          destroyOnClose
        >
          {!menulist ?
            <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" /> :
            <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={menulist}/>
          }
        </Modal>
      </>
    )
  }
}
export default ThawMenu
src/components/thawmenu/index.scss
src/locales/en-US/model.js
@@ -41,7 +41,6 @@
  'model.menu.level1': 'Level 1 menu',
  'model.menu.level2': 'Level 2 menu',
  'model.menu.level3': 'Level 3 menu',
  'model.menu.close': 'Are you sure to delete the menu <<@M>> ?',
  'model.menu.resetorder': 'Are you sure to adjust the menu sequence ?',
  'model.menu.basemsg': 'Please complete the basic information !',
  'header.menu.basedata': 'The basic information',
src/locales/zh-CN/model.js
@@ -41,7 +41,6 @@
  'model.menu.level1': '一级菜单',
  'model.menu.level2': '二级菜单',
  'model.menu.level3': '三级菜单',
  'model.menu.close': '确定删除《@M》菜单吗?',
  'model.menu.resetorder': '确认调整菜单顺序吗?',
  'model.menu.basemsg': '请完善菜单基本信息!',
  'header.menu.basedata': '基本信息',
src/menu/components/form/dragtitle/card.jsx
@@ -33,7 +33,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const close = () => {
    closeCard(id)
src/menu/components/search/main-search/dragsearch/card.jsx
@@ -32,7 +32,7 @@
      moveCard(draggedId, overIndex)
    },
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  let _defaultValue = '' // 下拉搜索、时间范围类型,初始值需要预处理
src/menu/components/share/actioncomponent/dragaction/card.jsx
@@ -28,7 +28,7 @@
      moveCard(draggedId, overIndex)
    },
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  let hasProfile = false
  if (['pop', 'prompt', 'exec'].includes(card.OpenType)) {
src/menu/components/share/clockcomponent/index.jsx
@@ -33,7 +33,7 @@
      this.setState({
        visible: false
      })
      this.props.updateConfig({...config, timer: res.timer, clearField: res.clearField || '', clearValue: res.clearValue || ''})
      this.props.updateConfig({...config, timer: res.timer, timerRepeats: res.timerRepeats, clearField: res.clearField || '', clearValue: res.clearValue || ''})
    })
  }
src/menu/components/share/clockcomponent/settingform/index.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Select, Tooltip, Input } from 'antd'
import { Form, Row, Col, Select, Tooltip, Input, InputNumber } from 'antd'
import { QuestionCircleOutlined } from '@ant-design/icons'
import './index.scss'
@@ -69,6 +69,18 @@
                )}
              </Form.Item>
            </Col>
            {timer ? <Col span={22}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="定时器执行次数。注:0表示没有限制。">
                  <QuestionCircleOutlined className="mk-form-tip" />
                  执行次数
                </Tooltip>
              }>
                {getFieldDecorator('timerRepeats', {
                  initialValue: config.timerRepeats || 0,
                })(<InputNumber min={0} max={500} precision={0} />)}
              </Form.Item>
            </Col> : null}
            {(config.subtype === 'balcony' || config.subtype === 'propcard') && timer ? <Col span={22}>
              <Form.Item label={
                <Tooltip placement="topLeft" title="可以指定字段用于控制定时器的关闭。">
src/menu/components/share/searchcomponent/dragsearch/card.jsx
@@ -31,7 +31,7 @@
      moveCard(draggedId, overIndex)
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  let _defaultValue = '' // 下拉搜索、时间范围类型,初始值需要预处理
src/mob/components/formdragelement/card.jsx
@@ -34,7 +34,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/mob/searchconfig/groupdragelement/card.jsx
@@ -26,7 +26,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/mob/searchconfig/searchdragelement/card.jsx
@@ -31,7 +31,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/router/index.js
@@ -22,6 +22,7 @@
const PrintT = asyncLoadComponent(() => import('@/views/printTemplate'))
const Interface = asyncLoadComponent(() => import('@/views/interface'))
const RoleManage = asyncLoadComponent(() => import('@/views/rolemanage'))
const SystemFunc = asyncLoadComponent(() => import('@/views/systemfunc'))
const routers = [
  {path: '/login', name: 'login', component: Login, auth: false},
@@ -41,6 +42,7 @@
  {path: '/docprint/:menuId/:id', name: 'docprint', component: BillPrint, auth: false},
  {path: '/paramsmain/:param', name: 'pmain', component: Main, auth: true},
  {path: '/role/:param', name: 'role', component: RoleManage, auth: true},
  {path: '/hs', name: 'hs', component: SystemFunc, auth: true},
  {path: '/interface', name: 'interface', component: Interface, auth: true}
]
src/templates/formtabconfig/dragelement/card.jsx
@@ -31,7 +31,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/templates/modalconfig/dragelement/card.jsx
@@ -38,7 +38,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/templates/sharecomponent/actioncomponent/dragaction/card.jsx
@@ -26,7 +26,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  let hasProfile = false
  let forbidSql = false
src/templates/sharecomponent/cardcomponent/dragdetail/card.jsx
@@ -14,7 +14,7 @@
    }),
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const [, drop] = useDrop({
    accept: 'detail',
src/templates/sharecomponent/chartgroupcomponent/dragchartview/card.jsx
@@ -16,7 +16,7 @@
    }),
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/templates/sharecomponent/columncomponent/dragcolumn/card.jsx
@@ -27,7 +27,7 @@
    }
  })
  
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  return (
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
src/templates/sharecomponent/searchcomponent/dragsearch/card.jsx
@@ -34,7 +34,7 @@
      }
    }
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  let _defaultValue = '' // 下拉搜索、时间范围类型,初始值需要预处理
src/templates/sharecomponent/tabscomponent/tabdragelement/card.jsx
@@ -41,7 +41,7 @@
    delCard(id)
  }
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  return (
    <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
src/views/design/header/editfirstmenu/dragelement/card.jsx
@@ -23,7 +23,7 @@
      }
    },
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/views/design/header/editfirstmenu/dragelement/index.jsx
@@ -1,14 +1,13 @@
import React, { useState } from 'react'
import { useDrop } from 'react-dnd'
import { Button } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import { is, fromJS } from 'immutable'
import update from 'immutability-helper'
import Card from './card'
import ItemTypes from './itemtypes'
import './index.scss'
const Container = ({dict, list, handlePreviewList, handleMenu, deleteMemu, handleButton }) => {
const Container = ({change, list, handlePreviewList, handleMenu, deleteMemu, handleButton }) => {
  const [cards, setCards] = useState(list)
  const moveCard = (id, atIndex) => {
    const { card, index } = findCard(id)
@@ -43,20 +42,12 @@
    deleteMemu(card)
  }
  const add = () => {
    handleButton('add')
  }
  const confirm = () => {
    handleButton('confirm')
  }
  const cancel = () => {
    handleButton('cancel')
  }
  const thawmenu = () => {
    handleButton('thawmenu')
  }
  const [, drop] = useDrop({ accept: ItemTypes.CARD })
@@ -73,12 +64,8 @@
          findCard={findCard}
        />
      ))}
      <div className="card-add" onClick={add}>
        <PlusOutlined />
      </div>
      <Button type="primary" onClick={thawmenu}>{dict['model.thaw'] + dict['model.menu']}</Button>
      <Button type="primary" onClick={confirm}>{dict['model.confirm']}</Button>
      <Button onClick={cancel}>{dict['model.close']}</Button>
      <Button type="primary" disabled={!change} onClick={confirm}>保存</Button>
      <Button onClick={cancel}>关闭</Button>
    </div>
  )
}
src/views/design/header/editfirstmenu/dragelement/index.scss
@@ -5,28 +5,24 @@
  float: left;
  background: #001529;
  padding-bottom: 5px;
  .card-add {
    border: 1px dashed gray;
    padding: 4px;
    margin-top: 9px;
    margin-left: 10px;
    width: 50px;
    float: left;
    text-align: center;
    cursor: pointer;
  }
  button {
    margin-top: 14px;
    margin-left: 10px;
    padding: 0 10px;
    height: 26px;
  }
  .ant-btn-primary[disabled] {
    background-color: #f5f5f5 !important;
    border-color: #d9d9d9 !important;
    color: rgba(0, 0, 0, 0.35) !important;
  }
  .btn-group {
    display: inline-block;
  }
  .card {
    position: relative;
    border: 1px dashed gray;
    border: 1px dashed #535353;
    margin-top: 8px;
    margin-right: 5px;
    float: left;
src/views/design/header/editfirstmenu/index.jsx
@@ -3,23 +3,14 @@
import { is, fromJS } from 'immutable'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
import { notification, Modal, Spin } from 'antd'
import { notification, Modal } from 'antd'
import moment from 'moment'
import TransferForm from '@/templates/zshare/basetransferform'
import DragElement from './dragelement'
import MenuForm from './menuform'
import Utils from '@/utils/utils.js'
import zhCN from '@/locales/zh-CN/model.js'
import enUS from '@/locales/en-US/model.js'
import Api from '@/api'
import './index.scss'
import card1 from '@/assets/img/card-bg2.jpg'
import card2 from '@/assets/img/card-bg5.jpg'
import card3 from '@/assets/img/card-bg8.jpg'
import card4 from '@/assets/img/card-bg7.jpg'
import card5 from '@/assets/img/card-bg6.jpg'
const { confirm } = Modal
@@ -31,20 +22,16 @@
  }
  state = {
    thawmenulist: null, // 已冻结的一级菜单
    addMvisible: null,
    menulist: null,
    editMenu: null, // 编辑菜单
    editMvisible: false, // 编辑菜单模态框
    thawMvisible: false, // 解除冻结模态框
    confirmLoading: false, // 提交中。。。
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    targetKeys: [] // 解冻菜单列表
    editMenu: null,  // 编辑菜单
    visible: false,  // 编辑菜单模态框
    loading: false,  // 提交中。。。
    change: false
  }
  handlePreviewList = (List) => {
    // 菜单顺序改变时,保存中间状态
    this.setState({menulist: List})
    this.setState({menulist: List, change: !is(fromJS(List), fromJS(this.props.menulist))})
  }
  editMenuModal = (Menu) => {
@@ -53,13 +40,14 @@
    if (!is(fromJS(this.state.menulist), fromJS(this.props.menulist))) {
      notification.warning({
        top: 92,
        message: this.state.dict['model.menu.presave'],
        message: '菜单顺序已调整,请保存!',
        duration: 5
      })
    } else {
      this.setState({
        editMvisible: true,
        editMenu: menu.card
        visible: true,
        editMenu: menu.card,
        loading: false
      })
    }
  }
@@ -69,19 +57,19 @@
    this.editMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Upt'
      this.setState({
        confirmLoading: true
        loading: true
      })
      Api.getSystemConfig(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            editMvisible: false,
            loading: false,
            visible: false,
            editMenu: null
          })
          this.props.reload()
        } else {
          this.setState({
            confirmLoading: false
            loading: false
          })
          notification.warning({
            top: 92,
@@ -91,58 +79,12 @@
        }
      })
    }, () => {})
  }
  editMemuCancel = () => {
    // 编辑菜单:取消
    this.setState({
      confirmLoading: false,
      editMvisible: false,
      editMenu: null
    })
  }
  addMemuSubmit = () => {
    // 新建菜单:提交
    this.addMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Add'
      param.Sort = (this.props.menulist.length + 1) * 10
      this.setState({
        confirmLoading: true
      })
      Api.getSystemConfig(param).then(res => {
        if (res.status) {
          this.setState({
            confirmLoading: false,
            addMvisible: false,
          })
          this.props.reload()
        } else {
          this.setState({
            confirmLoading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
      })
    }, () => {})
  }
  addMemuCancel = () => {
    // 新建菜单:取消
    this.setState({
      confirmLoading: false,
      addMvisible: false
    })
  }
  deleteMemu = (item) => {
    let _this = this
    confirm({
      title: this.state.dict['model.menu.close'].replace('@M', item.MenuName),
      title: `确定删除菜单《${item.MenuName}》吗?`,
      content: '',
      onOk() {
        let param = {
@@ -164,79 +106,12 @@
      onCancel() {}
    })
  }
  thawMemuSubmit = () => {
    const { targetKeys } = this.state
    if (targetKeys.length === 0) {
      notification.warning({
        top: 92,
        message: this.state.dict['form.required.select'] + this.state.dict['model.menu'],
        duration: 5
      })
    } else {
      this.setState({
        confirmLoading: true
      })
      let defers = targetKeys.map(item => {
        return new Promise((resolve) => {
          Api.getSystemConfig({
            func: 'sPC_MainMenu_ReDel',
            MenuID: item
          }).then(res => {
            if (res.status) {
              resolve('')
            } else {
              resolve(res.message)
            }
          })
        })
      })
      Promise.all(defers).then(res => {
        let msg = res.filter(Boolean)[0]
        if (msg) {
          notification.error({
            top: 92,
            message: msg,
            duration: 10
          })
        } else {
          this.setState({
            confirmLoading: false,
            thawMvisible: false,
            targetKeys: [],
            thawmenulist: null
          })
          this.props.reload()
        }
      })
    }
  }
  thawMemuCancel = () => {
    this.setState({
      thawMvisible: false,
      targetKeys: [],
      thawmenulist: null
    })
  }
  
  handleButton = (type) => {
    // 菜单编辑:添加,确定,取消
    let _menuchange = !is(fromJS(this.state.menulist), fromJS(this.props.menulist))
    if ((type === 'add' || type === 'thawmenu') && _menuchange) {
      notification.warning({
        top: 92,
        message: this.state.dict['model.menu.presave'],
        duration: 5
      })
    } else if (type === 'add') {
      this.setState({
        addMvisible: true
      })
    } else if (type === 'confirm' && _menuchange) {
    if (type === 'confirm' && _menuchange) {
      let _this = this
      let param  = {
        func: 'sPC_Menu_SortUpt',
@@ -251,7 +126,7 @@
      param.secretkey = Utils.encrypt(param.LText, param.timestamp) // md5密钥
      confirm({
        title: this.state.dict['model.menu.resetorder'],
        title: '确认调整菜单顺序吗?',
        content: '',
        onOk() {
          return Api.getSystemConfig(param).then(res => {
@@ -279,33 +154,6 @@
        },
        onCancel() {}
      })
    } else if (type === 'thawmenu') {
      this.setState({
        thawMvisible: true,
        targetKeys: []
      })
      Api.getSystemConfig({
        func: 'sPC_Get_FrozenMenu',
        ParentID: '0',
        TYPE: 10
      }).then(res => {
        if (res.status) {
          this.setState({
            thawmenulist: res.data.map(menu => {
              return {
                key: menu.MenuID,
                title: menu.MenuName
              }
            })
          })
        } else {
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
      })
    } else {
      this.props.exitEdit()
    }
@@ -317,38 +165,18 @@
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.menulist), fromJS(nextProps.menulist))) {
      this.setState({menulist: fromJS(nextProps.menulist).toJS()})
      this.setState({menulist: fromJS(nextProps.menulist).toJS(), change: false})
    }
  }
  render () {
    const { dict, menulist } = this.state
    const { menulist, change } = this.state
    return (
      <div className="header-edit-box">
        <div className="mask">
          <div className="tipcard card1" style={{backgroundImage: 'url(' + card1 + ')'}}>
            拖动一级菜单可调整顺序,顺序调整后,请点击确定按钮保存。
          </div>
          <div className="tipcard card2" style={{backgroundImage: 'url(' + card2 + ')'}}>
            鼠标经过菜单时会显示编辑图标,点击编辑可修改和删除菜单。
          </div>
          <div className="tipcard card3" style={{backgroundImage: 'url(' + card3 + ')'}}>
            点击解除冻结按钮,可还原已删除的一级菜单。
          </div>
          <div className="tipcard card4" style={{backgroundImage: 'url(' + card4 + ')'}}>
            点击添加图标,可新增一级菜单。
          </div>
          <div className="tipcard card5" style={{backgroundImage: 'url(' + card5 + ')'}}>
            <p>编辑状态中,菜单之外区域会锁定,查看系统数据请点击。</p>
            <div>
              <span className="new-view" onClick={() => {window.open('#/main')}} >新页面</span>
            </div>
          </div>
        </div>
        <DndProvider backend={HTML5Backend}>
          <DragElement
            dict={dict}
            change={change}
            list={menulist}
            handlePreviewList={this.handlePreviewList}
            handleMenu={this.editMenuModal}
@@ -356,48 +184,16 @@
            handleButton={this.handleButton}
          />
        </DndProvider>
        {/* 新建菜单模态框 */}
        <Modal
          title={dict['model.add'] + dict['model.menu']}
          visible={this.state.addMvisible}
          onOk={this.addMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.addMemuCancel}
          destroyOnClose
        >
          <MenuForm
            dict={dict}
            type="add"
            menu={null}
            inputSubmit={this.addMemuSubmit}
            wrappedComponentRef={(inst) => this.addMenuFormRef = inst}
          />
        </Modal>
        {/* 解除冻结菜单模态框 */}
        <Modal
          title={dict['model.thaw'] + dict['model.menu']}
          visible={this.state.thawMvisible}
          width={600}
          onOk={this.thawMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.thawMemuCancel}
          destroyOnClose
        >
          {!this.state.thawmenulist && <Spin style={{marginLeft: 'calc(50% - 22px)', marginTop: '70px', marginBottom: '70px'}} size="large" />}
          {this.state.thawmenulist && <TransferForm onChange={(vals) => this.setState({targetKeys: vals})} menulist={this.state.thawmenulist}/>}
        </Modal>
        {/* 编辑菜单模态框 */}
        <Modal
          title={dict['model.edit'] + dict['model.menu']}
          visible={this.state.editMvisible}
          title="编辑菜单"
          visible={this.state.visible}
          onOk={this.editMemuSubmit}
          confirmLoading={this.state.confirmLoading}
          onCancel={this.editMemuCancel}
          confirmLoading={this.state.loading}
          onCancel={() => this.setState({visible: false})}
          destroyOnClose
        >
          <MenuForm
            dict={dict}
            type="edit"
            menu={this.state.editMenu}
            inputSubmit={this.editMemuSubmit}
            wrappedComponentRef={(inst) => this.editMenuFormRef = inst}
src/views/design/header/editfirstmenu/menuform/index.jsx
@@ -1,13 +1,13 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Form, Row, Col, Input, Select, Radio } from 'antd'
import { Form, Row, Col, Input, Radio } from 'antd'
import Utils from '@/utils/utils.js'
import './index.scss'
class MainSearch extends Component {
  static propTpyes = {
    menu: PropTypes.any,         // 菜单信息,新建时为null
    dict: PropTypes.object,      // 字典项
    type: PropTypes.string,      // 操作类型
    inputSubmit: PropTypes.func
  }
@@ -18,7 +18,7 @@
      {
        type: 'text',
        key: 'menuName',
        label: this.props.dict['model.menu'] + this.props.dict['model.name'],
        label: '菜单名称',
        initVal: '',
        required: true,
        readonly: false
@@ -26,12 +26,12 @@
      {
        type: 'radio',
        key: 'openType',
        label: this.props.dict['model.openway'],
        label: '打开方式',
        initVal: 'menu',
        required: true,
        options: [{
          id: 'menu',
          text: this.props.dict['model.menu']
          text: '菜单'
        }, {
          id: 'outpage',
          text: '外部页面'
@@ -51,7 +51,7 @@
  UNSAFE_componentWillMount () {
    const { menu } = this.props
    if (this.props.type === 'add') {
    if (!menu) {
      this.setState({
        formlist: this.state.defaultMenu
      })
@@ -113,14 +113,14 @@
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.input'] + item.label + '!'
                    message: '请输入' + item.label + '!'
                  }
                ]
              })(<Input placeholder="" autoFocus={item.key.toLowerCase() === 'menuname'} autoComplete="off" disabled={item.readonly} />)}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'select') { // 下拉搜索
      } else if (item.type === 'radio') {
        fields.push(
          <Col span={24} key={index}>
            <Form.Item label={item.label}>
@@ -129,34 +129,7 @@
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                  }
                ]
              })(
                <Select
                  showSearch
                  filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  onChange={(value) => {this.openTypeChange(item.key, value)}}
                  getPopupContainer={() => document.getElementById('first-menu-form-box')}
                >
                  {item.options.map(option =>
                    <Select.Option key={option.id} value={option.id}>{option.text}</Select.Option>
                  )}
                </Select>
              )}
            </Form.Item>
          </Col>
        )
      } else if (item.type === 'radio') { // 下拉搜索
        fields.push(
          <Col span={24} key={index}>
            <Form.Item label={item.label}>
              {getFieldDecorator(item.key, {
                initialValue: item.initVal || '',
                rules: [
                  {
                    required: !!item.required,
                    message: this.props.dict['form.required.select'] + item.label + '!'
                    message: '请选择' + item.label + '!'
                  }
                ]
              })(
@@ -180,31 +153,31 @@
  }
  handleConfirm = () => {
    const { menu } = this.props
    // 表单提交时检查输入值是否正确
    return new Promise((resolve, reject) => {
      this.props.form.validateFieldsAndScroll((err, values) => {
        if (!err) {
          if (this.props.type === 'add') {
            resolve({
              MenuID: Utils.getuuid(),
              MenuName: values.menuName,
              PageParam: JSON.stringify({
                OpenType: values.openType,
                linkUrl: values.openType !== 'menu' ? values.linkUrl : ''
              })
        if (err) return
        if (!menu) {
          resolve({
            MenuID: Utils.getuuid(),
            MenuName: values.menuName,
            PageParam: JSON.stringify({
              OpenType: values.openType,
              linkUrl: values.openType !== 'menu' ? values.linkUrl : ''
            })
          } else {
            resolve({
              MenuID: this.props.menu.MenuID,
              MenuName: values.menuName,
              PageParam: JSON.stringify({
                OpenType: values.openType,
                linkUrl: values.openType !== 'menu' ? values.linkUrl : ''
              })
            })
          }
          })
        } else {
          reject(err)
          resolve({
            MenuID: menu.MenuID,
            MenuName: values.menuName,
            PageParam: JSON.stringify({
              OpenType: values.openType,
              linkUrl: values.openType !== 'menu' ? values.linkUrl : ''
            })
          })
        }
      })
    })
src/views/design/header/index.jsx
@@ -2,8 +2,8 @@
import { withRouter } from 'react-router-dom'
import {connect} from 'react-redux'
import { is, fromJS } from 'immutable'
import { Dropdown, Menu, Modal, notification, Switch, Button } from 'antd'
import { MenuFoldOutlined, EditOutlined, AppstoreOutlined, DownOutlined, HomeOutlined, ApiOutlined } from '@ant-design/icons'
import { Dropdown, Menu, Modal, notification, Switch, Button, Popover } from 'antd'
import { MenuFoldOutlined, SettingOutlined, AppstoreOutlined, DownOutlined, HomeOutlined, ApiOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
import asyncComponent from '@/utils/asyncComponent'
import {
@@ -14,8 +14,6 @@
} from '@/store/action'
import Api from '@/api'
import options from '@/store/options.js'
import zhCN from '@/locales/zh-CN/main.js'
import enUS from '@/locales/en-US/main.js'
import Utils from '@/utils/utils.js'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
@@ -24,22 +22,25 @@
const EditMenu = asyncComponent(() => import('./editfirstmenu'))
const VersionsUp = asyncComponent(() => import('./versions'))
const ThawMenu = asyncComponent(() => import('@/components/thawmenu'))
const MenuForm = asyncComponent(() => import('./editfirstmenu/menuform'))
const { confirm } = Modal
class Header extends Component {
  state = {
    menulist: null, // 一级菜单
    dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
    userName: sessionStorage.getItem('CloudUserName'),
    avatar: Utils.getrealurl(sessionStorage.getItem('CloudAvatar')),
    memberLevel: Utils.getMemberLevel()
    memberLevel: Utils.getMemberLevel(),
    visible: false,
    loading: false
  }
  logout = () => {
    // 退出登录
    let _this = this
    confirm({
      title: this.state.dict['main.logout.hint'],
      title: '您确定要退出吗?',
      content: '',
      onOk() {
        sessionStorage.clear()
@@ -82,11 +83,7 @@
      if (window.GLOB.systemType !== 'production') { // 非正式系统选择第一项
        this.props.modifyMainMenu(menulist[0] || null)
      } else {
        this.props.resetEditLevel('HS')
        window.GLOB.mkHS = true
        this.props.modifyMainMenu({
          MenuID: 'systemManageView'
        })
      }
    } else {
      notification.error({
@@ -196,42 +193,42 @@
    // 进入编辑状态
    this.props.resetEditLevel('level1')
  }
  enterEditManage = () => {
    const { editLevel } = this.props
    if (editLevel === 'HS')  return
    window.GLOB.mkHS = true
    this.props.resetEditLevel('HS')
    this.props.modifyMainMenu({
      MenuID: 'systemManageView'
    })
  }
  /**
   * @description 退出管理界面菜单
   */
  exitManage = () => {
    const { menulist } = this.state
    if (window.GLOB.systemType === 'production') { // 正式系统版本升级后,页面刷新
      this.props.history.replace('/main')
      window.location.reload()
      return
    }
    this.props.modifyMainMenu(menulist[0] || null)
    this.props.resetEditLevel(false)
    window.GLOB.mkHS = false
    MKEmitter.emit('modifyTabs', null, 'replace')
  }
  
  exitEdit = () => {
    // 退出编辑状态
    this.props.resetEditLevel(false)
    window.GLOB.mkHS = false
  }
  addMemuSubmit = () => {
    // 新建菜单:提交
    this.addMenuFormRef.handleConfirm().then(param => {
      param.func = 'sPC_MainMenu_Add'
      param.Sort = (this.state.menulist.length + 1) * 10
      this.setState({
        loading: true
      })
      Api.getSystemConfig(param).then(res => {
        if (res.status) {
          this.setState({
            loading: false,
            visible: false,
          })
          this.loadmenu()
        } else {
          this.setState({
            loading: false
          })
          notification.warning({
            top: 92,
            message: res.message,
            duration: 5
          })
        }
      })
    }, () => {})
  }
  
  UNSAFE_componentWillMount () {
@@ -289,6 +286,7 @@
      this.reload()
    })
    MKEmitter.addListener('mkUpdateMenuList', this.reload)
  }
  shouldComponentUpdate (nextProps, nextState) {
@@ -302,6 +300,7 @@
    this.setState = () => {
      return
    }
    MKEmitter.removeListener('mkUpdateMenuList', this.reload)
  }
  gotoDoc = () => {
@@ -316,10 +315,10 @@
  render () {
    const { mainMenu, editLevel } = this.props
    const { menulist, memberLevel } = this.state
    const { menulist, memberLevel, visible, loading } = this.state
    return (
      <header className={'sys-header-container ant-menu-dark ' + (['level2', 'level3', 'HS'].includes(editLevel) ? 'mask' : '')} id="main-header-container">
      <header className={'sys-header-container ant-menu-dark ' + (['level2', 'level3'].includes(editLevel) ? 'mask' : '')} id="main-header-container">
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
        <div className="header-collapse">
          <MenuFoldOutlined/>
@@ -334,48 +333,46 @@
                </li>
              )
            })}
            {!editLevel || editLevel === 'HS' ?
              <li key="HS" onClick={this.enterEditManage} className={editLevel === 'HS' ? 'active' : ''}>
            {!editLevel ?
              <li key="HS" onClick={() => window.open('#/hs')}>
                <span>HS</span>
              </li> : null
            }
          </ul> : null
        }
        {editLevel === 'HS' ? <Button className="level4-close" type="primary" onClick={this.exitManage}>退出</Button> : null}
        {/* 进入编辑按钮 */}
        {!editLevel && menulist ? <EditOutlined onClick={this.enterEdit} className="edit-check" /> : null}
        {!editLevel && window.GLOB.systemType !== 'production' ?
          <div className="app-entrance entrance">
            <div className="icon"><AppstoreOutlined /></div>
            <div className="title">应用管理</div>
            <div className="detail">可创建及管理PC、pad及移动端等不同设备的应用,实现明科云APP、微信公众号、小程序等多平台的应用共享。</div>
        {!editLevel && window.GLOB.systemType !== 'production' && menulist ? <Popover overlayClassName="mk-popover-control-wrap mk-menu-control" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={
          <div className="mk-popover-control">
            <PlusOutlined onClick={() => this.setState({visible: true, loading: false})} className="mk-edit-menu"/>
            <SwapOutlined onClick={this.enterEdit} className="mk-edit-menu"/>
            <div style={{display: 'inline-block', minWidth: '32px'}}><ThawMenu ParentId="0" Type="10" className="mk-edit-menu"/></div>
          </div>
        } trigger="hover">
          <SettingOutlined className="edit-check"/>
        </Popover> : null}
        <div className="app-entrance entrance">
          <div className="icon"><AppstoreOutlined /></div>
          <div className="title">应用管理</div>
          <div className="detail">可创建及管理PC、pad及移动端等不同设备的应用,实现明科云APP、微信公众号、小程序等多平台的应用共享。</div>
          {window.GLOB.systemType !== 'production' ?
            <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/appmanage')}}>
              编辑
            </Button>
          </div> : null
        }
        {editLevel === 'HS' && window.GLOB.systemType === 'production' ?
          <div className="app-prod-entrance entrance">
            <div className="icon"><AppstoreOutlined /></div>
            <div className="title">应用管理</div>
            <div className="detail">可创建及管理PC、pad及移动端等不同设备的应用,实现明科云APP、微信公众号、小程序等多平台的应用共享。</div>
            </Button> :
            <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/appcheck')}}>
              查看
            </Button>
          </div> : null
        }
        {!editLevel ?
          <div className="api-entrance entrance">
            <div className="icon"><ApiOutlined /></div>
            <div className="title">接口调试</div>
            <div className="detail">可自动处理登录接口的参数加密,以及业务接口的签名计算,方便开发人员的接口测试工作。</div>
            <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/interface')}}>
              编辑
            </Button>
          </div> : null
        }
          }
        </div>
        <div className="api-entrance entrance">
          <div className="icon"><ApiOutlined /></div>
          <div className="title">接口调试</div>
          <div className="detail">可自动处理登录接口的参数加密,以及业务接口的签名计算,方便开发人员的接口测试工作。</div>
          <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/interface')}}>
            编辑
          </Button>
        </div>
        {/* window.btoa(window.encodeURIComponent(JSON.stringify({ MenuType: 'home', MenuId: 'home_page_id', MenuName: '首页' }))) */}
        {!editLevel && window.GLOB.systemType !== 'production' ?
        {window.GLOB.systemType !== 'production' ?
          <div className="home-entrance entrance">
            <div className="icon"><HomeOutlined /></div>
            <div className="title">首页</div>
@@ -391,14 +388,14 @@
        <Dropdown className="header-setting" overlay={
          <Menu className="header-dropdown">
            <Menu.Item key="switch">
              {this.state.dict['main.edit']}
              编辑
              <Switch size="small" style={{marginLeft: '7px'}} disabled={!!editLevel} checked={true} onChange={this.changeEditState} />
            </Menu.Item>
            <Menu.Item key="doc" onClick={this.gotoDoc}>{this.state.dict['main.doc']}</Menu.Item>
            <Menu.Item key="doc" onClick={this.gotoDoc}>文档中心</Menu.Item>
            {options.sysType !== 'cloud' ? <Menu.Item style={{padding: 0}} key="verup">
              <VersionsUp />
            </Menu.Item> : null}
            <Menu.Item key="logout" onClick={this.logout}>{this.state.dict['main.logout']}</Menu.Item>
            <Menu.Item key="logout" onClick={this.logout}>退出</Menu.Item>
          </Menu>
        }>
          <div style={{zIndex: 1, position: 'relative'}}>
@@ -408,6 +405,20 @@
            </span>
          </div>
        </Dropdown>
        <Modal
          title="添加菜单"
          visible={visible}
          onOk={this.addMemuSubmit}
          confirmLoading={loading}
          onCancel={() => this.setState({visible: false})}
          destroyOnClose
        >
          <MenuForm
            menu={null}
            inputSubmit={this.addMemuSubmit}
            wrappedComponentRef={(inst) => this.addMenuFormRef = inst}
          />
        </Modal>
      </header>
    )
  }
@@ -417,8 +428,7 @@
  return {
    menuTree: state.menuTree,
    mainMenu: state.mainMenu,
    editLevel: state.editLevel,
    permAction: state.permAction
    editLevel: state.editLevel
  }
}
src/views/design/header/index.scss
@@ -144,9 +144,6 @@
  .app-entrance {
    left: 900px;
  }
  .app-prod-entrance {
    left: 300px;
  }
  .entrance {
    position: absolute;
    top: 100px;
src/views/design/index.scss
@@ -16,4 +16,20 @@
  #mk-tabview-wrap.hastab + .sys-header-container .app-prod-entrance {
    display: none;
  }
}
.mk-popover-control-wrap {
  .anticon-plus {
    color: #26C281;
  }
  .anticon-swap {
    position: relative;
    z-index: 2;
    color: #1890ff;
  }
  .mk-swap {
    transform: rotate(90deg);
  }
}
.mk-menu-control.mk-popover-control-wrap {
  padding-bottom: 0px;
}
src/views/design/sidemenu/editsecmenu/index.jsx
@@ -65,7 +65,7 @@
      })
    } else if (menu.type === 'close') {
      confirm({
        title: dict['model.menu.close'].replace('@M', menu.card.MenuName),
        title: `确定删除菜单《${menu.card.MenuName}》吗?`,
        content: '',
        onOk() {
          let param = {
src/views/design/sidemenu/editthdmenu/index.jsx
@@ -118,7 +118,7 @@
      })
    } else if (menu.type === 'close') {
      confirm({
        title: this.state.dict['model.menu.close'].replace('@M', menu.card.MenuName),
        title: `确定删除菜单《${menu.card.MenuName}》吗?`,
        content: '',
        onOk() {
          let param = {
src/views/design/sidemenu/index.jsx
@@ -6,7 +6,6 @@
import asyncComponent from '@/utils/asyncComponent'
import { resetEditLevel, modifyMenuTree, modifyMainMenu } from '@/store/action'
import { SySMenuList } from './config'
import options from '@/store/options.js'
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
@@ -53,30 +52,6 @@
    })
  }
  enterManageView = () => {
    let menulist = SySMenuList
    if (window.GLOB.systemType === 'production') {
      menulist.forEach(menu => {
        menu.children = menu.children.filter(item => item.systems && item.systems.includes(window.GLOB.systemType))
      })
      menulist = menulist.filter(menu => menu.children.length > 0)
    } else {
      menulist.forEach(menu => {
        menu.children = menu.children.filter(item => !item.systems || item.systems.includes(options.sysType))
      })
      menulist = menulist.filter(menu => menu.children.length > 0)
    }
    this.setState({
      subMenulist: menulist,
      rootSubmenuKeys: menulist.map(item => item.MenuID),
      openKeys: [menulist[0].MenuID]
    })
  }
  changemenu(e, menu) {
    e.preventDefault()
    if (this.props.editLevel !== 'HS') {
@@ -95,9 +70,7 @@
  }
  UNSAFE_componentWillReceiveProps (nextProps) {
    if (!is(fromJS(this.props.mainMenu), fromJS(nextProps.mainMenu)) && nextProps.mainMenu && nextProps.mainMenu.MenuID === 'systemManageView') {
      this.enterManageView()
    } else if (!is(fromJS(this.props.mainMenu), fromJS(nextProps.mainMenu))) {
    if (!is(fromJS(this.props.mainMenu), fromJS(nextProps.mainMenu))) {
      // 主菜单切换,请求2、3级菜单数据
      this.loadsubmenu(nextProps.mainMenu)
    }
src/views/design/sidemenu/index.scss
@@ -123,23 +123,3 @@
    cursor: pointer;
  }
}
.mk-popover-control-wrap {
  .mk-edit-menu {
    font-size: 18px;
    cursor: pointer;
    padding: 10px 15px;
  }
  .anticon-plus.mk-edit-menu {
    color: #26C281;
  }
  .mk-edit-menu.mk-swap {
    color: #1890ff;
    transform: rotate(90deg);
  }
  .anticon-unlock.mk-edit-menu {
    color: orange;
  }
}
.mk-menu-control.mk-popover-control-wrap {
  padding-bottom: 0px;
}
src/views/design/sidemenu/menuelement/card.jsx
@@ -23,7 +23,7 @@
      }
    },
  })
  const opacity = isDragging ? 0 : 1
  const opacity = isDragging ? 0.5 : 1
  const edit = () => {
    editCard(id)
src/views/design/sidemenu/menuelement/index.scss
@@ -5,16 +5,7 @@
  float: left;
  background: #001529;
  padding-bottom: 5px;
  .card-add {
    border: 1px dashed gray;
    padding: 2px;
    margin-top: 13px;
    margin-left: 10px;
    width: 50px;
    float: left;
    text-align: center;
    cursor: pointer;
  }
  button {
    margin-top: 14px;
    margin-left: 10px;
src/views/interface/history/index.jsx
@@ -195,30 +195,42 @@
  }
  uselogon = () => {
    let baseurl = ''
    if (process.env.NODE_ENV === 'production') {
      baseurl = document.location.origin + '/' + window.GLOB.service
    } else {
      baseurl = window.GLOB.location + '/' + window.GLOB.service
    }
    let m = {
      active: 'raw',
      createDate: '',
      formData: [],
      headers: [],
      interface: 'dologon / logon',
      interface: baseurl + 'webapi/logon',
      method: 'POST',
      params: [],
      raw: "{\n \"UserName\":\"******\",\n \"Password\":\"******\",\n \"systemType\":\"local\",\n \"Type\":\"公钥\",\n \"privatekey\":\"私钥\",\n \"timestamp\":\"YYYY-MM-DD HH:mm:ss\",\n \"appkey\":\"******\"\n}",
      raw: "{\n \"UserName\":\"******\",\n \"Password\":\"******\",\n \"systemType\":\"local\",\n \"Type\":\"公钥\",\n \"privatekey\":\"私钥\",\n \"timestamp\":\"" + moment().format('YYYY-MM-DD HH:mm:ss') + "\",\n \"appkey\":\"" + window.GLOB.appkey + "\"\n}",
      uuid: 'dologon'
    }
    MKEmitter.emit('useInterface', m)
  }
  usedostars = () => {
    let baseurl = ''
    if (process.env.NODE_ENV === 'production') {
      baseurl = document.location.origin + '/' + window.GLOB.service
    } else {
      baseurl = window.GLOB.location + '/' + window.GLOB.service
    }
    let m = {
      active: 'raw',
      createDate: '',
      formData: [],
      headers: [],
      interface: 'dostars',
      interface: baseurl + 'webapi/dostars',
      method: 'POST',
      params: [],
      raw: "{\n \"LoginUID\":\"******\",\n \"UserID\":\"******\",\n \"func\":\"******\"\n}",
      raw: "{\n \"func\":\"******\",\n \"LoginUID\":\"******\",\n \"UserID\":\"******\",\n \"nonc\":\"" + Utils.getguid() + "\",\n \"t\":" + parseInt(new Date().getTime() / 1000) + "\n}",
      uuid: 'dologon'
    }
    MKEmitter.emit('useInterface', m)
@@ -269,7 +281,7 @@
            <div className="line-title">示例</div>
              <div className="line-item" key="dologon">
                <div className="method">POST</div>
                <div className="inter" style={{lineHeight: '40px'}}>dologon / logon</div>
                <div className="inter" style={{lineHeight: '40px'}}>logon</div>
                <div className="action" style={{paddingLeft: '40px'}}>
                  <RightOutlined onClick={this.uselogon} />
                </div>
src/views/interface/workspace/request/index.jsx
@@ -157,6 +157,7 @@
    } else if (/dostars/ig.test(url)) {
      if (n) {
        n = JSON.parse(n)
        n = this.encryptParam(n)
        n = JSON.stringify(n)
      }
@@ -205,8 +206,8 @@
    let keys = Object.keys(param).sort()
    let values = ''
    keys.forEach(key => {
      if (key.toLowerCase() === 'rduri') return
      if (key.toLowerCase() === 't' || key.toLowerCase() === 'sign' || param[key] === undefined) {
      if (key.toLowerCase() === 'rduri' || key === 't') return
      if (key.toLowerCase() === 'sign' || param[key] === undefined) {
        delete param[key]
        return
      }
@@ -220,6 +221,7 @@
        values += key + param[key]
      }
    })
    param.sign = md5(values)
    param.t = param.t || new Date().getTime()
src/views/systemfunc/header/index.jsx
New file
@@ -0,0 +1,47 @@
import React, {Component} from 'react'
import avatar from '@/assets/img/avatar.jpg'
import MainLogo from '@/assets/img/main-logo.png'
import './index.scss'
class Header extends Component {
  state = {
    userName: sessionStorage.getItem('CloudUserName'),
    avatar: sessionStorage.getItem('CloudAvatar') || avatar,
  }
  exitManage = () => {
    window.close()
  }
  UNSAFE_componentWillMount () {
  }
  /**
   * @description 组件销毁,清除state更新
   */
  componentWillUnmount () {
    this.setState = () => {
      return
    }
  }
  render () {
    return (
      <header className="sys-header-container ant-menu-dark">
        <div className="header-logo"><img src={MainLogo} alt=""/></div>
        <div className="title">HS</div>
        <div className="close" onClick={() => window.close()}>关闭</div>
        <div className="header-setting">
          <img src={this.state.avatar} alt=""/>
          <span>
            <span className="username">{this.state.userName}</span>
          </span>
        </div>
      </header>
    )
  }
}
export default Header
src/views/systemfunc/header/index.scss
New file
@@ -0,0 +1,66 @@
.sys-header-container {
  position: fixed;
  z-index: 22;
  left: 0;
  top: 0;
  font-weight: bold!important;
  width: 100%;
  height: 48px;
  .header-logo {
    float: left;
    width: 180px;
    line-height: 48px;
    text-align: center;
    padding-left: 5px;
    box-sizing: border-box;
    opacity: 1;
    transition: width 0.2s, opacity 0.15s;
    img {
      max-width: 100%;
      max-height: 40px;
    }
  }
  .title {
    position: absolute;
    font-size: 20px;
    color: #ffffff;
    left: calc(50% - 14px);
    top: 10px;
  }
  .close {
    position: absolute;
    font-size: 16px;
    color: #ffffff;
    right: 90px;
    top: 12px;
    cursor: pointer;
  }
  .header-setting {
    position: relative;
    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;
      }
    }
  }
}
src/views/systemfunc/index.jsx
New file
@@ -0,0 +1,34 @@
import React, {Component} from 'react'
import { ConfigProvider } from 'antd'
import enUS from 'antd/es/locale/en_US'
import zhCN from 'antd/es/locale/zh_CN'
import asyncComponent from '@/utils/asyncComponent'
import Header from './header'
import Sidemenu from './sidemenu'
import './index.scss'
const Tabview = asyncComponent(() => import('@/components/tabview'))
const _locale = sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS
class Design extends Component {
  UNSAFE_componentWillMount() {
    sessionStorage.setItem('isEditState', 'true')
    window.GLOB.mkHS = true
  }
  render () {
    return (
      <div className="mk-hs-view">
        <ConfigProvider locale={_locale}>
          <Sidemenu key="sidemenu"/>
          <Tabview key="tabview"/>
          <Header key="header"/>
        </ConfigProvider>
      </div>
    )
  }
}
export default Design
src/views/systemfunc/index.scss
New file
@@ -0,0 +1,5 @@
.mk-hs-view {
  display: flex;
  flex: auto;
  min-height: 100%;
}
src/views/systemfunc/sidemenu/config.jsx
src/views/systemfunc/sidemenu/index.jsx
New file
@@ -0,0 +1,89 @@
import React, {Component} from 'react'
import { Menu } from 'antd'
import { FolderOutlined } from '@ant-design/icons'
import { SySMenuList } from './config'
import options from '@/store/options.js'
import MKEmitter from '@/utils/events.js'
import './index.scss'
const { SubMenu } = Menu
class Sidemenu extends Component {
  state = {
    subMenulist: [],         // 二级菜单
    rootSubmenuKeys: [],
    openKeys: []
  }
  changemenu(e, menu) {
    e.preventDefault()
    MKEmitter.emit('modifyTabs', menu, 'plus')
  }
  componentDidMount () {
    let menulist = SySMenuList
    if (window.GLOB.systemType === 'production') {
      menulist.forEach(menu => {
        menu.children = menu.children.filter(item => item.systems && item.systems.includes(window.GLOB.systemType))
      })
      menulist = menulist.filter(menu => menu.children.length > 0)
    } else {
      menulist.forEach(menu => {
        menu.children = menu.children.filter(item => !item.systems || item.systems.includes(options.sysType))
      })
      menulist = menulist.filter(menu => menu.children.length > 0)
    }
    this.setState({
      subMenulist: menulist,
      rootSubmenuKeys: menulist.map(item => item.MenuID),
      openKeys: [menulist[0].MenuID]
    })
  }
  onOpenChange = openKeys => {
    const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1)
    if (this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
      this.setState({ openKeys })
    } else {
      this.setState({
        openKeys: latestOpenKey ? [latestOpenKey] : []
      })
    }
  }
  render () {
    return (
      <aside className="mk-sys-side-menu ant-menu-dark mk-edit">
        <Menu openKeys={this.state.openKeys} onOpenChange={this.onOpenChange} mode="inline" theme="dark">
        {this.state.subMenulist && this.state.subMenulist.map((item, index) => {
          return (
            <SubMenu
              key={item.MenuID}
              title={
                <span><FolderOutlined /> {item.MenuName}</span>
              }
            >
              {item.children.map(cell => {
                return (
                  <Menu.Item key={cell.MenuID}>
                    <a href={cell.src} id={cell.MenuID} onClick={(e) => this.changemenu(e, cell)}>{cell.MenuName}</a>
                  </Menu.Item>
                )
              })}
            </SubMenu>
          )
        })}
      </Menu>
      </aside>
    )
  }
}
export default Sidemenu
src/views/systemfunc/sidemenu/index.scss
New file
@@ -0,0 +1,123 @@
.mk-sys-side-menu {
  flex: 0 0 235px;
  width: 235px;
  padding: 48px 0 40px;
  transition: width 0.2s, flex 0.2s;
  .ant-menu-item {
    padding-left: 0!important;
    cursor: default;
    a {
      padding-left: 48px;
    }
    .editable-menu-item {
      display: block;
      padding-left: 48px;
      cursor: pointer;
    }
  }
  .ant-menu-sub.ant-menu-inline {
    position: relative;
  }
  .ant-menu-sub.ant-menu-inline > .ant-menu-item {
    height: 38px;
    line-height: 38px;
    margin: 0px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    a {
      display: inline-block;
    }
    .edit-check {
      top: -5px;
    }
  }
  .ant-menu-sub.ant-menu-inline > .ant-menu-item.ant-menu-item-active {
    background: #06b4f7;
  }
  .ant-menu-sub.ant-menu-inline > .ant-menu-item.ant-menu-item-selected {
    background: #06b4f7;
  }
  .ant-menu-inline .ant-menu-item {
    font-size: 1.1rem;
  }
  .ant-menu-dark.ant-menu-inline .ant-menu-submenu-title {
    margin: 0;
    height: 48px;
    line-height: 48px;
  }
  .ant-menu-dark.ant-menu-inline .ant-menu-submenu-open .ant-menu-submenu-title {
    background: #364150;
  }
  .edit-check {
    font-size: 18px;
    position: absolute;
    cursor: pointer;
    padding: 10px 15px;
    margin-right: 0px;
    right: 0px;
    top: 0px;
    :hover {
      color: #ffffff;
    }
  }
  .edit-control + .ant-menu-submenu-arrow {
    display: none;
  }
  .menu-add {
    position: relative;
    border: 1px dashed gray;
    margin: 8px 0px;
    height: 40px;
    line-height: 40px;
    width: 98%;
    clear: both;
    text-align: center;
    cursor: pointer;
    .anticon {
      font-size: 20px;
    }
  }
  .menu-btn {
    .ant-btn {
      padding: 0 10px;
      margin-left: 5px;
    }
  }
  .sup-menu {
    position: relative;
    z-index: 1;
  }
  .ant-menu-sub.ant-menu-inline .sub-menu {
    position: absolute;
    z-index: 1;
    width: 48px;
    left: 187px;
  }
}
.mk-sys-side-menu.mk-edit { // 编辑时控制菜单底色
  .ant-menu-sub.ant-menu-inline {
    > .ant-menu-item.ant-menu-item-selected {
      background: unset;
    }
    > .ant-menu-item.ant-menu-item-active {
      background: unset;
    }
  }
}
.ant-menu-submenu.ant-menu-submenu-popup {
  max-height: 80vh;
  overflow-y: scroll;
  &::-webkit-scrollbar {
    display: none;
  }
}
.ant-menu-vertical .ant-menu-item {
  cursor: default;
  height: 30px;
  line-height: 30px;
  a {
    cursor: pointer;
  }
}