src/api/cacheutils.js
@@ -306,6 +306,31 @@ } /** * @description 删除IndexedDB中保存的配置信息-批量 */ static delIndexDBConfig (keys) { if (!window.GLOB.IndexDB || !keys) return let objectStore = window.GLOB.IndexDB.transaction(['configs'], 'readwrite').objectStore('configs') objectStore.openCursor().onsuccess = (event) => { let cursor = event.target.result if (cursor) { if (cursor.value && keys.includes(cursor.value.menuid)) { let request = objectStore.delete(cursor.key) request.onerror = () => { window.GLOB.IndexDB = null } } cursor.continue() } } } /** * @description 获取IndexedDB中的配置信息 */ static getIndexDBMenuConfig (MenuID, userid) { src/api/index.js
@@ -274,14 +274,15 @@ clear = true } }) if (clear) { CacheUtils.clearWebSqlConfig() } else { let keys = res.menu_data.map(mid => `'${mid.menuid}'`).join(',') CacheUtils.delWebSqlConfig(keys) } } if (clear) { CacheUtils.clearWebSqlConfig() } else if (res.menu_data && res.menu_data.length > 0) { let keys = res.menu_data.map(mid => `'${mid.menuid}'`).join(',') CacheUtils.delWebSqlConfig(keys) } if (msg.version) { CacheUtils.updateWebSqlTime(curTime) } else { @@ -303,21 +304,33 @@ func: 's_get_app_version', modifydate: msg.createDate || curTime, } this.getSystemConfig(param).then(res => { if (!res.status) { reject() return } let clear = false let version = res.app_version || '1.00' appVersion.newVersion = version appVersion.oldVersion = appVersion.oldVersion || version if (res.menu_data && res.menu_data.length > 0) { CacheUtils.clearIndexDBConfig() res.menu_data.forEach(mid => { if (systemMenuKeys.indexOf(mid.menuid) > -1) { clear = true } }) if (clear) { CacheUtils.clearIndexDBConfig() } else if (res.menu_data && res.menu_data.length > 0) { let keys = res.menu_data.map(mid => `'${mid.menuid}'`) CacheUtils.delIndexDBConfig(keys) } } CacheUtils.updateIndexDBversion({version: version, createDate: curTime}) CacheUtils.updateIndexDBversion({version: appVersion.oldVersion, createDate: curTime}) resolve(appVersion) }) src/assets/css/viewstyle.scss
@@ -167,6 +167,13 @@ color: $color5; } } >.mk-breadview-wrap { >.ant-breadcrumb { .anticon-redo:hover, .anticon-home:hover { color: $color5; } } } } .custom-data-card-box, .custom-prop-card-box { .data-zoom.radio .card-row-list > .ant-col:not(.active):not(.selected):hover > .card-item-box, .data-zoom.checkbox .card-row-list > .ant-col:not(.active):not(.selected):hover > .card-item-box { src/components/Image/index.jsx
@@ -6,6 +6,8 @@ let Img = new Image() Img.src = this.props.url if (!this.ImageWrapDom) return if (Img.complete) { this.setSize(Img.width, Img.height) } else { src/components/breadview/index.jsx
New file @@ -0,0 +1,160 @@ import React, {Component} from 'react' import {connect} from 'react-redux' import { is, fromJS } from 'immutable' import { BackTop, Breadcrumb, Icon} from 'antd' import moment from 'moment' import 'moment/locale/zh-cn' import asyncComponent from '@/utils/asyncLoadComponent' import NotFount from '@/components/404' import mzhCN from '@/locales/zh-CN/main.js' import menUS from '@/locales/en-US/main.js' import MKEmitter from '@/utils/events.js' import './index.scss' const Home = asyncComponent(() => import('@/tabviews/home')) const CustomPage = asyncComponent(() => import('@/tabviews/custom')) const CommonTable = asyncComponent(() => import('@/tabviews/commontable')) const CalendarPage = asyncComponent(() => import('@/tabviews/calendar')) const TreePage = asyncComponent(() => import('@/tabviews/treepage')) const Iframe = asyncComponent(() => import('@/tabviews/iframe')) const RoleManage = asyncComponent(() => import('@/tabviews/rolemanage')) const FormTab = asyncComponent(() => import('@/tabviews/formtab')) let service = '' if (process.env.NODE_ENV === 'production') { service = document.location.origin + '/' + window.GLOB.service + 'zh-CN/' } else { service = window.GLOB.location + '/' + window.GLOB.service + 'zh-CN/' } class BreadView extends Component { state = { tabview: null, // 标签 dict: localStorage.getItem('lang') !== 'en-US' ? mzhCN : menUS, } refreshTabview = () => { const { tabview } = this.state window.GLOB.CacheMap = new Map() MKEmitter.emit('reloadMenuView', tabview.MenuID) } selectcomponent = (view) => { // 根据tab页中菜单信息,选择所需的组件 if (view.type === 'Home') { return (<Home MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) } else if (view.type === 'CommonTable' || view.type === 'ManageTable') { return (<CommonTable MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'CustomPage') { return (<CustomPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'TreePage') { return (<TreePage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'CalendarPage') { return (<CalendarPage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'RolePermission') { return (<RoleManage MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID}/>) } else if (view.type === 'FormTab') { return (<FormTab MenuNo={view.MenuNo} MenuID={view.MenuID} MenuName={view.MenuName} key={view.MenuID} param={view.param}/>) } else if (view.type === 'iframe') { return (<Iframe key={view.MenuID} MenuID={view.MenuID} MenuNo={view.MenuNo} title={view.MenuName} MenuName={view.MenuName} url={service + view.LinkUrl}/>) } else { return (<NotFount key={view.MenuID} />) } } UNSAFE_componentWillMount () { if (!sessionStorage.getItem('lang') || sessionStorage.getItem('lang') === 'zh-CN') { moment.locale('zh-cn') } else { moment.locale('en') } let home = { MenuID: 'home_page_id', MenuName: this.state.dict['main.homepage'], selected: true, type: 'Home' } this.setState({tabview: home}) } gotoHome = () => { let home = { MenuID: 'home_page_id', MenuName: this.state.dict['main.homepage'], selected: true, type: 'Home' } this.setState({tabview: home}) } UNSAFE_componentWillReceiveProps (nextProps) { if (nextProps.tabviews && !is(fromJS(this.state.tabviews), fromJS(nextProps.tabviews))) { // 保存修改标签集 this.setState({ tabview: nextProps.tabviews[nextProps.tabviews.length - 1] }) let node = document.getElementById('root').parentNode.parentNode if (node) { node.scrollTop = 0 } } } /** * @description 组件销毁,清除state更新 */ componentWillUnmount () { this.setState = () => { return } } render () { const { tabview } = this.state return ( <section id="mk-breadview-wrap" className="mk-breadview-wrap"> {tabview ? <Breadcrumb separator=""> <Breadcrumb.Item> <Icon type="home" onClick={this.gotoHome} /> </Breadcrumb.Item> {tabview.ParentNames && tabview.ParentNames[0] ? <Breadcrumb.Item>{tabview.ParentNames[0]}</Breadcrumb.Item> : null} {tabview.ParentNames && tabview.ParentNames[0] ? <Breadcrumb.Separator children={<Icon type="right" />} /> : null} {tabview.ParentNames && tabview.ParentNames[1] ? <Breadcrumb.Item>{tabview.ParentNames[1]}</Breadcrumb.Item> : null} {tabview.ParentNames && tabview.ParentNames[1] ? <Breadcrumb.Separator children={<Icon type="right" />} /> : null} <Breadcrumb.Item><Icon type="redo" onClick={this.refreshTabview}/>{tabview.MenuName}</Breadcrumb.Item> </Breadcrumb> : null} {tabview ? this.selectcomponent(tabview) : null} <BackTop> <div className="ant-back-top"> <div className="ant-back-top-content"> <div className="ant-back-top-icon"></div> </div> </div> </BackTop> </section> ) } } const mapStateToProps = (state) => { return { tabviews: state.tabviews } } const mapDispatchToProps = () => { return {} } export default connect(mapStateToProps, mapDispatchToProps)(BreadView) src/components/breadview/index.scss
New file @@ -0,0 +1,73 @@ .mk-breadview-wrap { min-height: 100%; padding-top: 48px; width: 100%; box-sizing: content-box; >.ant-breadcrumb { padding: 10px; .anticon-home { cursor: pointer; margin-right: 10px; } .anticon-redo { cursor: pointer; margin-right: 5px; } .ant-breadcrumb-link + .ant-breadcrumb-separator { display: none; } } >.commontable, >.calendar-page { padding-left: 15px; padding-right: 15px; } >.commontable, >.calendar-page { > .top-search { padding-left: 0; padding-right: 0; margin: 0 24px; } } iframe { width: 100%; height: calc(100vh - 115px); overflow-y: scroll; border: 0; margin-top: 16px; } .main-copy { position: fixed; z-index: 20; bottom: 65px; right: 30px; width: 40px; height: 40px; i { font-size: 18px; } } .main-copy.ifr-copy { bottom: 65px; right: 40px; width: 30px; height: 32px; border: 2px solid #687991; opacity: 0.6; i { font-size: 14px; color: #687991; } } .main-copy.ifr-copy:hover { opacity: 1; } .ant-back-top { bottom: 20px; right: 30px; } } .ant-message { top: 50px; z-index: 1080; } src/components/header/index.jsx
@@ -48,7 +48,8 @@ thdMenuList: [], oriVersion: '', newVersion: '', debug: sessionStorage.getItem('debug') === 'true' debug: sessionStorage.getItem('debug') === 'true', navBar: window.GLOB.navBar } handleCollapse = () => { @@ -126,10 +127,10 @@ changeMenu (value) { // 主菜单切换 if (value.PageParam.OpenType === 'menu') { if (value.OpenType === 'outpage' && value.linkUrl) { window.open(value.linkUrl) } else if (value.OpenType === 'menu') { this.props.modifyMainMenu(value) } else if (value.PageParam.OpenType === 'outpage') { window.open(value.PageParam.linkUrl) } } @@ -227,14 +228,19 @@ let tabs = fromJS(this.props.tabviews).toJS() let menu = fromJS(response[1]).toJS() tabs = tabs.map(tab => { tab.selected = false return tab }) if (this.state.navBar === 'topmenu') { menu.selected = true this.props.modifyTabview([menu]) } else { tabs = tabs.map(tab => { tab.selected = false return tab }) menu.selected = true tabs.push(menu) this.props.modifyTabview(tabs) menu.selected = true tabs.push(menu) this.props.modifyTabview(tabs) } } }) } @@ -247,14 +253,18 @@ let fstItem = { MenuID: fst.MenuID, MenuName: fst.MenuName, PageParam: {OpenType: 'menu', linkUrl: ''}, OpenType: 'menu', children: [] } if (fst.PageParam) { try { fstItem.PageParam = JSON.parse(fst.PageParam) } catch (e) { fstItem.PageParam = {OpenType: 'menu', linkUrl: ''} fstItem.PageParam = null } if (fstItem.PageParam && fstItem.PageParam.OpenType === 'outpage' && fstItem.PageParam.linkUrl) { fstItem.OpenType = 'outpage' fstItem.linkUrl = fstItem.PageParam.linkUrl } } @@ -287,6 +297,7 @@ debug: sessionStorage.getItem('debug'), role_id: sessionStorage.getItem('role_id'), mainlogo: window.GLOB.mainlogo, navBar: window.GLOB.navBar || '', mstyle: window.GLOB.style } @@ -297,6 +308,7 @@ ParentId: snd.MenuID, MenuID: trd.MenuID, MenuName: trd.MenuName, ParentNames: [fst.MenuName, snd.MenuName], MenuNo: trd.MenuNo, EasyCode: trd.EasyCode, type: 'CommonTable', // 默认值为常用表 @@ -541,15 +553,18 @@ changeVerMenu(menu, type) { if (type === 'first') { if (menu.PageParam.OpenType === 'menu') { if (menu.OpenType === 'outpage' && menu.linkUrl) { window.open(menu.linkUrl) } else if (menu.OpenType === 'menu') { } else if (menu.PageParam.OpenType === 'outpage') { window.open(menu.PageParam.linkUrl) } } else { if (menu.OpenType === 'newpage' || menu.OpenType === 'NewPage') { if (menu.OpenType === 'newpage' || menu.OpenType === 'NewPage') { // NewPage为打开外部页面地址,newpage为打开系统菜单 window.open(menu.src) } else if (menu.OpenType === 'blank') { menu.selected = true this.props.modifyTabview([menu]) } else if (this.state.navBar === 'topmenu') { menu.selected = true this.props.modifyTabview([menu]) } else { @@ -578,7 +593,7 @@ render () { const { mainMenu, collapse } = this.props const { thdMenuList, searchkey, oriVersion, newVersion, debug, menulist } = this.state const { thdMenuList, searchkey, oriVersion, newVersion, debug, menulist, navBar } = this.state const menu = ( <Menu className="header-dropdown"> @@ -602,12 +617,12 @@ return ( <header className="header-container ant-menu-dark" id="main-header-container"> <div className={'header-logo ' + (collapse ? 'collapse' : '')}><img src={this.state.logourl} alt=""/></div> <div className={'header-collapse ' + (collapse ? 'collapse' : '')}> {menulist && menulist.length ? <Icon type={collapse ? 'menu-unfold' : 'menu-fold'} onClick={this.handleCollapse}/> : null} <div className={'header-logo ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')}><img src={this.state.logourl} alt=""/></div> <div className={'header-collapse ' + (collapse && navBar !== 'topmenu' ? 'collapse' : '')}> {navBar !== 'topmenu' ? <Icon type={collapse ? 'menu-unfold' : 'menu-fold'} onClick={this.handleCollapse}/> : null} </div> {/* 正常菜单 */} {menulist ? {navBar !== 'topmenu' && menulist ? <ul className="header-menu">{ menulist.map(item => { return ( @@ -619,7 +634,7 @@ </ul> : null } {/* 正常菜单 */} {/* {menulist ? {navBar === 'topmenu' && menulist ? <ul className="header-menu vertical-menu">{ menulist.map(item => { if (item.children && item.children.length > 0) { @@ -661,7 +676,7 @@ } })} </ul> : null } */} } {/* 头像、用户名 */} <Dropdown className="header-setting" overlay={menu}> <div> src/components/tabview/index.jsx
@@ -35,7 +35,7 @@ service = window.GLOB.location + '/' + window.GLOB.service + 'zh-CN/' } class Header extends Component { class TabViews extends Component { static propTpyes = { collapse: PropTypes.bool, tabviews: PropTypes.array // 标签页数组 @@ -269,4 +269,4 @@ } } export default connect(mapStateToProps, mapDispatchToProps)(Header) export default connect(mapStateToProps, mapDispatchToProps)(TabViews) src/index.js
@@ -154,6 +154,7 @@ GLOB.webSite = _systemMsg.webSite GLOB.style = _systemMsg.style GLOB.showline = _systemMsg.showline || '' GLOB.navBar = _systemMsg.navBar || 'sidemenu' if (GLOB.favicon) { let link = document.querySelector("link[rel*='icon']") || document.createElement('link') src/router/index.js
@@ -58,6 +58,9 @@ if (_param.mainlogo) { window.GLOB.mainlogo = _param.mainlogo } if (_param.navBar) { window.GLOB.navBar = _param.navBar } if (_param.mstyle && styles[_param.mstyle]) { document.body.className = styles[_param.mstyle] } src/tabviews/zshare/actionList/tabbutton/index.jsx
@@ -134,18 +134,22 @@ return tab.MenuID !== newtab.MenuID }) if (tabviews.length !== tabs.length) { this.props.modifyTabview(fromJS(tabs).toJS()) } this.setState({}, () => { if (MenuID) { tabs.splice(index + 1, 0, newtab) } else { tabs.push(newtab) if (window.GLOB.navBar === 'topmenu') { this.props.modifyTabview([newtab]) } else { if (tabviews.length !== tabs.length) { this.props.modifyTabview(fromJS(tabs).toJS()) } this.props.modifyTabview(tabs) }) this.setState({}, () => { if (MenuID) { tabs.splice(index + 1, 0, newtab) } else { tabs.push(newtab) } this.props.modifyTabview(tabs) }) } MKEmitter.emit('openNewTab') if (window.GLOB.systemType === 'production') { src/templates/sharecomponent/actioncomponent/actionform/index.jsx
@@ -665,7 +665,7 @@ } ] })( <Cascader options={item.options || []} placeholder="" /> <Cascader allowClear options={item.options || []} placeholder="" /> )} </Form.Item> </Col> src/views/login/index.jsx
@@ -291,7 +291,8 @@ doclogo: res.doclogo || '', style: res.CSS || '', showline: res.split_line_show || 'true', webSite: res.WebSite || '' webSite: res.WebSite || '', navBar: res.NavBar !== 'topmenu' ? 'sidemenu' : 'topmenu' } sessionStorage.setItem('home_background', res.index_background_color) @@ -344,6 +345,7 @@ window.GLOB.mainlogo = systemMsg.mainlogo window.GLOB.style = systemMsg.style window.GLOB.navBar = systemMsg.navBar if (window.GLOB.style && styles[window.GLOB.style]) { document.body.className = styles[window.GLOB.style] + ' ' + (res.split_line_show === 'false' ? 'hidden-split-line' : '') src/views/main/index.jsx
@@ -11,16 +11,23 @@ import './index.scss' const Tabview = asyncComponent(() => import('@/components/tabview')) const Breadview = asyncComponent(() => import('@/components/breadview')) const _locale = localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS class Main extends Component { state = { navBar: window.GLOB.navBar } render () { const { navBar } = this.state return ( <div className="mk-main-view"> <ConfigProvider locale={_locale}> <Header key="header"/> <Sidemenu key="sidemenu"/> <Tabview key="tabview"/> {navBar !== 'topmenu' ? <Sidemenu key="sidemenu"/> : null} {navBar !== 'topmenu' ? <Tabview key="tabview"/> : null} {navBar === 'topmenu' ? <Breadview key="breadview"/> : null} <QueryLog /> </ConfigProvider> </div> src/views/menudesign/index.jsx
@@ -508,7 +508,7 @@ EasyCode: _config.easyCode || '', Template: 'CustomPage', MenuName: _config.MenuName || '', PageParam: JSON.stringify({Template: 'CustomPage', OpenType: 'newtab'}), PageParam: JSON.stringify({Template: 'CustomPage', OpenType: _config.OpenType || 'newtab'}), LongParam: window.btoa(window.encodeURIComponent(JSON.stringify(_config))), LText: '', LTexttb: '' src/views/menudesign/menuform/index.jsx
@@ -143,6 +143,8 @@ this.props.updateConfig({...config, cacheUseful: value}) } else if (key === 'timeUnit') { this.props.updateConfig({...config, timeUnit: value}) } else if (key === 'OpenType') { this.props.updateConfig({...config, OpenType: value}) } } @@ -255,6 +257,24 @@ </Form.Item> </Col> <Col span={24}> <Form.Item label="打开方式"> {getFieldDecorator('OpenType', { initialValue: config.OpenType || 'newtab', rules: [ { required: true, message: dict['form.required.select'] + dict['model.openway'] + '!' } ] })( <Select onChange={(value) => {this.selectChange('OpenType', value)}}> <Select.Option value="newtab">标签页</Select.Option> <Select.Option value="newpage">新页面</Select.Option> </Select> )} </Form.Item> </Col> <Col span={24}> <Form.Item label={ <Tooltip placement="topLeft" title="对于不经常性变动的信息,缓存数据有助于提高查询效率。"> <Icon type="question-circle" />