Commit 715215a2 authored by 曾婧's avatar 曾婧

华农主题提交本地一版本

parent b5637430
/*
* @Author: ZengJing
* @Date: 2022-04-12 18:26:15
* @LastEditTime: 2022-04-14 09:47:56
* @LastEditors: ZengJing
* @Description:
* @FilePath: \CivWeb\config\micor.js
*/
export function genActiveRule(routerPrefix) {
return location => {
......@@ -34,18 +42,24 @@ export default {
// origin: `//127.0.0.1:8345`,
// },
// },
{
name: 'civ_webgis',
entry: `//${window.location.hostname}:8081/civ_webgis`,
container: '#micro-container',
activeRule: '/civbase/civ_webgis',
},
// {
// name: 'civ_webgis',
// entry: `//${window.location.hostname}:8081/civ_webgis`,
// container: '#micro-container',
// activeRule: '/civbase/civ_webgis',
// },
{
name: 'civweb4',
entry: `//${window.location.hostname}:3020/civweb4`,
container: '#micro-container',
activeRule: '/civbase/civweb4',
},
{
name: 'civ_energy',
entry: `//${window.location.hostname}:8081/civ_energy`,
container: '#micro-container',
activeRule: '/civbase/civ_energy',
},
// {
// name: 'middleground',
// entry: `//${window.location.hostname}:8082/middleground`,
......
......@@ -2,7 +2,7 @@
// const proxyURL = process.env.NODE_ENV !== 'production' ? 'http://192.168.10.150:8777' : window.location.origin;
// const proxyURL = 'https://work.panda-water.cn';
// const proxyURL = 'http://192.168.12.47:8082';
const proxyURL = 'https://panda-water.cn';
const proxyURL = 'http://localhost:8086';
module.exports = {
......
{
"name": "civbase",
"version": "0.0.14",
"description": "",
"description": "1. Make sure that you have Node.js v8.15.1 and npm v5 or above installed.\r 2. Run `npm run setup` in order to install dependencies and clean the git repo.<br />\r _At this point you can run `npm start`",
"repository": {
"type": "git",
"url": "https://g.civnet.cn:8443/ReactWeb5/CivWeb.git"
......@@ -303,5 +303,6 @@
"webpackbar": "5.0.0-3",
"whatwg-fetch": "^3.0.0",
"yorkie": "^2.0.0"
}
},
"main": ".eslintrc.js"
}
This diff was suppressed by a .gitattributes entry.
/*
* @Author: ZengJing
* @Date: 2022-04-14 10:25:39
* @LastEditTime: 2022-04-14 10:30:09
* @LastEditors: ZengJing
* @Description:
* @FilePath: \CivWeb\src\components\GlobalHeader\HNRightContent.js
*/
import React, { useState, useRef } from 'react';
import { message } from 'antd';
import _ from 'lodash';
import { connect } from 'react-redux';
import Icon from '@ant-design/icons';
import classNames from 'classnames';
import { useHistory } from '@wisdom-utils/runtime';
import { HeaderSearch, useIntl, AvatarDropdown as Avatar } from '@wisdom-utils/components';
import { actionCreators } from '../../containers/App/store';
import styles from './index.less';
import NoticeIconView from './NoticeIconView';
/* eslint-disable */
const orderSvg = () => (
<svg
version="1.1"
x="0px"
y="0px"
width="24px"
height="24px"
viewBox="0 0 24 24"
enableBackground="new 0 0 24 24"
space="preserve"
>
<path
fill="hsla(221, 100%, 95%, 0.7)"
d="M7.223,13.131c-0.445,0-0.815,0.364-0.815,0.816c0,0.446,0.37,0.816,0.815,0.816
c0.446,0,0.816-0.37,0.816-0.816C8.039,13.495,7.669,13.131,7.223,13.131L7.223,13.131z M7.223,16.574L7.223,16.574
c-0.445,0-0.815,0.371-0.815,0.817c0,0.45,0.37,0.814,0.815,0.814c0.446,0,0.816-0.364,0.816-0.814
C8.039,16.945,7.669,16.574,7.223,16.574L7.223,16.574z M7.223,9.688L7.223,9.688c-0.445,0-0.815,0.366-0.815,0.817
c0,0.445,0.37,0.815,0.815,0.815c0.446,0,0.816-0.37,0.816-0.815C8.039,10.054,7.669,9.688,7.223,9.688L7.223,9.688z M20.469,4.533
L20.469,4.533h-2.246V4.082c0-0.268-0.22-0.48-0.485-0.48h-2.622c-0.138-0.59-0.434-1.1-0.839-1.505
c-0.59-0.591-1.388-0.95-2.28-0.95c-0.884,0-1.677,0.359-2.262,0.95C9.323,2.502,9.022,3.012,8.879,3.602H6.263
c-0.267,0-0.492,0.213-0.492,0.48v0.451H3.548c-0.451,0-0.821,0.363-0.821,0.814v16.688c0,0.452,0.37,0.817,0.821,0.817h16.921
c0.438,0,0.805-0.365,0.805-0.817V5.348C21.273,4.896,20.907,4.533,20.469,4.533L20.469,4.533z M10.671,3.027
c0.405-0.404,0.718-0.653,1.325-0.653c0.614,0,0.933,0.249,1.337,0.653c0.221,0.227,0.158,0.256,0.273,0.574h-3.208
C10.516,3.283,10.44,3.254,10.671,3.027 M7.015,4.822L7.015,4.822h9.982v1.054H7.015 M19.647,21.215L19.647,21.215H4.359V6.158
h1.411v0.451c0,0.267,0.226,0.486,0.492,0.486h11.475c0.266,0,0.485-0.22,0.485-0.486V6.158h1.425V21.215L19.647,21.215z
M16.742,9.765L16.742,9.765H9.659c-0.267,0-0.485,0.468-0.485,0.74c0,0.267,0.219,0.739,0.485,0.739h7.083
c0.277,0,0.491-0.473,0.491-0.739C17.233,10.232,17.02,9.765,16.742,9.765L16.742,9.765z M16.742,16.65L16.742,16.65H9.659
c-0.267,0-0.485,0.468-0.485,0.741c0,0.271,0.219,0.728,0.485,0.728h7.083c0.277,0,0.491-0.457,0.491-0.728
C17.233,17.118,17.02,16.65,16.742,16.65L16.742,16.65z M16.742,13.213L16.742,13.213H9.659c-0.267,0-0.485,0.462-0.485,0.735
c0,0.271,0.219,0.734,0.485,0.734h7.083c0.277,0,0.491-0.464,0.491-0.734C17.233,13.675,17.02,13.213,16.742,13.213L16.742,13.213z"
/>
</svg>
);
const homeSvg = () => (
<svg
version="1.1"
x="0px"
y="0px"
width="24px"
height="24px"
viewBox="0 0 24 24"
enableBackground="new 0 0 24 24"
space="preserve"
>
<path
fill="hsla(221, 100%, 95%, 0.7)"
d="M23.359,13.561v-1.313L12.057,1.064L0.642,12.247v1.37h2.84v9.318h7.381v-4.935h2.271v4.935h7.385v-9.318
L23.359,13.561z M18.815,11.917v9.319H14.84v-4.935H9.161v4.935H5.185v-9.319H3.311l8.746-8.551l8.577,8.551H18.815z"
/>
</svg>
);
const favitorSvg = () => (
<svg
t="1631171489722"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="16457"
width="24"
height="24"
>
<path
d="M512 87.806c-234.721 0-424.194 189.474-424.194 424.194s189.474 424.194 424.194 424.194 424.194-189.474 424.194-424.194-189.474-424.194-424.194-424.194zM783.484 442.715l-137.155 100.393c-7.069 5.655-9.899 14.141-7.069 22.624l52.317 161.194c5.655 18.382-15.553 33.935-31.108 22.624l-137.155-100.393c-7.069-5.655-16.967-5.655-24.037 0l-137.155 100.393c-15.553 11.312-36.763-4.242-31.108-22.624l53.731-162.608c2.829-8.484 0-16.967-7.069-22.624l-137.155-100.393c-15.553-11.312-7.069-35.349 11.312-35.349h169.678c8.484 0 16.967-5.655 18.382-14.141l52.317-161.194c5.655-18.382 32.522-18.382 38.177 0l52.317 161.194c2.829 8.484 9.899 14.141 18.382 14.141h169.678c21.21 0 28.278 25.452 12.725 36.763z"
p-id="16458"
fill="hsla(221, 100%, 95%, 0.7)"
/>
</svg>
);
const themeSvg = () => (
<svg
t="1631362986014"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
>
<path
d="M552.75 563.239c44.4 26.348 99.1 26.348 143.5 0C740.65 536.89 768 488.197 768 435.5c0-81.462-64.247-147.5-143.5-147.5S481 354.038 481 435.5c0 52.697 27.35 101.39 71.75 127.739z"
fill="hsla(221, 100%, 95%, 0.7)"
p-id="2351"
/>
<path
d="M471.264 952c-18.842 0-38.581-1.796-60.115-4.49l-5.384-0.899c-152.533-23.352-256.614-171.55-261.1-177.837-147.149-224.541-73.574-451.777 65.5-577.52C348.34 65.511 578.934 11.621 780.814 174.19c130.102 105.085 169.58 250.588 171.375 256.875v1.797c18.843 102.39 3.59 177.836-45.76 226.337-75.368 72.752-200.086 49.4-217.134 45.807-23.328-2.695-40.376 4.49-52.938 19.76-13.458 17.064-16.15 39.518-11.664 52.991 12.562 37.723 14.356 66.464 5.384 88.02C604.058 922.361 551.12 952 471.264 952z m-51.973-80.488l5.083 0.849c82.179 12.72 132.164-3.393 152.497-49.188 0-0.849 4.236-11.873-6.778-45.796-11.013-30.53-2.541-70.39 19.486-97.528 22.875-28.834 56.763-41.556 96.581-37.315l2.542 0.848c0.847 0 105.9 22.898 160.122-29.683 33.04-32.226 43.207-88.199 28.805-166.221-3.39-11.025-39.819-130.603-144.872-214.562-166.053-135.69-356.674-90.743-471.894 13.57-105.9 96.68-183.843 280.71-53.374 480.007 0.848 0 89.804 127.21 211.802 145.02z"
fill="hsla(221, 100%, 95%, 0.7)"
p-id="2352"
/>
<path
d="M203 529c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m90-115.235A54 54 0 0 1 266 367c0-29.823 24.177-54 54-54s54 24.177 54 54a54 54 0 0 1-81 46.765zM427 278c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m180 44c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z m90 144c0-29.823 24.177-54 54-54s54 24.177 54 54-24.177 54-54 54-54-24.177-54-54z"
fill="hsla(221, 100%, 95%, 0.7)"
/>
</svg>
);
const OrderIcon = props => <Icon component={orderSvg} {...props} />;
const HomeIcon = props => <Icon component={homeSvg} {...props} />;
const FavitorIcon = props => <Icon component={favitorSvg} {...props} />;
const ThemeIcon = props => <Icon component={themeSvg} {...props} />;
const MESSAGE_BOX_URL = 'product/maintenance/CaseManage/CaseDoingBox/StardCaseDoingBoxView|isDelay=1';
export const getConfig = (widgets, url, key) => {
let widgetconfig = {};
if (widgets) {
// eslint-disable-next-line no-plusplus
for (let i = 0; i < widgets.length; i++) {
const widget = widgets[i];
if (widget && widget[key]) widget[key] = widget[key].replace(/\\/g, '/').trim();
// eslint-disable-next-line eqeqeq
if (widget[key] && url.toLowerCase() === widget[key].toLowerCase()) {
widgetconfig = widget;
break;
} else {
const children = widget.widgets ? widget.widgets : widget.routes;
if (children) {
widgetconfig = getConfig(children, url, key);
if (widgetconfig) {
break;
}
}
}
}
}
return widgetconfig;
};
const GlobalHeaderRight = props => {
const [options, setOptions] = useState([]);
const homeRef = useRef(null);
const favitorRef = useRef(null);
const history = useHistory();
const { theme, layout } = props;
let className = styles.right;
if (theme === 'dark' && layout === 'top') {
className = `${styles.right} ${styles.dark}`;
}
const intl = useIntl();
console.log('props.global ==', props.global);
const goHome = event => {
event.stopPropagation();
let url = _.isString(props.global.get('homepage'))
? props.global.get('homepage')
: props.global.get('homepage.url');
if (!props.global.get('home')) {
url = `civweb4/${url.replace(/^\//, '').replace(/^civweb4\//, '')}`;
}
window.share.event.emit('goHome', `/${url}`);
// url ? (
// window.share.event.emit('listenerMointer', {
// label: '首页',
// url: url.replace(/^civweb4\//, ''),
// })
// ) : null;
};
const handleOrder = event => {
event.stopPropagation();
const widgetConfig = getConfig(
props.global.get('widgets').concat(props.global.get('uiwidgets')),
MESSAGE_BOX_URL,
'url',
);
if (Object.keys(widgetConfig).length > 0) {
props.history.push(`/civweb4/${MESSAGE_BOX_URL}`);
setCurrentIndex(2);
} else {
message.warning('对不起,您没有菜单权限!');
}
};
const handlerFavitor = event => {
// setCurrentIndex(1);
history.push('/commonmenu');
window.share &&
window.share.event &&
window.share.event.emit('event:favitor', {
name: '常用',
path: '/commonmenu',
icon: <FavitorIcon />,
});
};
const handlerTheme = () => {
window.share.event.emit('event:theme');
};
const handleSelect = (value, data) => {
window.share.event.emit('addTips', options, data);
};
const handleSearch = value => {
// eslint-disable-next-line no-undef
const search = new AMap.Autocomplete();
const areaName =
// eslint-disable-next-line no-undef
createStoreage.get('globalConfig').mapsettings.areasettings &&
// eslint-disable-next-line no-undef
createStoreage.get('globalConfig').mapsettings.areasettings.areaName;
const area = (areaName || '') + value;
setOptions([]);
// eslint-disable-next-line no-unused-expressions
value
? search.search(area, (status, res) => {
if (res && res.tips) {
const result = res.tips.map(item => {
item.value = item.name;
item.label = (
<>
<span>{item.name}</span>
<span style={{ color: '#c1c1c1' }}>{item.district + item.address}</span>
</>
);
return item;
});
setOptions(result);
}
})
: setOptions([]);
};
return (
<div className={className}>
{/* <HeaderSearch
className={`${styles.action} ${styles.search} ${styles.extendsearch}`}
placeholder={intl.formatMessage({ id: 'component.search.menu.placeholder' })}
offset="46px"
defaultValue=""
mode="tiled"
options={options}
{...props}
onSelect={handleSelect}
onChange={handleSearch}
onSearch={handleSearch}
/> */}
<div className={styles.nav}>
{/* <div className={classNames(styles.item)} onClick={goHome} ref={homeRef}>
<HomeIcon title={intl.formatMessage({ id: 'component.header.icon.home' })} />
<span>首页</span>
</div> */}
{/* {// 云平台去掉常用菜单
props.global &&
props.global.userInfo &&
props.global.userInfo.Groups &&
props.global.userInfo.Groups.length ? null : (
<div className={classNames(styles.item)} onClick={handlerFavitor} ref={favitorRef}>
<FavitorIcon />
<span>常用</span>
</div>
)} */}
{/* <div className={classNames(styles.item)} onClick={handlerTheme}>
<ThemeIcon/>
<span>主题</span>
</div> */}
{/* <div className={classNames(styles.item)}>
<OrderIcon onClick={handleOrder} title={intl.formatMessage({ id: 'component.header.icon.order' })} />
<span>工单</span>
</div> */}
</div>
{/* <NoticeIconView title={intl.formatMessage({ id: 'component.header.icon.alarm' })} /> */}
<Avatar
menu
config={props.global}
updateCurrentIndex={props.updateCurrentIndex}
updateConfig={props.updateConfig}
logout={props.logout}
/>
</div>
);
};
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
flatMenu: state.getIn(['global', 'flatMenu']),
menu: state.getIn(['global', 'menu']),
recentKeywords: state.getIn(['global', 'recentKeywords']),
recentVisited: state.getIn(['global', 'recentVisited']),
recentProducts: state.getIn(['global', 'recentProducts']),
});
const mapDispatchToProps = dispatch => ({
updateRecentKeywords(keyword) {
dispatch(actionCreators.updateRecentKeywords(keyword));
},
updateRecentVisited(history) {
dispatch(actionCreators.updateRecentVisited(history));
},
updateRecentProduct(history) {
dispatch(actionCreators.updateRecentProduct(history));
},
clearRecentProduct() {
dispatch(actionCreators.clearRecentProduct());
},
updateCurrentIndex(index) {
dispatch(actionCreators.updateCurrentIndex(index));
},
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
updateComplexConfig(config) {
dispatch(actionCreators.updateComplexConfig(config));
},
logout() {
dispatch(actionCreators.logout());
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(GlobalHeaderRight);
import React, { useContext } from 'react';
import { ConfigProvider, Divider, Skeleton, Tooltip } from 'antd';
import './index.less';
import classNames from 'classnames';
import { ReactSVG } from 'react-svg';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import { useHistory } from '@wisdom-utils/runtime';
const LoadingSkeleton = (props) => {
const route = props.route;
return (
<div style={{ padding: route && !route.routes ? '20px 6px 6px 6px' : '0px' }}>
<Skeleton loading={route && !route.routes} active title={false} paragraph={{ rows: 10 }}>
{props.children}
</Skeleton>
</div>
);
};
const Menu = (props) => {
const {
prefixCls,
collapsed,
onCollapse,
onMenuClick,
menuHeaderRender,
onMenuHeaderClick,
} = props;
const route = props.route;
const history = useHistory();
const [selectIndex, setSelectIndex] = useMergedState(() => -1, {
value: props.active,
onChange: props.onActiveChange,
});
const toLink = (path) => {
if (!window.__POWERED_BY_QIANKUN__) {
history.push(path);
} else {
window.history.pushState(null, '', path);
}
};
const onSelectItem = (item, index) => {
let current = void 0;
let childrenRoutes = [];
if (item && item.routes) {
current = item.routes[0];
childrenRoutes = item.routes;
} else {
current = item;
childrenRoutes = [item];
}
setSelectIndex(index);
if (/iframe/.test(current.path)) {
history.push({
path: 'iframe',
state: current.params,
});
} else {
window.__POWERED_BY_QIANKUN__ ? toLink(`/civbase${current.path}`) : toLink(current.path);
}
onMenuClick && onMenuClick(current, childrenRoutes, index);
};
return (
<LoadingSkeleton {...props}>
{route && route.routes && route.routes.length > 0 && (
<React.Fragment>
{menuHeaderRender ? (
menuHeaderRender(props)
) : (
<>
<ul
className={classNames(`${prefixCls}-menu`)}
style={{ minHeight: '0px', marginBottom: '0px' }}
>
<li className={`${prefixCls}-menu-item`} onClick={onMenuHeaderClick}>
<Tooltip placement="right" title={collapsed ? route.name : ''}>
<a>
{route && route.extData && route.extData.icon && (
<img src={route.extData.icon} />
)}
{collapsed ? null : (
<span
className={classNames(
`${prefixCls}-menu-item-text`,
`${prefixCls}-menu-item-current`,
)}
>
{route && route.name}
</span>
)}
</a>
</Tooltip>
</li>
</ul>
<div className={`${prefixCls}-line`} />
</>
)}
<ul className={classNames(`${prefixCls}-menu ${prefixCls}-menu-vertical`)}>
{route &&
(route.routes || [])
.filter((item) => !item.hideInMenu)
.map((item, index) => {
return (
<React.Fragment key={index}>
<li
key={index}
className={classNames(`${prefixCls}-menu-item`, {
[`${prefixCls}-menu-item-active`]: index === selectIndex,
})}
onClick={() => onSelectItem(item, index)}
>
<Tooltip placement="right" title={collapsed ? item.name : ''}>
<a>
{item.icon ? (
item.icon
) : item.extData && /.svg/.test(item.extData.icon) ? (
<ReactSVG
src={item.extData.icon}
style={{ width: '20px', height: '20px' }}
className={`${prefixCls}-menu-item-icon`}
/>
) : (
item.extData && <img src={item.extData.icon} />
)}
{collapsed ? (
item.extData && (
<span className={`${prefixCls}-menu-item-text`}>
{(item.extData.shortName || item.name).substr(0, 2)}
</span>
)
) : (
<span className={`${prefixCls}-menu-item-text`}>{item.name}</span>
)}
</a>
</Tooltip>
</li>
<Divider
style={{
border: '1px solid rgb(49, 53, 62, 0.3)',
margin: '0 auto',
minWidth: '80%',
width: '80%',
}}
/>
</React.Fragment>
);
})}
</ul>
</React.Fragment>
)}
</LoadingSkeleton>
);
};
export default (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('layout-slider');
const { menuItemRender, menuHeaderRender, siderWidth } = props;
const { collapsed, onCollapse, route, style } = props;
return (
<>
<div
style={{
width: collapsed ? '48px' : `${siderWidth}px`,
overflow: 'hidden',
flex: `0 0 ${collapsed ? 48 : siderWidth}px`,
maxWidth: collapsed ? 48 : siderWidth,
minWidth: collapsed ? 48 : siderWidth,
transition:
'background-color 0.3s ease 0s, min-width 0.3s ease 0s, max-width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s',
...style,
}}
/>
<aside
className={classNames(`${prefixCls}`, `${prefixCls}-fixed`, {
[`${prefixCls}-collapsed`]: collapsed,
})}
>
<div className={`${prefixCls}-children`}>
<div
className={`${prefixCls}-wrapper`}
style={{ flex: '1 1 0%', overflow: 'hidden auto' }}
>
{/*{LoadingSkeleton(props)}*/}
{menuItemRender
? menuItemRender(props)
: Menu(Object.assign({}, props, { prefixCls: prefixCls }))}
</div>
{route && route.routes && route.routes.length > 0 && (
<div className={`${prefixCls}-pro-sider-links`}>
<ul
className={`${prefixCls}-menu ${prefixCls}-menu-root ${prefixCls}-menu-inline ${prefixCls}-menu-dark ${prefixCls}-pro-sider-link-menu`}
role="menu"
tabIndex="0"
>
<li
className={`${prefixCls}-menu-item ${prefixCls}-menu-item-only-child ${prefixCls}-pro-sider-collapsed-button`}
style={{ height: '40px', lineHeight: '40px' }}
role="menuitem"
tabIndex="-1"
onClick={onCollapse}
>
<span className={`${prefixCls}-menu-title-content`}>
<span
role="img"
aria-label="menu-fold"
className="anticon anticon-menu-fold"
style={{ color: '#fff' }}
>
<svg
viewBox="64 64 896 896"
focusable="false"
width="1em"
height="1em"
fill="currentColor"
aria-hidden="true"
>
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 000 13.8z"></path>
</svg>
</span>
</span>
</li>
</ul>
<div aria-hidden="true" style={{ display: 'none' }} />
</div>
)}
</div>
</aside>
</>
);
};
/*
* @Author: ZengJing
* @Date: 2022-04-15 09:34:03
* @LastEditTime: 2022-04-15 18:06:00
* @LastEditors: ZengJing
* @Description:
* @FilePath: \CivWeb\src\layouts\AppLayout\components\SlideMenu\index.js
*/
import React, { useContext, useEffect } from 'react';
import { ConfigProvider, Divider, Skeleton, Tooltip } from 'antd';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { ReactSVG } from 'react-svg';
import ProLayout, { getPageTitle } from '@ant-design/pro-layout';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import { useHistory } from '@wisdom-utils/runtime';
const LoadingSkeleton = props => {
const route = props.route;
return (
<div style={{ padding: route && !route.routes ? '20px 6px 6px 6px' : '0px' }}>
<Skeleton loading={route && !route.routes} active title={false} paragraph={{ rows: 10 }}>
{props.children}
</Skeleton>
</div>
);
};
const Menu = props => {
const { prefixCls, collapsed, onCollapse, onMenuClick, menuHeaderRender, onMenuHeaderClick, title } = props;
const route = props.route;
const history = useHistory();
const [selectIndex, setSelectIndex] = useMergedState(() => -1, {
value: props.active,
onChange: props.onActiveChange,
});
const toLink = path => {
if (!window.__POWERED_BY_QIANKUN__) {
history.push(path);
} else {
window.history.pushState(null, '', path);
}
};
const onSelectItem = (item,dom) => {
let current = void 0;
let childrenRoutes = [];
console.log('item', item,dom);
if (item && item.child) {
current = item.child[0];
childrenRoutes = item.child;
} else {
current = item;
childrenRoutes = [item];
}
if (/iframe/.test(current.path)) {
history.push({
path: 'iframe',
state: current.params,
});
} else {
window.__POWERED_BY_QIANKUN__ ? toLink(`/civbase${current.path}`) : toLink(current.path);
}
console.log('current', childrenRoutes);
onMenuClick && onMenuClick(current, childrenRoutes);
};
useEffect(() => {
route.routes = treeRoutes(route.routes);
console.log('newRoutes************', route.routes);
}, [route]);
const treeRoutes = iroute =>
iroute
.filter(item => item.level !== 3)
.map(item => {
console.log('item..>', item);
if (item.routes && Array.isArray(item.routes) && item.routes.length >= 1) {
if(item.level===2){
item.child = item.routes;
}
item.routes = treeRoutes(item.routes);
}
return item;
});
return (
<LoadingSkeleton {...props}>
{route && route.routes && route.routes.length > 0 && (
<ProLayout
route={route}
title={props.title}
logo={null}
siderWidth={140}
config={props.global}
currentMenuIndex={props.currentMenuIndex}
// onHeaderLogo={handlerIndustry}
// onPageChange={handlerPageChange}
// onMenuPanelItemClick={handleUpdateCurrentIndex}
menuItemRender={(item, dom) => {
return item.level < 3 ? (
<div
onClick={() => {
onSelectItem(item,dom);
}}
className="test-icon"
>
{/.svg/.test(item.extData.icon) ? (
<div className="my-svg">
<ReactSVG src={item.extData.icon} style={{ width: '100%', height: '100%' }} />
</div>
) : (
<div className="my-img">
<img src={item.extData.icon} style={{ width: '100%', height: '100%' }} />
</div>
)}
<span style={{ marginLeft: '5px' }}> {dom} </span>
</div>
) : null;
}}
subMenuItemRender={(item, dom) => (
<div className="test-icon">
{/.svg/.test(item.extData.icon) ? (
<div className="my-svg">
<ReactSVG src={item.extData.icon} style={{ width: '100%', height: '100%' }} />
</div>
) : (
<div className="my-img">
<img src={item.extData.icon} style={{ width: '100%', height: '100%' }} />
</div>
)}
<span style={{ marginLeft: '5px' }}> {dom} </span>
</div>
)}
// headerSiteRender={() =>
// renderSite({
// data: cityData,
// config: props.global,
// loading: siteLoading,
// setLoading: setSiteLoading,
// action: siteAction,
// })
// }
>
<>
{/* <Suspense fallback={<></>}>
{window.location.pathname.startsWith('/civbase/civ_3d') ? (
<KeepAlive>
<CesiumMap />
</KeepAlive>
) : window.location.pathname.startsWith('/civbase/civ_webgis') ? (
mapMode === 'AMap' ? (
<AMap />
) : (
<ArcgisMap options={{ type: 'ArcgisMap' }} />
)
) : null}
</Suspense>
<div id="micro-container" className="subapp-container">
{props.children}
</div> */}
</>
</ProLayout>
)}
</LoadingSkeleton>
);
};
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
settings: state.getIn(['global', 'defaultSetting']),
collapsed: state.getIn(['global', 'collapsed']),
menu: state.getIn(['global', 'menu']),
currentMenuIndex: state.getIn(['global', 'currentMenuIndex']),
flatMenu: state.getIn(['global', 'flatMenu']),
authValidate: state.getIn(['global', 'authValidate']),
pathname: state.getIn(['global', 'pathname']),
selectedKeys: state.getIn(['global', 'selectedKeys']),
openKeys: state.getIn(['global', 'openKeys']),
complexConfig: state.getIn(['global', 'complexConfig']),
complexPathName: state.getIn(['global', 'complexPathName']),
microMounted: state.getIn(['global', 'microMounted']),
});
const mapDispatchToProps = dispatch => ({
updageSetting(setting) {
dispatch(actionCreators.updageSetting(setting));
},
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
updateCurrentIndex(index) {
dispatch(actionCreators.updateCurrentIndex(index));
},
updateCollapsed(collapsed) {
dispatch(actionCreators.updateCollapsed(collapsed));
},
updateAuthValidate(auth) {
dispatch(actionCreators.updateAuthValidate(auth));
},
updatePathname(pathname) {
dispatch(actionCreators.updatePathname(pathname));
},
updateSelectedKeys(keys) {
dispatch(actionCreators.updateSelectedKeys(keys));
},
updateOpenKeys(keys) {
dispatch(actionCreators.updateOpenKeys(keys));
},
updateComplexConfig(config) {
dispatch(actionCreators.updateComplexConfig(config));
},
updateComplexPathName(pathname) {
dispatch(actionCreators.updateComplexPathName(pathname));
},
logout() {
dispatch(actionCreators.logout());
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Menu);
@import '~antd/es/style/themes/default.less';
@panda-prefix-cls: ~'@{ant-prefix}-layout-slider';
@primary-color: #1685ff;
@primary-1: color(~`colorPalette('@{primary-color}', 1) `); // replace tint(@primary-color, 90%)
@primary-2: color(~`colorPalette('@{primary-color}', 2) `); // replace tint(@primary-color, 80%)
@primary-3: color(~`colorPalette('@{primary-color}', 3) `); // unused
@primary-4: color(~`colorPalette('@{primary-color}', 4) `); // unused
@primary-5: color(
~`colorPalette('@{primary-color}', 5) `
); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%)
@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color
@primary-7: color(~`colorPalette('@{primary-color}', 7) `); // replace shade(@primary-color, 5%)
@primary-8: color(~`colorPalette('@{primary-color}', 8) `); // unused
@primary-9: color(~`colorPalette('@{primary-color}', 9) `); // unused
@primary-10: color(~`colorPalette('@{primary-color}', 10) `); // unused
@slider-light: #fff;
@color-black: #fff;
.@{panda-prefix-cls} {
overflow: hidden;
flex: 0 0 80px;
max-width: 80px;
min-width: 80px;
width: 80px;
background-color: @layout-header-background;
transition: background 0.3s, width 0.3s cubic-bezier(0.2, 0, 0, 1) 0s;
&-logo{
display: none;
}
&-fixed {
position: fixed !important;
top: 46px;
left: 0;
z-index: 600;
height: calc(100% - 46px);
// overflow: auto;
overflow-x: hidden;
box-shadow: 2px 0 8px 0 rgb(29 35 41 / 5%);
transition: all 0.2s;
}
&-collapsed {
flex: 0 0 48px;
max-width: 48px;
min-width: 48px;
width: 48px;
transition: background 0.3s, width 0.5s cubic-bezier(0.2, 0, 0, 1) 0s;
.sliderMenu {
.splitLine {
width: 48px;
}
}
}
&-children {
display: flex;
flex-direction: column;
height: 100%;
}
&-wrapper {
flex: 1 1 0%;
}
&-menu {
position: relative;
min-height: 100%;
&-item {
height: 74px;
display: flex;
align-items: center;
text-align: center;
width: 100%;
justify-content: center;
cursor: pointer;
transition: border-color 0.3s, background 0.3s,
padding 0.1s cubic-bezier(0.215, 0.61, 0.355, 1);
a {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
img {
width: 22px;
height: 22px;
opacity: 0.7;
}
}
&-icon {
transition: font-size 0.15s cubic-bezier(0.215, 0.61, 0.355, 1),
margin 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.3s;
font-size: 14px;
svg {
path,
rect,
circle,
.cls-1 {
fill: hsla(0, 0%, 100%, 0.65) !important;
stroke: hsla(0, 0%, 100%, 0.65) !important;
stroke-width: 0 !important;
stroke-linecap: round;
stroke-miterlimit: 10;
}
}
}
&-text {
display: block;
color: hsla(0, 0%, 100%, 0.65);
padding-top: 4px;
max-width: 70px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
opacity: 1;
transition: opacity 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), margin 0.3s, color 0.3s;
}
&-current {
color: @color-black;
}
&.hover {
span {
color: #fff;
}
.icon {
&.fillCurrent {
svg {
path {
fill: hsla(0, 0%, 100%, 0.65) !important;
stroke: hsla(0, 0%, 100%, 0.65) !important;
}
}
}
// svg {
// path:not(.st0) {
// fill: #fff!important;
// }
// path.st0 {
// fill:url(#SVGID_1_)!important;
// }
// path.st1 {
// fill:url(#SVGID_2_)!important;
// }
// }
}
}
&-active {
background: @primary-color;
box-shadow: 0px 1px 0px 0px rgba(238, 238, 238, 0.17);
span {
color: #ffffff;
}
.icon {
svg {
path,
rect,
circle {
// fill: #fff!important;
}
}
}
}
}
}
}
import React, { useState } from 'react';
import classNames from 'classnames';
import styles from './index.less';
const Categories = (props) => {
const [currentIndex, setCurrentIndex] = useState(props.currentMenuIndex);
const selectCategories = (event, index) => {
event.preventDefault();
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
setCurrentIndex(index);
// eslint-disable-next-line no-unused-expressions
props.onChange && props.onChange(index);
};
return (
<div
className={classNames(styles['menu-categories'], {
[styles['min-cateorites']]: props.mode,
})}
>
{(props.data || []).map((item, index) => {
const categorieCls = classNames(
styles['categorie-name'],
styles.btn,
currentIndex === index ? styles.active : '',
);
return (
<div
className={categorieCls}
key={item.name}
onClick={(event) => selectCategories(event, index)}
>
{/* eslint-disable-next-line jsx-a11y/alt-text */}
<img src={item.extData.icon} />
<span>{item.extData.label}</span>
</div>
);
})}
</div>
);
};
export default Categories;
import React from 'react';
import styles from './index.less';
const Menu = (props) => {
const renderTitle = (title) => <h4 className={styles.title}>{title}</h4>;
const renderMenuItem = (data) => {
let menuItem = [];
if (!data) {
return;
}
// eslint-disable-next-line no-prototype-builtins
if (!data.hasOwnProperty('routes')) {
menuItem = (
<div
className={styles['main-menus-recentAll-menu-group-items-menu-item']}
onClick={(event) => props.handleClick(event, data)}
>
<img src={data.extData.icon} alt="" />
<a
className={`${styles['main-menus-recentAll-menu-group-items-menu-item-name']} ${styles.pad}`}
>
{data.name}
</a>
</div>
);
} else {
data.routes.forEach((item, index) => {
const render = (
<div
className={styles['main-menus-recentAll-menu-group-items-menu-item']}
key={item.name}
onClick={(event) => props.handleClick(event, item)}
>
<img src={item.extData.icon} alt="" />
<a
className={`${styles['main-menus-recentAll-menu-group-items-menu-item-name']} ${styles.pad}`}
>
{item.name}
</a>
</div>
);
menuItem.push(render);
});
}
// eslint-disable-next-line consistent-return
return menuItem;
};
return (
<div className={styles['main-menus']}>
<div className={styles['main-menus-recentAll']}>
<div className={styles['main-menus-recentAll-menu-group']}>
{(props.data.routes || []).map((item, index) => (
<div className={styles['main-menus-recentAll-menu-group-items']} key={item.name}>
{renderTitle(item.name)}
{renderMenuItem(item)}
</div>
))}
</div>
</div>
</div>
);
};
export default Menu;
import React, { useState } from 'react';
import classNames from 'classnames';
import styles from './min.less';
const Categories = (props) => {
const [currentIndex, setCurrentIndex] = useState(props.currentMenuIndex);
const selectCategories = (event, index) => {
event.preventDefault();
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
setCurrentIndex(index);
// eslint-disable-next-line no-unused-expressions
props.onChange && props.onChange(index);
};
return (
<div
className={classNames(styles['menu-categories'], {
[styles['min-cateorites']]: props.mode,
})}
>
{(props.data || [])
.filter((item) => !item.hideInMenu)
.map((item, index) => {
const categorieCls = classNames(
styles['categorie-name'],
styles.btn,
currentIndex === index ? styles.active : '',
);
return (
<div
className={categorieCls}
key={item.name}
onClick={(event) => selectCategories(event, index)}
>
{/* eslint-disable-next-line jsx-a11y/alt-text */}
<img src={item.extData.icon} />
<span>{item.extData.label}</span>
</div>
);
})}
</div>
);
};
export default Categories;
import React, { useEffect, useRef, useState, useContext } from 'react';
import classNames from 'classnames';
import propTypes from 'prop-types';
import KeyCode from 'rc-util/lib/KeyCode';
import Icon from '@ant-design/icons';
import Categories from './MinCategories';
import './min.less';
import { ConfigProvider } from 'antd';
// eslint-disable-next-line import/extensions
import { events } from '@wisdom-utils/utils/lib/helpers';
const ThLarge = (props) => (
<svg viewBox="0 0 1024 1024" version="1.1" width="14" height="14">
<path
d="M592 64h384c26.51 0 48 21.49 48 48v320c0 26.51-21.49 48-48 48H592c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48z m-160 0H48C21.49 64 0 85.49 0 112v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zM0 592v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H48c-26.51 0-48 21.49-48 48z m592 368h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H592c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48z"
fill="#737f97"
/>
</svg>
);
const ThLargeIcon = (props) => <Icon component={ThLarge} {...props} />;
const MinPanel = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls('panel-min');
const getCategories = () => {
let { data } = props;
// eslint-disable-next-line no-prototype-builtins
data = data.filter((item) => item.hasOwnProperty('extData'));
return data;
};
const categories = getCategories();
const wcls = categories.length <= 10 ? 'w110' : 'w210';
const panelCls = classNames(
[`${prefixCls}-mainPane`],
props.visible ? `${prefixCls}-mainPane-visible` : `${prefixCls}-mainPane-hidden`,
[`${prefixCls}-mainPane-${wcls}`],
);
const domRef = useRef();
// eslint-disable-next-line no-debugger;
const [currentMenu, setCurrentMenu] = useState(null);
useEffect(() => {
setCurrentMenu(props.data[props.currentMenuIndex]);
}, [props.data, props.currentMenuIndex]);
// eslint-disable-next-line no-underscore-dangle
let _clickEvents = null;
const handleKeyDown = (event) => {
if (event.keyCode === KeyCode.ESC) {
const { onClose } = props;
event.stopPropagation();
if (onClose) {
onClose(event);
}
}
};
const domFocus = () => {
if (domRef) {
domRef.current.focus();
}
};
const handleDocumentClick = (e) => {
if (props.visible) {
const node = domRef && domRef.current;
if (
node &&
(node === e.target ||
node.contains(e.target) ||
(e.target !== document && !document.documentElement.contains(e.target)))
) {
return;
}
// eslint-disable-next-line no-unused-expressions
props.onClose && props.onClose(e);
}
};
const addDocumentEvents = () => {
if (props.canCloseByOutSideClick) {
_clickEvents = events.on(document, 'click', handleDocumentClick);
}
};
const removeDocumentEvents = () => {
_clickEvents.off();
_clickEvents = null;
};
const selectItem = (event, item) => {
// eslint-disable-next-line no-unused-expressions
props.onSelect && props.onSelect(item);
};
const handleCategories = (index) => {
setCurrentMenu(props.data[index]);
// eslint-disable-next-line no-unused-expressions
props.onChange && props.onChange(index);
};
useEffect(() => {
if (props.visible) {
domFocus();
}
addDocumentEvents();
return () => removeDocumentEvents();
}, [props.visible]);
return (
<div
className={panelCls}
tabIndex="-1"
onKeyDown={(event) => (props.visible && props.keyboard ? handleKeyDown(event) : undefined)}
ref={domRef}
>
<div className={`${prefixCls}-mainPane-main`}>
<div className={`${prefixCls}-mainPane-main-left`}>
<Categories
mode="mini"
data={categories}
onChange={handleCategories}
currentMenuIndex={props.currentMenuIndex}
/>
</div>
</div>
</div>
);
};
MinPanel.propTypes = {
visible: propTypes.bool,
keyboard: propTypes.bool,
onClose: propTypes.func,
canCloseByOutSideClick: propTypes.bool,
};
MinPanel.defaultProps = {
visible: false,
keyboard: true,
canCloseByOutSideClick: true,
onClose: () => {},
};
export default MinPanel;
import React, { useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import propTypes from 'prop-types';
import KeyCode from 'rc-util/lib/KeyCode';
import { Spin } from 'antd';
import Icon, { MenuOutlined } from '@ant-design/icons';
import { events } from '@wisdom-utils/utils/lib/helpers';
import Categories from './Categories';
import styles from './index.less';
import Menu from './Menu';
// eslint-disable-next-line import/extensions
const ThLarge = (props) => (
<svg viewBox="0 0 1024 1024" version="1.1" width="14" height="14">
<path
d="M592 64h384c26.51 0 48 21.49 48 48v320c0 26.51-21.49 48-48 48H592c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48z m-160 0H48C21.49 64 0 85.49 0 112v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zM0 592v320c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H48c-26.51 0-48 21.49-48 48z m592 368h384c26.51 0 48-21.49 48-48V592c0-26.51-21.49-48-48-48H592c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48z"
fill="#737f97"
/>
</svg>
);
const ThLargeIcon = (props) => <Icon component={ThLarge} {...props} />;
const Panel = (props) => {
const panelCls = classNames(styles.mainPane, props.visible ? styles.visible : styles.hidden);
const domRef = useRef();
// eslint-disable-next-line no-debugger;
const [currentMenu, setCurrentMenu] = useState(null);
useEffect(() => {
setCurrentMenu(props.data[props.currentMenuIndex]);
}, [props.data, props.currentMenuIndex]);
// eslint-disable-next-line no-underscore-dangle
let _clickEvents = null;
const handleKeyDown = (event) => {
if (event.keyCode === KeyCode.ESC) {
const { onClose } = props;
event.stopPropagation();
if (onClose) {
onClose(event);
}
}
};
const domFocus = () => {
if (domRef) {
domRef.current.focus();
}
};
const handleDocumentClick = (e) => {
if (props.visible) {
const node = domRef && domRef.current;
if (
node &&
(node === e.target ||
node.contains(e.target) ||
(e.target !== document && !document.documentElement.contains(e.target)))
) {
return;
}
// eslint-disable-next-line no-unused-expressions
props.onClose && props.onClose(e);
}
};
const addDocumentEvents = () => {
if (props.canCloseByOutSideClick) {
_clickEvents = events.on(document, 'click', handleDocumentClick);
}
};
const removeDocumentEvents = () => {
_clickEvents.off();
_clickEvents = null;
};
const getCategories = () => {
let { data } = props;
// eslint-disable-next-line no-prototype-builtins
data = data.filter((item) => item.hasOwnProperty('extData'));
return data;
};
const handleCategories = (index) => {
setCurrentMenu(props.data[index]);
// eslint-disable-next-line no-unused-expressions
props.onChange && props.onChange(index);
};
const selectItem = (event, item) => {
// eslint-disable-next-line no-unused-expressions
props.onSelect && props.onSelect(item);
};
useEffect(() => {
if (props.visible) {
domFocus();
}
addDocumentEvents();
return () => removeDocumentEvents();
}, [props.visible]);
return (
<div
className={panelCls}
tabIndex="-1"
onKeyDown={(event) => (props.visible && props.keyboard ? handleKeyDown(event) : undefined)}
ref={domRef}
>
<div className={styles.header}>
<ThLargeIcon />
<div className={styles['header-title']}>切换子系统</div>
<span className={styles.subheader}>
<MenuOutlined />
子系统功能一览
</span>
<span className={styles.marks}>
<img
src="https://panda-water.cn/web4/assets/images/waterMarks/%E8%8F%9C%E5%8D%95%E6%B0%B4%E5%8D%B0.SVG"
alt=""
/>
</span>
</div>
<div className={styles.main}>
<div className={styles['main-left']}>
<Categories
data={getCategories()}
onChange={handleCategories}
currentMenuIndex={props.currentMenuIndex}
/>
</div>
<div className={styles['main-menus']}>
<Spin spinning={!currentMenu}>
<Menu data={currentMenu || []} handleClick={selectItem} />
</Spin>
</div>
</div>
</div>
);
};
Panel.propTypes = {
visible: propTypes.bool,
keyboard: propTypes.bool,
onClose: propTypes.func,
canCloseByOutSideClick: propTypes.bool,
};
Panel.defaultProps = {
visible: false,
keyboard: true,
canCloseByOutSideClick: true,
onClose: () => {},
};
export default Panel;
import Panel from './Panel';
import MinPanel from './MinPanel';
export { Panel, MinPanel };
@import '~antd/es/style/themes/default.less';
@dark-menu-catatories-color: rgba(255, 255, 255, 0.65);
.mainPane {
position: absolute;
&.hidden {
// display: none;
flex: 1 1 0%;
// position: relative;
z-index: 5;
background-color: rgb(247, 247, 247);
// min-width: 490px;
// max-width: 980px;
width: 0;
overflow: hidden;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
transform: translateX(-1240px);
}
&.visible {
display: block;
flex: 1 1 0%;
position: absolute;
z-index: 30;
background-color: #001529;
min-width: 500px;
max-width: 640px;
overflow: hidden;
height: 100%;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
}
.header {
width: 100%;
height: 40px;
line-height: 20px;
text-align: center;
padding: 0 0 0 18px;
display: inline-flex;
align-items: center;
&-title {
color: #fff;
padding-left: 12px;
}
.subheader {
color: #fff;
display: flex;
align-items: center;
margin-left: 20px;
:global(.@{ant-prefix}icon-menu) {
color: #737f97;
padding-right: 12px;
}
}
.marks {
position: absolute;
right: 12px;
top: 8px;
}
}
.main {
// padding: 32px 0px 0px 32px;
padding: 0px 0px 0px 4px;
height: 100%;
overflow: hidden;
box-sizing: border-box;
display: flex;
&-left {
// padding-top: 32px;
width: 125px;
height: 100%;
overflow: hidden auto;
box-sizing: border-box;
.menu-categories {
&.min-cateorites {
position: relative;
top: 46px;
}
.categorie-name {
border-width: 0px 0px 0px 1px;
border-top-style: initial;
border-right-style: initial;
border-bottom-style: initial;
border-top-color: initial;
border-right-color: initial;
border-bottom-color: initial;
border-image: initial;
border-left-style: solid;
border-left-color: rgb(222, 222, 222);
display: flex;
align-items: center;
&.btn {
box-sizing: border-box;
outline: medium;
background: none;
cursor: pointer;
font-family: inherit;
font-size: inherit;
text-decoration: none;
transition: all 0.3s ease-out 0s;
border: 1px solid transparent;
vertical-align: middle;
text-align: left;
color: rgb(85, 85, 85);
// display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0px 12px;
height: 40px;
line-height: 40px;
&:hover {
border-left: 2px solid @primary-color;
span {
color: #fff;
}
}
&:hover,
&:link:hover,
&:visited:hover {
color: #273150;
}
}
img {
width: 17px;
height: 17px;
}
span {
margin-left: 12px;
color: @dark-menu-catatories-color;
}
&.active {
background-color: @primary-color;
// border-left: 2px solid @primary-2;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
}
}
}
}
&-menus {
flex: 1 1 0%;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: row;
margin-left: 12px;
&::-webkit-scrollbar {
width: 0px;
height: 0px;
}
&-recentAll {
flex: 1 1 0%;
padding: 0px 32px 32px 0px;
overflow: auto;
&-menu-group {
margin-bottom: 12px;
columns: 120px 3;
column-gap: 12px;
&-items {
display: inline-block;
margin-bottom: 20px;
width: 100%;
break-inside: avoid;
.title {
margin: 0px 0px 8px 0px;
padding: 0px;
height: 30px;
line-height: 30px;
font-size: 12px;
font-weight: 600;
color: #fff;
transition: all 250ms linear 0s;
}
&-menu-item {
position: relative;
transition: all 300ms ease 0s;
display: flex;
align-items: center;
img {
width: 14px;
height: 14px;
}
&-name {
box-sizing: border-box;
outline: medium;
background: none;
cursor: pointer;
font-family: inherit;
font-size: inherit;
text-decoration: none;
transition: all 0.3s ease-out 0s;
border: 1px solid transparent;
vertical-align: middle;
text-align: left;
color: rgba(255, 255, 255, 0.65);
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0px 12px;
height: 32px;
line-height: 30px;
&.pad {
padding: 0px 4px;
}
&:link,
&:visited,
&:hover {
// color: rgb(85, 85, 85);
color: #fff;
}
}
}
}
}
}
}
}
}
@import '~antd/es/style/themes/default.less';
@dark-menu-catatories-color: rgba(255, 255, 255, 0.65);
@primary-color: #1685ff;
@panda-prefix-cls: ~'@{ant-prefix}-panel-min';
.@{panda-prefix-cls}-mainPane {
position: absolute;
&-hidden {
// display: none;
flex: 1 1 0%;
// position: relative;
z-index: 5;
background-color: rgb(247, 247, 247);
// min-width: 490px;
// max-width: 980px;
width: 0;
overflow: hidden;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
transform: translateX(-1240px);
}
&-visible {
display: block;
flex: 1;
position: absolute;
z-index: 610;
background-color: rgba(0, 21, 41, 0.99);
min-width: 210px;
max-width: 210px;
overflow: hidden;
height: 100%;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
}
&-w110 {
min-width: 110px;
max-width: 110px;
}
&-w210 {
min-width: 210px;
max-width: 210px;
}
&-header {
width: 100%;
height: 40px;
line-height: 20px;
text-align: center;
padding: 0 0 0 18px;
display: inline-flex;
align-items: center;
&-title {
color: #fff;
padding-left: 12px;
}
.subheader {
color: #fff;
display: flex;
align-items: center;
margin-left: 20px;
:global(.@{ant-prefix}icon-menu) {
color: #737f97;
padding-right: 12px;
}
}
.marks {
position: absolute;
right: 12px;
top: 8px;
}
}
&-main {
// padding: 32px 0px 0px 32px;
padding: 0px 0px 0px 4px;
height: 100%;
overflow: hidden;
box-sizing: border-box;
display: flex;
&-left {
// padding-top: 32px;
// width: 125px;
height: 100%;
overflow: hidden auto;
box-sizing: border-box;
.menu-categories {
&.min-cateorites {
position: relative;
top: 48px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.categorie-name {
border-width: 0px 0px 0px 1px;
border-top-style: initial;
border-right-style: initial;
border-bottom-style: initial;
border-top-color: initial;
border-right-color: initial;
border-bottom-color: initial;
border-image: initial;
border-left-style: solid;
border-left-color: rgb(222, 222, 222);
display: flex;
align-items: center;
&.btn {
box-sizing: border-box;
outline: medium;
background: none;
cursor: pointer;
font-family: inherit;
font-size: inherit;
text-decoration: none;
transition: all 0.3s ease-out 0s;
border: 1px solid transparent;
vertical-align: middle;
text-align: left;
color: #555555;
width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 12px 12px;
height: 74px;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 2px;
&:hover {
// border-left: 2px solid @primary-color;
// span {
// color: #fff;
// }
span {
color: #fff;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
}
}
&:hover,
&:link:hover,
&:visited:hover {
color: #273150;
}
}
img {
width: 22px;
height: 22px;
}
span {
// margin-left: 12px;
padding-top: 4px;
color: @dark-menu-catatories-color;
opacity: 1;
transition: opacity 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), margin 0.3s, color 0.3s;
}
&.active {
background-color: rgba(0, 0, 0, 0.2);
// border-left: 2px solid @primary-2;
transition: all 0.25s cubic-bezier(0, 0, 0.2, 1) 0s;
span {
color: #fff;
}
}
}
}
}
&-menus {
flex: 1 1 0%;
height: 100%;
overflow: hidden;
display: flex;
flex-direction: row;
margin-left: 12px;
&::-webkit-scrollbar {
width: 0px;
height: 0px;
}
&-recentAll {
flex: 1 1 0%;
padding: 0px 32px 32px 0px;
overflow: auto;
&-menu-group {
margin-bottom: 12px;
columns: 120px 3;
column-gap: 12px;
&-items {
display: inline-block;
margin-bottom: 20px;
width: 100%;
break-inside: avoid;
.title {
margin: 0px 0px 8px 0px;
padding: 0px;
height: 30px;
line-height: 30px;
font-size: 12px;
font-weight: 600;
color: #fff;
transition: all 250ms linear 0s;
}
&-menu-item {
position: relative;
transition: all 300ms ease 0s;
display: flex;
align-items: center;
img {
width: 14px;
height: 14px;
}
&-name {
box-sizing: border-box;
outline: medium;
background: none;
cursor: pointer;
font-family: inherit;
font-size: inherit;
text-decoration: none;
transition: all 0.3s ease-out 0s;
border: 1px solid transparent;
vertical-align: middle;
text-align: left;
color: rgba(255, 255, 255, 0.65);
display: block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0px 12px;
height: 32px;
line-height: 30px;
&.pad {
padding: 0px 4px;
}
&:link,
&:visited,
&:hover {
// color: rgb(85, 85, 85);
color: #fff;
}
}
}
}
}
}
}
}
}
import React, { useContext, useEffect } from 'react';
import { ConfigProvider } from 'antd';
import propTypes from 'prop-types';
import Icon from '@ant-design/icons';
import warning from 'warning';
import SlideMenu from '../components/SlideMenu';
import WrapContent from '@wisdom-utils/components/lib/AppLayout/layouts/WrapContent';
import Header from '@wisdom-utils/components/lib/AppLayout/layouts/Header';
import Footer from '@wisdom-utils/components/lib/AppLayout/layouts/Footer';
import TopNavHeader from '@wisdom-utils/components/lib/AppLayout/components/TopNavHeader';
import PageContainer from '@wisdom-utils/components/lib/AppLayout/components/PageContainer';
import { helpers } from '@wisdom-utils/utils';
import { getBreadcrumbProps } from '@wisdom-utils/components/lib/AppLayout/layouts/utils/getBreadcrumbProps';
import getMenuData from '@wisdom-utils/components/lib/AppLayout/layouts/utils/getMenuData';
import { findPathByLeafId } from '@wisdom-utils/components/lib/AppLayout/helpers';
const { renderRoutes } = helpers;
import { MinPanel } from '@wisdom-utils/components/lib/AppLayout/components/SliderPanel';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import RouteContext from '@wisdom-utils/components/lib/AppLayout/layouts/RouteContext';
import { getPageTitleInfo } from '@wisdom-utils/components/lib/AppLayout/layouts/getPageTitle';
import omit from 'omit.js';
import classNames from 'classnames';
import useDocumentTitle from '@wisdom-utils/components/lib/AppLayout/layouts/hooks/useDocumentTitle';
import defaultSettings from '@wisdom-utils/components/lib/AppLayout/layouts/defaultSettings';
import isBrowser from '@wisdom-utils/components/lib/AppLayout/layouts/utils/isBrowser';
const homeSvg = () => (
<svg
t="1631169883330"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2203"
width="20"
height="20"
>
<path
d="M423.9 487H221.7c-34.9 0-63.4-28.4-63.4-63.4V221.5c0-34.9 28.4-63.4 63.4-63.4h202.2c34.9 0 63.4 28.4 63.4 63.4v202.2c-0.1 34.9-28.5 63.3-63.4 63.3z m0-63.3v31.7-31.7zM221.7 221.5v202.2h202.1l0.1-202.2H221.7zM803.1 487H600.9c-34.9 0-63.4-28.4-63.4-63.4V221.5c0-34.9 28.4-63.4 63.4-63.4h202.2c34.9 0 63.4 28.4 63.4 63.4v202.2c0 34.9-28.5 63.3-63.4 63.3z m0-63.3v31.7-31.7zM600.9 221.5v202.2H803l0.1-202.2H600.9zM423.9 865.8H221.7c-34.9 0-63.4-28.4-63.4-63.4V600.3c0-34.9 28.4-63.4 63.4-63.4h202.2c34.9 0 63.4 28.4 63.4 63.4v202.2c-0.1 34.9-28.5 63.3-63.4 63.3z m0-63.3v31.7-31.7zM221.7 600.3v202.2h202.1l0.1-202.2H221.7zM736.9 865.8h-69.7c-71.4 0-129.6-58.1-129.6-129.6v-69.7c0-71.4 58.1-129.6 129.6-129.6h69.7c71.4 0 129.6 58.1 129.6 129.6v69.7c0 71.5-58.2 129.6-129.6 129.6z m-69.8-265.5c-36.5 0-66.2 29.7-66.2 66.2v69.7c0 36.5 29.7 66.2 66.2 66.2h69.7c36.5 0 66.2-29.7 66.2-66.2v-69.7c0-36.5-29.7-66.2-66.2-66.2h-69.7z"
fill="#B2B2B2"
/>
</svg>
);
const HomeIcon = (props) => <Icon component={homeSvg} {...props} style={{ marginRight: '0px' }} />;
const defaultPageTitleRender = (pageProps, props) => {
const { pageTitleRender } = props;
const pageTitleInfo = getPageTitleInfo(pageProps);
if (pageTitleRender === false) {
return {
title: props.title || '',
id: '',
pageName: '',
};
}
if (pageTitleRender) {
const title = pageTitleRender(pageProps, pageTitleInfo.title, pageTitleInfo);
if (typeof title === 'string') {
return {
...pageTitleInfo,
title,
};
}
warning(typeof title === 'string', 'layout: renderPageTitle return value should be a string');
}
return pageTitleInfo;
};
const headerRender = (props) => {
if (props.headerRender === false) {
return null;
}
return <Header {...props} />;
};
const footerRender = (props) => {
if (props.footerRender === false) {
return null;
}
if (props.footerRender) {
return props.footerRender({ ...props }, <Footer />);
}
return null;
};
const renderSiderMenu = (props) => {
const { menuRender } = props;
if (menuRender === false) {
return null;
}
const defaultDom = <SlideMenu {...props} />;
if (menuRender) {
return menuRender(props, defaultDom);
}
return defaultDom;
};
const getPaddingLeft = (hasLeftPadding, collapsed, siderWidth) => {
if (hasLeftPadding) {
return collapsed ? 48 : siderWidth;
}
return 0;
};
const BasicLayout = (props) => {
const {
children,
route,
style,
contentStyle,
siderWidth = 80,
location = { pathname: '/' },
menu,
handerMapContentRender,
subMenuItemRender,
menuItemRender,
menuHeaderRender,
currentMenuIndex,
onMenuHeaderClick,
onMenuPanelItemClick,
onPageChange,
disableContentMargin,
isChildrenLayout: propsIsChildrenLayout,
menuDataRender,
formatMessage,
} = props || {};
const context = useContext(ConfigProvider.ConfigContext);
const prefixCls = props.prefixCls ?? context.getPrefixCls();
const [tabActiveKey, setTabActiveKey] = React.useState('1');
const [selectedKey, setSelectedKey] = React.useState([]);
const [subRoutes, setSubRoutes] = React.useState([]);
const [currentRoute, setCurrentRoute] = React.useState({});
const [selectIndex, setSelectIndex] = React.useState(-1);
const [visible, setVisible] = React.useState(false);
const [activeMenu, setActiveMenu] = useMergedState(() => 0, {
value: currentMenuIndex,
onChange: onMenuPanelItemClick,
});
const [collapsed, onCollapse] = useMergedState(() => false, {
value: props.collapsed,
onChange: props.onCollapse,
});
const menuInfoData = React.useMemo(
() => getMenuData(route?.routes || [], menu, formatMessage, menuDataRender),
[formatMessage, menu, menuDataRender, route?.routes],
);
const { breadcrumb = {}, breadcrumbMap, menuData = [] } = menuInfoData || {};
const defaultProps = omit(
{
prefixCls,
...props,
siderWidth,
formatMessage,
breadcrumb,
},
['className', 'style', 'breadcrumbRender'],
);
const pageTitleInfo = defaultPageTitleRender(
{
pathname: location.pathname,
...defaultProps,
breadcrumbMap,
},
props,
);
const breadcrumbProps = getBreadcrumbProps(
{
...defaultProps,
breadcrumbRender: props.breadcrumbRender,
breadcrumbMap,
},
props,
);
const onMenuClick = (current, routes) => {
setTabActiveKey(current.path);
if (current.routes) {
setSelectedKey([current.routes[0].href]);
}
setSubRoutes(routes);
};
const _onMenuHeaderClick = () => {
onMenuHeaderClick && onMenuHeaderClick();
setVisible(!visible);
};
const siderMenuDom = renderSiderMenu(
Object.assign(
{},
{
...defaultProps,
collapsed,
onCollapse,
route: props.route,
active: selectIndex,
onActiveChange: setSelectIndex,
menu,
menuItemRender,
menuHeaderRender,
onMenuClick,
onMenuHeaderClick: _onMenuHeaderClick,
},
),
);
const headerDom = headerRender({
...defaultProps,
hasSiderMenu: !!siderMenuDom,
collapsed,
onCollapse,
});
const footerDom = footerRender({
collapsed,
...defaultProps,
});
const hasLeftPadding = true;
const { isChildrenLayout: contextIsChildrenLayout } = useContext(RouteContext);
const isChildrenLayout =
propsIsChildrenLayout !== undefined ? propsIsChildrenLayout : contextIsChildrenLayout;
const leftSiderWidth = getPaddingLeft(!!hasLeftPadding, collapsed, siderWidth);
const genLayoutStyle = {
position: 'relative',
};
if (isChildrenLayout || (contentStyle && contentStyle.minHeight)) {
genLayoutStyle.minHeight = 0;
}
const baseClassName = `${prefixCls}-basic-layout`;
const contentClassName = classNames(`${baseClassName}-content`, {
[`${baseClassName}-has-header`]: headerDom,
[`${baseClassName}-content-disable-margin`]: disableContentMargin,
});
const [hasFooterToolbar, setHasFooterToolbar] = React.useState(false);
useEffect(() => {
const newRoutes =
(route &&
route.routes &&
Array.isArray(route.routes) &&
route.routes.filter((item) => !item.hideInMenu)[currentMenuIndex]) ||
{};
if (!_.isEqual(currentRoute, newRoutes)) {
// setCurrentRoute({});
setSelectIndex(-1);
setCurrentRoute(newRoutes);
}
}, [route, currentMenuIndex]);
useEffect(() => {
const initSelectRoute = findPathByLeafId(
`${(props.location && props.location.pathname) || ''}`,
[currentRoute],
'',
'path',
true,
);
const parentMenuName =
initSelectRoute && initSelectRoute.parent && initSelectRoute.parent.label;
if (parentMenuName) {
let currentChildrenRoute = currentRoute.routes.find((item) => item.name === parentMenuName);
if (!currentChildrenRoute) {
currentChildrenRoute = initSelectRoute;
}
let childrenName = currentChildrenRoute ? currentChildrenRoute.name : parentMenuName;
if (currentChildrenRoute.routes) {
const active = currentChildrenRoute.routes.find(
(item) => item.name === initSelectRoute.name,
);
setTabActiveKey(active.path);
} else {
setTabActiveKey(currentChildrenRoute.path);
}
const initSelectIndex = currentRoute.routes.findIndex((item) => item.name === childrenName);
setSelectIndex(initSelectIndex);
currentChildrenRoute && currentChildrenRoute.routes
? setSubRoutes(currentChildrenRoute.routes)
: setSubRoutes([currentChildrenRoute]);
} else {
let url =
props.config && props.config.hasOwnProperty('get') && props.config.get('homepage')
? _.isString(props.config.get('homepage'))
? props.config.get('homepage')
: props.config.get('homepage.url')
: '';
if (!props.config.get('home')) {
url = `civweb4/${url.replace(/^\//, '').replace(/^civweb4\//, '')}`;
}
setSelectIndex(-1);
setSubRoutes([
{
icon: <HomeIcon />,
path: `/${url}`,
name: '首页',
},
]);
}
}, []);
useEffect(() => {
window.share &&
window.share.event &&
window.share.event.on(
'event:updateCurrentChildrenRoutes',
({ currentPath, currentRoute, selectedIndex }) => {
currentRoute && currentRoute.parent && currentRoute.parent.routes
? setSubRoutes(currentRoute.parent.routes)
: !currentRoute.parent
? setSubRoutes(currentRoute.routes)
: setSubRoutes([currentRoute]);
setSelectIndex(selectedIndex);
setTabActiveKey(currentPath);
},
);
window.share &&
window.share.event &&
window.share.event.on('event:favitor', ({ icon, name, path }) => {
setSubRoutes([
{
icon: <HomeIcon />,
path: path,
name: name,
},
]);
});
window.share &&
window.share.event &&
window.share.event.on('goHome', (url) => {
setSubRoutes([
{
icon: <HomeIcon />,
path: url,
name: '首页',
},
]);
setTabActiveKey(url);
window.history.pushState(null, '', `/civbase${url}`);
});
return () => {
window.share &&
window.share.event &&
window.share.event.removeAllListeners('event:updateCurrentChildrenRoutes');
window.share && window.share.event && window.share.event.removeAllListeners('event:favitor');
window.share && window.share.event && window.share.event.removeAllListeners('goHome');
};
}, []);
useEffect(() => {
if (selectIndex !== -1 && currentRoute && currentRoute.hasOwnProperty('routes')) {
const routes = currentRoute.routes[selectIndex];
if (routes) {
if (routes && routes.routes) {
const route =
routes &&
routes.routes &&
routes.routes.find(
(item) => item.path === decodeURI(window.location.pathname.replace('/civbase', '')),
);
if (route && route.path) {
setTabActiveKey(route.path);
}
}
}
}
onPageChange && onPageChange(props.location);
}, [props.location, location.pathname.search]);
useDocumentTitle(pageTitleInfo, props.title || false);
return (
<RouteContext.Provider
value={{
collapsed,
currentRoute,
isChildrenLayout: true,
title: pageTitleInfo.pageName,
hasSiderMenu: !!siderMenuDom,
hasHeader: !!headerDom,
siderWidth: leftSiderWidth,
hasFooter: !!footerDom,
hasFooterToolbar,
setHasFooterToolbar,
pageTitleInfo,
}}
>
<div className={`${prefixCls}-basic-layout`}>
<div className={`${prefixCls}-basic-layout-has-slider`} style={{ minHeight: '100%' }}>
{siderMenuDom}
<div className={`${prefixCls}-layout`} style={{ width: 'calc(100% - 80px)' }}>
<MinPanel
visible={visible}
keyboard
data={route.routes || []}
onClose={() => setVisible(false)}
currentMenuIndex={activeMenu}
onChange={(index) => setActiveMenu(index)}
/>
<WrapContent
isChildrenLayout={isChildrenLayout}
className={contentClassName}
style={contentStyle}
>
<div className={`${prefixCls}-page-container-wrap`}>{headerDom}</div>
<TopNavHeader
{...props}
childrenRoutes={subRoutes}
tabActiveKey={tabActiveKey}
selectedKey={selectedKey}
onTabChange={setTabActiveKey}
onHandlerSubmenu={setSelectedKey}
/>
<PageContainer style={{ paddingTop: '0px', height: '100%' }}>
{renderRoutes(prefixCls, route.routes, props)}
{handerMapContentRender && handerMapContentRender(props)}
{/*<div id="micro-container" className="subapp-container">*/}
{/* {children}*/}
{/*</div>*/}
{children}
</PageContainer>
</WrapContent>
{footerDom}
</div>
</div>
</div>
</RouteContext.Provider>
);
};
BasicLayout.propTypes = {
logo: propTypes.node || propTypes.string,
config: propTypes.object,
onPageChange: propTypes.func,
collapsed: propTypes.bool,
onCollapse: propTypes.func,
isChildrenLayout: propTypes.bool,
footerRender: propTypes.func || propTypes.bool,
className: propTypes.string,
contentStyle: propTypes.object,
disableContentMargin: propTypes.bool,
waterMarkProps: propTypes.object,
ErrorBoundary: propTypes.any,
pageTitleRender: propTypes.func || propTypes.bool,
menuRender: propTypes.func || propTypes.bool,
menuDataRender: propTypes.func || propTypes.bool,
breadcrumbRender: propTypes.func || propTypes.bool,
itemRender: propTypes.node,
headerRender: propTypes.func || propTypes.bool,
breadcrumbProps: propTypes.object,
};
BasicLayout.defaultProps = {
...defaultSettings,
location: isBrowser() ? window.location : undefined,
};
export default BasicLayout;
@import '~antd/es/style/themes/default.less';
@primary-color: #1685ff;
@primary-1: color(~`colorPalette('@{primary-color}', 1) `); // replace tint(@primary-color, 90%)
@primary-2: color(~`colorPalette('@{primary-color}', 2) `); // replace tint(@primary-color, 80%)
@primary-3: color(~`colorPalette('@{primary-color}', 3) `); // unused
@primary-4: color(~`colorPalette('@{primary-color}', 4) `); // unused
@primary-5: color(
~`colorPalette('@{primary-color}', 5) `
); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%)
@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color
@primary-7: color(~`colorPalette('@{primary-color}', 7) `); // replace shade(@primary-color, 5%)
@primary-8: color(~`colorPalette('@{primary-color}', 8) `); // unused
@primary-9: color(~`colorPalette('@{primary-color}', 9) `); // unused
@primary-10: color(~`colorPalette('@{primary-color}', 10) `); // unused
@slider-light: #fff;
@color-black: #fff;
@panda-prefix-cls: ~'@{ant-prefix}';
.@{panda-prefix-cls}-basic-layout * {
box-sizing: border-box;
}
.@{panda-prefix-cls}-basic-layout {
display: flex;
flex-direction: column;
width: 100%;
min-height: 100%;
&-has-slider {
flex-direction: row;
display: flex;
flex: auto;
}
&-content {
position: relative;
height: calc(100vh - 82px);
margin-top: 82px;
overflow: hidden;
&.hook_web4 {
height: calc(100% - 82px);
margin-top: 82px;
}
}
}
.@{panda-prefix-cls}-layout {
position: relative;
flex: auto;
flex-direction: column;
min-height: 0;
background: #f0f2f5;
width: 100%;
}
.@{panda-prefix-cls}-global-page-header {
position: fixed;
top: 0px;
width: 100%;
left: 0px;
z-index: 999;
box-sizing: border-box;
margin: 0;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: 'tnum', 'tnum';
position: relative;
height: 46px;
background-color: #0678f5;
background-size: cover;
display: flex;
flex-direction: row;
box-sizing: border-box;
&-header {
position: absolute;
width: 100%;
display: flex;
align-items: center;
height: 100%;
padding-left: 17px;
&-logo {
display: flex;
align-items: center;
height: 100%;
padding-left: 7px;
img {
//width: 48px;
width: 42px;
height: auto;
//height: 25px;
}
}
&-title {
min-width: 200px;
font-size: 26px;
font-weight: 400;
color: #ffffff;
opacity: 0.9;
padding-left: 25px;
font-family: PangMenZhengDaoBiaoTiTi;
letter-spacing: 2px;
}
}
}
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
@hn-greenColor: #00b278;
:global {
.panda-console-base-userWrapper-userInfo-header {
//右上角弹框
background-color: @hn-greenColor;
}
}
.hnlayout {
:global {
.panda-console-base-global-page-header-header-logo {
& > img {
width: 144px !important;
height: 36px;
}
}
.panda-console-base-global-page-header {
background-color: @hn-greenColor;
& > img {
display: none;
}
}
.panda-console-base-layout-slider {
background-color: #fff;
}
.panda-console-base-layout-slider-menu-item-active {
background-color: @hn-greenColor;
.panda-console-base-layout-slider-menu-item-text {
color: #fff;
}
}
.panda-console-base-layout-slider-menu-item-text {
color: #7c7c7a;
}
.panda-console-base-divider-horizontal {
border: none !important;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover svg path,
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover svg rect,
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover svg circle {
fill: @hn-greenColor !important;
stroke: @hn-greenColor !important;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover img {
filter: drop-shadow(10px 0px @hn-greenColor);
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover .menu-item-name {
color: @hn-greenColor;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab:hover .panda-console-base-tabs-tab-btn {
color: @hn-greenColor;
}
.panda-console-base-menu-item-children
:global
.panda-console-base-tabs-tab
.panda-console-base-tabs-tab-btn
.panda-console-base-dropdown-trigger
div
div {
width: 100%;
height: 100%;
}
.panda-console-base-menu-item-children .menu-item {
float: left;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-tab) {
display: flex !important;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-tab-btn) {
position: relative;
display: flex;
align-items: center;
color: #737983;
transform: scale(0.92);
}
.panda-console-base-menu-item-children
:global(.panda-console-base-tabs-tab.panda-console-base-tabs-tab-active .panda-console-base-tabs-tab-btn) {
color: @hn-greenColor !important;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-tab-btn > div > div) {
display: flex;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-nav::before) {
border-bottom: none !important;
}
.panda-console-base-menu-item-children .menu-item-name {
margin-left: 8px;
color: #737983;
transition: border-color 0.3s, color 0.3s, padding 0.1s cubic-bezier(0.215, 0.61, 0.355, 1);
}
.panda-console-base-menu-item-children .menu-item-name:hover {
color: @hn-greenColor;
}
.panda-console-base-menu-item-children :global .panda-console-base-divider-vertical {
left: 20px;
margin: 0 1px !important;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-nav-operations .ant-tabs-nav-more {
margin-right: 0px !important;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-ink-bar) {
background: @hn-greenColor !important;
}
.panda-console-base-menu-item-children :global(.panda-console-base-tabs-tab-active) {
color: @hn-greenColor !important;
}
.panda-console-base-menu-item-children
:global(.panda-console-base-tabs-tab-active .panda-pro-layouts-basic-layout-menu-item-name) {
color: @hn-greenColor !important;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab-active svg path,
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab-active svg rect,
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab-active svg circle {
fill: @hn-greenColor !important;
stroke: @hn-greenColor !important;
}
.panda-console-base-menu-item-children :global .panda-console-base-tabs-tab-active img {
filter: drop-shadow(10px 0px @hn-greenColor);
}
.panda-console-base-panel-min-mainPane-visible {
background-color: #fff;
}
.panda-console-base-panel-min-mainPane-main-left .menu-categories .categorie-name span {
color: #737983;
}
.panda-console-base-panel-min-mainPane-main-left .menu-categories .categorie-name.active {
}
.panda-console-base-panel-min-mainPane-main-left .menu-categories .categorie-name.btn:hover span {
color: #333;
}
.panda-console-base-layout-slider-menu-item:hover span {
color: #333;
}
.panda-console-base-panel-min-mainPane-main-left .menu-categories .categorie-name.active {
background: none;
span {
color: @hn-greenColor;
}
}
.panda-console-base-pro-basicLayout-content {
margin: 0;
}
.panda-console-base-pro-sider-links {
position: fixed;
bottom: 0;
z-index: 999;
display: none;
width: 50px;
}
.panda-console-base-pro-sider-logo {
display: none;
}
.test-icon {
.my-svg {
width: 18px;
height: 18px;
display: inline-block;
}
.my-img {
width: 18px;
height: 18px;
display: inline-block;
}
&>span{
}
}
.panda-console-base-pro-menu-item-title {
display: inline-block;
overflow: hidden;
text-align: left;
text-overflow: ellipsis;
vertical-align: bottom;
}
.panda-console-base-menu-sub .panda-console-base-menu-item.panda-console-base-menu-item-only-child{
padding-left: 26px!important;
}
.panda-console-base-pro-sider .panda-console-base-layout-sider-children{
margin-top: 44px;
}
}
}
import React, { useEffect, useRef, useState, Suspense } from 'react';
import { Anchor, Popover, Radio, Spin } from 'antd';
import Icon, { LoadingOutlined } from '@ant-design/icons';
import { store, helpers } from '@wisdom-utils/utils';
import classNames from 'classnames';
import Cookies from 'js-cookie';
import { connect } from 'react-redux';
import { useHistory } from '@wisdom-utils/runtime';
import KeepAlive from 'react-activation';
import AMapLoader from '@amap/amap-jsapi-loader';
import BasicLayout from './AppLayout/layouts/BasicLayout';
import RightContent from '@/components/GlobalHeader/ExtendRightContent';
import defaultSetting from '@wisdom-utils/components/lib/AppLayout/layouts/defaultSettings';
import { actionCreators } from '@/containers/App/store';
import { WEB_GIS_TYPE } from '../constants';
import SecurityLayout from './SecurityLayout';
import Site from './Site';
import layoutStyles from './BasicLayout.less';
import styls from './HN.less';
const ArcgisMap = React.lazy(() => import('../pages/map/arcgis'));
const AMap = React.lazy(() => import('../pages/map/amap'));
const CesiumMap = React.lazy(() => import('../pages/map/cesiumMap'));
const { params } = helpers;
const { getParamsV1 } = params;
const antIcon = <LoadingOutlined style={{ fontSize: 12 }} spin />;
const arrowSvg = ({ fillColor = '#fff' }) => (
<svg
t="1543324489942"
className="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/1999/xlink"
width="16"
height="16"
>
<path
d="M511.700683 639.423111 191.917496 319.596945 319.830771 319.596945 511.700683 511.715521 703.570595 319.596945 831.48387 319.596945Z"
p-id="8626"
fill={fillColor}
/>
</svg>
);
const ArrowIcon = props => <Icon component={arrowSvg} {...props} />;
const optionsWith = [{ label: '按站点', value: 'site' }, { label: '按城市', value: 'city' }];
const HOT = ['HOT', '县', '市', 'New'];
const StationsItem = (item, action, onChangeVisible) => {
const changeGroup = (event, data) => {
debugger;
action.changeGroup && action.changeGroup(event, data, onChangeVisible);
};
return (
<li key={item.groupID} style={{ marginRight: `${item.style.marginRight}px` }}>
<a
className={classNames(layoutStyles.city_select, layoutStyles.showTip)}
title={item.city}
index={item.promoteIndex}
style={{ fontSize: '13px' }}
onClick={event => changeGroup(event, item)}
>
{item.groupName}
{item.promoteTip && HOT.includes(item.promoteTip) && <div title={`${item.promoteTip}`}>{item.promoteTip}</div>}
</a>
</li>
);
};
const Stations = props => {
const data = props.data.stations;
const [targetOffset, setTargetOffset] = useState(undefined);
const cityPane = useRef(null);
const cityContent = useRef(null);
const [defaultTab, setDefaultTab] = useState('site');
useEffect(() => {
setTargetOffset(cityPane.current.clientHeight / 2);
}, []);
const handleClick = (event, link) => {
event.preventDefault();
};
const handleTabChange = event => {
setDefaultTab(event.target.value);
};
return (
<>
<div className={layoutStyles.focusStations}>
<ul>{Array.isArray(data) ? data.map(item => StationsItem(item, props.action, props.setVisible)) : null}</ul>
</div>
<Radio.Group
options={optionsWith}
optionType="button"
buttonStyle="solid"
size="small"
value={defaultTab}
onChange={handleTabChange}
style={{ marginTop: '6px' }}
/>
<div style={{ maxWidth: '520px', position: 'relative' }}>
{defaultTab === 'site' ? (
<div className={classNames(layoutStyles.city_pane, layoutStyles.station_container)} ref={cityPane}>
<Anchor
affix={false}
onClick={handleClick}
targetOffset={targetOffset}
getContainer={() => cityContent.current}
>
<ul className={layoutStyles.py}>
{props.data && props.data.siteCityList && props.data.siteCityList.letters}
</ul>
<div className={layoutStyles.cityContent} style={{ height: '335px' }} ref={cityContent}>
{props.data && props.data.siteCityList && props.data.siteCityList.content}
</div>
</Anchor>
</div>
) : (
<div className="city_pane city_container">{props.data.citySelector}</div>
)}
<Spin spinning={props.loading} tip="加载中" />
</div>
</>
);
};
const renderSite = ({ data, config, loading, setLoading, action }) => {
const [visible, setVisible] = useState(false);
let loaded = !!((data && !data.stations) || (Array.isArray(data.weathers) && data.weathers.length === 0));
if (config && config.userInfo && config.userInfo.site === '') {
loaded = false;
}
return (
<>
<Spin
indicator={antIcon}
spinning={loaded}
size="small"
style={{ marginLeft: '10px' }}
tip=""
wrapperClassName={layoutStyles.spinLoadding}
>
<>
<Popover
placement="bottomLeft"
trigger="click"
visible={visible}
content={
<Stations data={data} loading={loading} setLoading={setLoading} setVisible={setVisible} action={action} />
}
arrowPointAtCenter
overlayClassName={classNames(layoutStyles.stationsWrapper, layoutStyles.stationsTop)}
onVisibleChange={visible => setVisible(visible)}
>
{Array.isArray(data.stations) ? (
<div className={layoutStyles.toggleSite}>
<img src={require('../assets/basic/site.png')} className={layoutStyles.site} />
<span className={layoutStyles.name}>{data.currentStationName}</span>
<ArrowIcon
className={layoutStyles.arrow}
fillColor="#fff"
style={{
transform: !visible ? `rotate(0deg)` : `rotate(180deg)`,
}}
/>
</div>
) : null}
</Popover>
</>
</Spin>
{data.weathers && Object.keys(data.weathers).length > 0 ? (
<span
className={layoutStyles.weatcher}
style={{
borderLeft: data.stations.length === 0 ? '0px' : '1px solid rgba(256, 256, 256, 0.3)',
}}
>
<img src={data.weathers && data.weathers.icon} className={layoutStyles.icon} />
<span className={layoutStyles.text}>{data.weathers && data.weathers.text}</span>
</span>
) : null}
</>
);
};
const Layout = props => {
const [collapse, setCollapse] = useState(false);
const [cityData, setCityData] = useState({});
const [siteLoading, setSiteLoading] = useState(false);
const [mapMode, setMapMode] = useState(WEB_GIS_TYPE.ARCGIS);
const [siteAction, setSiteAction] = useState(() => new Site(props, setSiteLoading));
// const basename = getBaseName();
const history = useHistory();
useEffect(() => {
siteAction.setGlobalConfig(props.global);
if (!Cookies.get('token')) {
let client = props.global && props.global.hasOwnProperty('client') ? props.global.get('client') : null;
client = client !== 'undefined' && !_.isNull(client) && !_.isUndefined(client) ? client : 'city';
let generateType = props.global && props.global.hasOwnProperty('get') ? props.global.get('generateType') : null;
generateType =
!_.isNull(generateType) && !_.isUndefined(generateType) && generateType !== 'undefined'
? `&generateType=${generateType}`
: '';
history.replace(`/user/login?client=${client}${generateType}`);
props.logout();
return;
}
if (
props.global &&
props.global.userInfo &&
props.global.userInfo.token !== null &&
props.global.userInfo.loginName &&
Object.keys(cityData).length === 0
) {
siteAction.getCityStationsForUser().then(res => {
setCityData(res);
});
}
}, [props.global]);
const handlerPageChange = () => {
const params = getParamsV1(props.location.pathname);
if (params.hasOwnProperty('mapType') && params.mapType === WEB_GIS_TYPE.AMAP) {
AMapLoader.reset();
setMapMode(WEB_GIS_TYPE.AMAP);
} else {
if (!/civweb4/.test(location.pathname)) {
AMapLoader.reset();
setMapMode(WEB_GIS_TYPE.ARCGIS);
}
}
};
useEffect(() => {
window.share.event.on('updateSite', res => setCityData(res));
return () => {
window.share.event.removeAllListeners('updateSite');
};
}, []);
const handleUpdateCurrentIndex = index => {
props.updateCurrentIndex(index);
window.share && window.share.event.emit('trigger:updateMenuIndex', index);
store.set('updateMenuIndex', index);
};
const handlerIndustry = event => {
props.global.get('userInfo.site') ? history.push(`/industry`) : void 0;
};
const handlerCollapsed = () => {
setCollapse(!collapse);
};
const logo =
props.global && _.isFunction(props.global.get) && props.global.get('bannerLogo')
? props.global &&
_.isFunction(props.global.transformDevAssetsBaseURL) &&
props.global.transformDevAssetsBaseURL(props.global.get('bannerLogo'))
: defaultSetting.logo;
return (
<SecurityLayout loading {...props}>
<div className={styls.hnlayout}>
{/* <BasicLayout
route={props.route}
title={props.global.title}
logo={logo}
config={props.global}
collapsed={collapse}
onCollapse={handlerCollapsed}
currentMenuIndex={props.currentMenuIndex}
onHeaderLogo={handlerIndustry}
onPageChange={handlerPageChange}
onMenuPanelItemClick={handleUpdateCurrentIndex}
headerContentRender={() => <RightContent />}
headerSiteRender={() =>
renderSite({
data: cityData,
config: props.global,
loading: siteLoading,
setLoading: setSiteLoading,
action: siteAction,
})
}
>
<>
<Suspense fallback={<></>}>
{window.location.pathname.startsWith('/civbase/civ_3d') ? (
<KeepAlive>
<CesiumMap />
</KeepAlive>
) : window.location.pathname.startsWith('/civbase/civ_webgis') ? (
mapMode === 'AMap' ? (
<AMap />
) : (
<ArcgisMap options={{ type: 'ArcgisMap' }} />
)
) : null}
</Suspense>
<div id="micro-container" className="subapp-container">
{props.children}
</div>
</>
</BasicLayout> */}
<BasicLayout
route={props.route}
title={''}
logo={require('@/assets/basic/HN-logo.png')}
config={props.global}
currentMenuIndex={props.currentMenuIndex}
onHeaderLogo={handlerIndustry}
onPageChange={handlerPageChange}
onMenuPanelItemClick={handleUpdateCurrentIndex}
headerContentRender={() => <RightContent />}
headerSiteRender={() =>
renderSite({
data: cityData,
config: props.global,
loading: siteLoading,
setLoading: setSiteLoading,
action: siteAction,
})
}
>
<>
<Suspense fallback={<></>}>
{window.location.pathname.startsWith('/civbase/civ_3d') ? (
<KeepAlive>
<CesiumMap />
</KeepAlive>
) : window.location.pathname.startsWith('/civbase/civ_webgis') ? (
mapMode === 'AMap' ? (
<AMap />
) : (
<ArcgisMap options={{ type: 'ArcgisMap' }} />
)
) : null}
</Suspense>
<div id="micro-container" className="subapp-container">
{props.children}
</div>
</>
</BasicLayout>
</div>
</SecurityLayout>
);
};
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
settings: state.getIn(['global', 'defaultSetting']),
collapsed: state.getIn(['global', 'collapsed']),
menu: state.getIn(['global', 'menu']),
currentMenuIndex: state.getIn(['global', 'currentMenuIndex']),
flatMenu: state.getIn(['global', 'flatMenu']),
authValidate: state.getIn(['global', 'authValidate']),
pathname: state.getIn(['global', 'pathname']),
selectedKeys: state.getIn(['global', 'selectedKeys']),
openKeys: state.getIn(['global', 'openKeys']),
complexConfig: state.getIn(['global', 'complexConfig']),
complexPathName: state.getIn(['global', 'complexPathName']),
microMounted: state.getIn(['global', 'microMounted']),
});
const mapDispatchToProps = dispatch => ({
updageSetting(setting) {
dispatch(actionCreators.updageSetting(setting));
},
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
updateCurrentIndex(index) {
dispatch(actionCreators.updateCurrentIndex(index));
},
updateCollapsed(collapsed) {
dispatch(actionCreators.updateCollapsed(collapsed));
},
updateAuthValidate(auth) {
dispatch(actionCreators.updateAuthValidate(auth));
},
updatePathname(pathname) {
dispatch(actionCreators.updatePathname(pathname));
},
updateSelectedKeys(keys) {
dispatch(actionCreators.updateSelectedKeys(keys));
},
updateOpenKeys(keys) {
dispatch(actionCreators.updateOpenKeys(keys));
},
updateComplexConfig(config) {
dispatch(actionCreators.updateComplexConfig(config));
},
updateComplexPathName(pathname) {
dispatch(actionCreators.updateComplexPathName(pathname));
},
logout() {
dispatch(actionCreators.logout());
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Layout);
import LoadingComponent from '@wisdom-utils/components/lib/AppLayout/components/PageLoading';
import { dynamic } from '@wisdom-utils/runtime';
import BasicLayout from '../layouts/BasicLayout';
import BasicLayout from '../layouts/HNLayout';
import { UserLayout } from '@wisdom-utils/components/lib/AppLayout';
import BootPage from '../pages/bootpage';
import Iframe from '../pages/iframe';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment