| | |
| | | import React, {Component} from 'react' |
| | | import { withRouter } from 'react-router-dom' |
| | | import {connect} from 'react-redux' |
| | | import { is, fromJS } from 'immutable' |
| | | import { Dropdown, Menu, Modal, notification, Switch, Button, Popover } from 'antd' |
| | | import { MenuFoldOutlined, SettingOutlined, AppstoreOutlined, DownOutlined, HomeOutlined, ApiOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons' |
| | | import { MenuFoldOutlined, SettingOutlined, AppstoreOutlined, DownOutlined, HomeOutlined, ApiOutlined, PlusOutlined, EditOutlined, MenuOutlined, DatabaseOutlined } from '@ant-design/icons' |
| | | import moment from 'moment' |
| | | |
| | | import asyncComponent from '@/utils/asyncComponent' |
| | | import { |
| | |
| | | |
| | | changeMenu (value) { |
| | | // 主菜单切换 |
| | | if (this.props.editLevel) { |
| | | // 编辑状态下,不可切换菜单 |
| | | return |
| | | } |
| | | if (value.PageParam.OpenType === 'menu') { |
| | | this.props.modifyMainMenu(value) |
| | | } else if (value.PageParam.OpenType === 'outpage') { |
| | |
| | | |
| | | async loadmenu () { |
| | | // 获取主菜单 |
| | | let _param = {func: 's_get_pc_menus', systemType: options.sysType, debug: 'Y'} |
| | | _param.pro_sys = window.GLOB.systemType === 'production' ? 'Y' : '' |
| | | let _param = { |
| | | func: 's_get_pc_menus', |
| | | systemType: options.sysType, |
| | | pro_sys: window.GLOB.systemType === 'production' ? 'Y' : '', |
| | | debug: 'Y' |
| | | } |
| | | |
| | | let result = await Api.getSystemConfig(_param) |
| | | |
| | |
| | | |
| | | this.setState({ menulist }) |
| | | |
| | | this.props.modifyMenuTree(menulist) |
| | | if (window.GLOB.systemType !== 'production') { // 非正式系统选择第一项 |
| | | this.props.modifyMainMenu(menulist[0] || null) |
| | | } else { |
| | | let mainMenu = menulist[0] || null |
| | | |
| | | if (this.props.editLevel === 'level1') { |
| | | mainMenu = null |
| | | } else if (this.props.mainMenu && this.props.mainMenu.MenuID) { |
| | | let _menu = menulist.filter(item => item.MenuID === this.props.mainMenu.MenuID)[0] |
| | | mainMenu = _menu || mainMenu |
| | | |
| | | if (!_menu && (this.props.editLevel === 'level2' || this.props.editLevel === 'level3')) { |
| | | this.props.resetEditLevel(false) |
| | | } |
| | | } |
| | | |
| | | this.props.modifyMenuTree(menulist) |
| | | this.props.modifyMainMenu(mainMenu) |
| | | } else { |
| | | notification.error({ |
| | | top: 92, |
| | |
| | | } |
| | | |
| | | getMenulist = (result) => { |
| | | let iframes = ['Main/Index', 'bda/rdt', 'Home/rdt'] |
| | | let menulist = [] |
| | | let thdMenuList = [] |
| | | result.fst_menu && result.fst_menu.forEach(fst => { |
| | |
| | | MenuID: snd.MenuID, |
| | | MenuName: snd.MenuName, |
| | | PageParam: {Icon: 'folder'}, |
| | | children: [] |
| | | children: [], |
| | | level: 'second' |
| | | } |
| | | |
| | | if (snd.PageParam) { |
| | |
| | | MenuNo: trd.MenuNo, |
| | | EasyCode: trd.EasyCode, |
| | | type: 'CommonTable', // 默认值为常用表 |
| | | OpenType: 'newtab' // 打开方式 |
| | | OpenType: 'newtab', // 打开方式 |
| | | level: 'third' |
| | | } |
| | | |
| | | if (trd.LinkUrl && iframes.includes(trd.LinkUrl.split('?')[0])) { |
| | | trdItem.type = 'iframe' |
| | | trdItem.LinkUrl = trd.LinkUrl.replace('&', '&') |
| | | trdItem.forbidden = true |
| | | } else { |
| | | try { |
| | | trdItem.PageParam = trd.PageParam ? JSON.parse(trd.PageParam) : {OpenType: 'newtab'} |
| | | } catch (e) { |
| | | trdItem.PageParam = {OpenType: 'newtab'} |
| | | } |
| | | try { |
| | | trdItem.PageParam = trd.PageParam ? JSON.parse(trd.PageParam) : {OpenType: 'newtab'} |
| | | |
| | | trdItem.type = trdItem.PageParam.Template || trdItem.type |
| | | trdItem.OpenType = trdItem.PageParam.OpenType || trdItem.OpenType |
| | | trdItem.OpenType = trdItem.PageParam.OpenType |
| | | } catch (e) { |
| | | trdItem.PageParam = {OpenType: 'newtab'} |
| | | } |
| | | |
| | | if (trdItem.type === 'CustomPage' && this.state.memberLevel < 20) { // 会员等级大于等于20时,有编辑权限 |
| | | trdItem.forbidden = true |
| | | } |
| | | if (trdItem.type === 'CustomPage' && this.state.memberLevel < 20) { // 会员等级大于等于20时,有编辑权限 |
| | | trdItem.forbidden = true |
| | | } |
| | | |
| | | thdMenuList.push(trdItem) |
| | |
| | | enterEdit = () => { |
| | | // 进入编辑状态 |
| | | this.props.resetEditLevel('level1') |
| | | this.props.modifyMainMenu(null) |
| | | } |
| | | |
| | | exitEdit = () => { |
| | | // 退出编辑状态 |
| | | this.props.resetEditLevel(false) |
| | | this.props.modifyMainMenu(this.state.menulist[0] || null) |
| | | } |
| | | |
| | | |
| | | addMemuSubmit = () => { |
| | | // 新建菜单:提交 |
| | | this.addMenuFormRef.handleConfirm().then(param => { |
| | |
| | | }) |
| | | }, () => {}) |
| | | } |
| | | |
| | | setSystemFuncs = () => { |
| | | if (!window.GLOB.IndexDB) { |
| | | return |
| | | } |
| | | this.getfuncTime().then(res => { |
| | | Api.getSystemFuncs(res.createDate).then(result => { |
| | | if (!result.status) { |
| | | notification.error({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 10 |
| | | }) |
| | | } else if (result.func_detail && result.func_detail.length > 0) { |
| | | this.writeFuncs(result.func_detail) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | writeFuncs = (funcs) => { |
| | | let shim = +sessionStorage.getItem('sys_time_shim') |
| | | let timestamp = moment().add(shim, 'seconds').format('YYYY-MM-DD HH:mm:ss') |
| | | |
| | | // if (window.GLOB.WebSql) { |
| | | // window.GLOB.WebSql.transaction(tx => { |
| | | // tx.executeSql('DELETE FROM FUNCS') |
| | | |
| | | // funcs.forEach(item => { |
| | | // if (!item.key_sql) return |
| | | // tx.executeSql('INSERT INTO FUNCS (func_code, key_sql) VALUES (?, ?)', [item.func_code, item.key_sql]) |
| | | // }) |
| | | // tx.executeSql(`UPDATE VERSIONS SET createDate='${timestamp}' where CDefine1='funcs'`) |
| | | // }) |
| | | // } else { |
| | | let objectStore = window.GLOB.IndexDB.transaction(['funcs'], 'readwrite').objectStore('funcs') |
| | | |
| | | objectStore.clear() |
| | | |
| | | funcs.forEach(item => { |
| | | if (!item.key_sql) return |
| | | item.id = item.func_code |
| | | objectStore.add(item) |
| | | }) |
| | | |
| | | let funcStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') |
| | | funcStore.put({id: 'funcs', version: '1.0', createDate: timestamp}) |
| | | // } |
| | | } |
| | | |
| | | getfuncTime = () => { |
| | | return new Promise((resolve, reject) => { |
| | | // if (window.GLOB.WebSql) { |
| | | // window.GLOB.WebSql.transaction(tx => { |
| | | // tx.executeSql("SELECT * FROM VERSIONS where CDefine1='funcs'", [], (tx, results) => { |
| | | // let rows = results.rows |
| | | // if (rows.length === 0) { |
| | | // tx.executeSql('DELETE FROM FUNCS') |
| | | // tx.executeSql('INSERT INTO VERSIONS (version, createDate, CDefine1) VALUES (?, ?, ?)', ['1.0', '1970-01-01 14:59:09.000', 'funcs']) |
| | | // resolve({createDate: '1970-01-01 14:59:09.000'}) |
| | | // } else { |
| | | // resolve(rows[0]) |
| | | // } |
| | | // }, (tx, results) => { |
| | | // reject() |
| | | // console.warn(results) |
| | | // }) |
| | | // }) |
| | | // } else { |
| | | let objectStore = window.GLOB.IndexDB.transaction(['version'], 'readwrite').objectStore('version') |
| | | let request = objectStore.get('funcs') |
| | | |
| | | request.onerror = (event) => { |
| | | console.warn(event) |
| | | reject() |
| | | } |
| | | |
| | | request.onsuccess = () => { |
| | | if (request.result) { |
| | | resolve(request.result) |
| | | } else { |
| | | let add = objectStore.add({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) |
| | | |
| | | add.onerror = () => { |
| | | reject() |
| | | } |
| | | add.onsuccess = () => { |
| | | resolve({id: 'funcs', version: '1.0', createDate: '1970-01-01 14:59:09.000'}) |
| | | } |
| | | } |
| | | } |
| | | // } |
| | | }) |
| | | } |
| | | |
| | | getSmStemp = () => { |
| | | if (!sessionStorage.getItem('msgTemplate')) { |
| | | let _sql = `select ID,TemplateCode,SignName+'_'+describe as SignName from (select * from bd_msn_sms_temp where deleted=0 and status=20 ) a |
| | | inner join (select openid from sapp where id='${window.GLOB.appkey}') b |
| | | on a.openid=b.openid` |
| | | |
| | | _sql = Utils.formatOptions(_sql) |
| | | |
| | | let param = { |
| | | func: 'sPC_Get_SelectedList', |
| | | LText: _sql, |
| | | obj_name: 'data', |
| | | arr_field: 'ID,TemplateCode,SignName' |
| | | } |
| | | |
| | | param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') |
| | | param.secretkey = Utils.encrypt(param.LText, param.timestamp) |
| | | param.open_key = Utils.encryptOpenKey(param.secretkey, param.timestamp) // 云端数据验证 |
| | | |
| | | Api.getSystemConfig(param).then(res => { |
| | | let msgs = [] |
| | | if (!res.status) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: res.message, |
| | | duration: 5 |
| | | }) |
| | | } else if (res.data) { |
| | | msgs = res.data |
| | | } |
| | | sessionStorage.setItem('msgTemplate', JSON.stringify(msgs)) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | sessionStorage.setItem('isEditState', 'true') |
| | |
| | | this.loadmenu() |
| | | } |
| | | |
| | | UNSAFE_componentWillReceiveProps (nextProps) { |
| | | if (!is(fromJS(this.props.menuTree), fromJS(nextProps.menuTree)) && !is(fromJS(this.state.menulist), fromJS(nextProps.menuTree))) { |
| | | this.setState({ |
| | | menulist: nextProps.menuTree |
| | | }) |
| | | } |
| | | } |
| | | |
| | | componentDidMount () { |
| | | window.addEventListener('storage', (e) => { |
| | | if (e.key === 'menuUpdate') { |
| | | this.reload() |
| | | } else if (e.key === 'wxTemplates') { |
| | | if (e.newValue) { |
| | | sessionStorage.setItem('wxTemplates', e.newValue) |
| | | } |
| | | } |
| | | }) |
| | | MKEmitter.addListener('mkUpdateMenuList', this.reload) |
| | | |
| | | if (window.GLOB.systemType !== 'production') { |
| | | setTimeout(() => { |
| | | Api.getSystemConfig({func: 'sPC_Get_Roles_sModular'}).then(res => { |
| | |
| | | sessionStorage.setItem('permFuncField', JSON.stringify(_permFuncField)) |
| | | } |
| | | }) |
| | | }, 50) |
| | | }, 100) |
| | | |
| | | setTimeout(() => { |
| | | this.setSystemFuncs() |
| | | this.getSmStemp() |
| | | }, 500) |
| | | } |
| | | |
| | | window.addEventListener('storage', (e) => { |
| | | if (e.key !== 'menuUpdate') return |
| | | |
| | | this.reload() |
| | | }) |
| | | MKEmitter.addListener('mkUpdateMenuList', this.reload) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | /** |
| | |
| | | {/* 进入编辑按钮 */} |
| | | {!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> |
| | | <PlusOutlined onClick={() => this.setState({visible: true, loading: false})}/> |
| | | <EditOutlined onClick={this.enterEdit}/> |
| | | <div style={{display: 'inline-block', minWidth: '32px'}}><ThawMenu ParentId="0" Type="10"/></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> : |
| | | <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/appcheck')}}> |
| | | 查看 |
| | | </Button> |
| | | } |
| | | </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: '首页' }))) */} |
| | | {window.GLOB.systemType !== 'production' ? |
| | | <div className="home-entrance entrance"> |
| | | <div className="icon"><HomeOutlined /></div> |
| | | <div className="title">首页</div> |
| | | <div className="detail">基于自定义页面的首页设计,可实现灵活的元素配置及样式调整,展现当前系统的风格。</div> |
| | | <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/menudesign/JTdCJTIyTWVudVR5cGUlMjIlM0ElMjJob21lJTIyJTJDJTIyTWVudUlkJTIyJTNBJTIyaG9tZV9wYWdlX2lkJTIyJTJDJTIyTWVudU5hbWUlMjIlM0ElMjIlRTklQTYlOTYlRTklQTElQjUlMjIlN0Q=')}}> |
| | | <div className="entrance-wrap"> |
| | | {window.GLOB.systemType !== 'production' ? |
| | | <div className="entrance"> |
| | | <div className="icon"><HomeOutlined /></div> |
| | | <div className="title">首页</div> |
| | | <div className="detail">基于自定义页面的首页设计,可实现灵活的元素配置及样式调整,展现当前系统的风格。</div> |
| | | <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/menudesign/JTdCJTIyTWVudVR5cGUlMjIlM0ElMjJob21lJTIyJTJDJTIyTWVudUlkJTIyJTNBJTIyaG9tZV9wYWdlX2lkJTIyJTJDJTIyTWVudU5hbWUlMjIlM0ElMjIlRTklQTYlOTYlRTklQTElQjUlMjIlN0Q=')}}> |
| | | 编辑 |
| | | </Button> |
| | | </div> : null |
| | | } |
| | | <div className="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="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> : |
| | | <Button type="primary" disabled={!(memberLevel >= 20)} title={memberLevel >= 20 ? '' : '会员等级不够,无开发权限。'} onClick={() => {window.open('#/appcheck')}}> |
| | | 查看 |
| | | </Button> |
| | | } |
| | | </div> |
| | | {window.GLOB.systemType !== 'production' ? <div className="entrance"> |
| | | <div className="icon"><MenuOutlined /></div> |
| | | <div className="title">菜单操作说明</div> |
| | | <div className="detail">鼠标悬停 <SettingOutlined style={{color: '#1890ff'}}/> 可显示菜单的添加、排序(包括编辑、删除)与解冻功能,双击三级菜单可进入编辑窗口。</div> |
| | | <Button type="primary" onClick={() => {window.open('#/main')}}> |
| | | 新窗口 |
| | | </Button> |
| | | </div> : null} |
| | | {window.GLOB.systemType !== 'production' ? <div className="entrance"> |
| | | <div className="icon"><DatabaseOutlined /></div> |
| | | <div className="title">存储过程</div> |
| | | <div className="detail">可在页面中查看或编辑本地存储过程。</div> |
| | | <Button type="primary" onClick={() => {window.open('#/proc')}}> |
| | | 编辑 |
| | | </Button> |
| | | </div> : null} |
| | | </div> |
| | | {/* 编辑菜单 */} |
| | | {editLevel === 'level1' ? <EditMenu menulist={this.state.menulist} reload={this.reload} exitEdit={this.exitEdit}/> : null} |
| | | {/* 头像、用户名 */} |