import empty from '@/Images/others/empty.png';
import GetImg from '@/components/GetImg';
import Header from '@/components/Header';
import { QiankunMainProvider } from '@/qiankun/qiankunConfig';
import connectQiankun from '@/qiankun/state';
import useMenus from '@/qiankun/useMenu';
import { getBusinessInfo } from '@/services/businessInfoEdit';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import ProLayout from '@ant-design/pro-layout';
import { UNVMessageBox, UNVModal } from 'UNV-DESIGN';
import { Alert, Button, ConfigProvider, Space } from 'antd';
import axios from 'axios';
import React, { useEffect, useMemo, useState } from 'react';
import { history, useIntl } from 'umi';
import uniview from '../../public/uniview.png';
import AccountManage from '../Images/menuImages/AccountManage.png';
import AuthManage from '../Images/menuImages/AuthManage.png';
import Business from '../Images/menuImages/Business.png';
import CounterpartProduct from '../Images/menuImages/CounterpartProduct.png';
import ErrorFeedback from '../Images/menuImages/ErrorFeedback.png';
import EvaluatedMaintain from '../Images/menuImages/EvaluatedMaintain.png';
import GeneIcon from '../Images/menuImages/GeneIcon.png';
import KnowledgeBase from '../Images/menuImages/KnowledgeBase.png';
import quot from '../Images/menuImages/quot.png';
import OperationLog from '../Images/menuImages/OperationLog.png';
import OperatorDataUpload from '../Images/menuImages/OperatorDataUpload.png';
import PartsBatchMaintain from '../Images/menuImages/PartsBatchMaintain.png';
import ProductCatalog from '../Images/menuImages/ProductCatalog.png';
import ProductColorPage from '../Images/menuImages/ProductColorPage.png';
import ProductFileUpload from '../Images/menuImages/ProductFileUpload.png';
import ProductLaunch from '../Images/menuImages/ProductLaunch.png';
import ProductMetaData from '../Images/menuImages/ProductMetaData.png';
import ProductParamConfig from '../Images/menuImages/ProductParamConfig.png';
import ProductShelfCategory from '../Images/menuImages/ProductShelfCategory.png';
import ProductShelves from '../Images/menuImages/ProductShelves.png';
import ProjectFileUpload from '../Images/menuImages/ProjectFileUpload.png';
import ProjectPublishManagement from '../Images/menuImages/ProjectPublishManagement.png';
import ShutdownSwitch from '../Images/menuImages/ShutdownSwitch.png';
import SolutionParamConfig from '../Images/menuImages/SolutionParamConfig.png';
import SpecCheck from '../Images/menuImages/SpecCheck.png';
import SpecEdit from '../Images/menuImages/SpecEdit.png';
import SubscriptManage from '../Images/menuImages/SubscriptManage.png';
import TemplateManage from '../Images/menuImages/TemplateManage.png';
import BehaviorAnalysis from '../Images/menuImages/BehaviorAnalysis.png';
import TenderGuide from '../Images/menuImages/TenderGuide.png';
import ToolImg from '../Images/menuImages/ToolImg.png';
import batchEditIcon from '../Images/menuImages/batchEditIcon.png';
import menuForPromotionParams from '../Images/menuImages/menuForPromotionParams.png';
import menuForPromotionUpload from '../Images/menuImages/menuForPromotionUpload.png';
import saleCountry from '../Images/menuImages/saleCountry.png';
import picOverlay from '../Images/menuImages/picOverlay.png';
import thirdPart from '../Images/menuImages/thirdPart.png';
import CustomizedProductMaintenance from '../Images/menuImages/CustomizedProductMaintenance.png';
import ServiceNewsIcon from '../Images/menuImages/ServiceNewsIcon.png';
import handover from '../Images/menuImages/handover.png';
import Notice from '../Images/menuImages/notice.png';
import supportProduct from '../Images/menuImages/supportProduct.png';
import helpIcon from '../Images/menuImages/helpIcon.png';
import exchanged from '../Images/menuImages/exchanged.png';
import SogouExplorer from '../Images/others/SogouExplorer.png';
import chrome from '../Images/others/chrome.png';
import msedge from '../Images/others/msedge.png';
import styles from './index.less';
const getAppFromUrl = (url: string) => {
const res = url.split('/');
if (res && res.length > 2) {
return `/${res[2]}`;
}
return '/';
};
const getIcon = (iconString: string) => {
switch (iconString) {
case 'SpecEdit':
return <img src={SpecEdit} alt="" />;
case 'TemplateManage':
return <img src={TemplateManage} alt="" />;
case 'ProductParamConfig':
case 'ParamsConfig':
case 'OperatorParamConfig':
case 'SupportParamConfig':
case 'FeedbackParamsConfig':
case 'SystemFileParamConfig':
case 'TenderDataConfig':
return <img src={ProductParamConfig} alt="" />;
case 'TenderGuide':
case 'TenderGuideCheck':
return <img src={TenderGuide} alt="" />;
case 'ProductColorPage':
case 'ProductColorPageInspect':
return <img src={ProductColorPage} alt="" />;
case 'ProductMetaData':
case 'MarketMetaData':
case 'MarketMetaDataCheck':
return <img src={ProductMetaData} alt="" />;
case 'ProductShelfCategory':
return <img src={ProductShelfCategory} alt="" />;
case 'SpecCheck':
return <img src={SpecCheck} alt="" />;
case 'ProductFileUpload':
case 'ProductFileCheck':
case 'TechnicalFileUpload':
case 'TechnicalFileCheck':
case 'BidDataManage':
case 'TrainDataUpload':
case 'SystemFile':
case 'SystemFileCheck':
case 'TenderDataUpload':
case 'TenderDataCheck':
case 'PublicBiddingKnowledge':
case 'SecretBiddingKnowledge':
case 'PersonCertificateManage':
case 'CompanyCertificationManage':
case 'HonorMaterialManage':
case 'KnowledgePropertyManage':
case 'BusinessContractManage':
case 'BiddingMaterialReview':
return <img src={ProductFileUpload} alt="" />;
case 'ProductLaunch':
return <img src={ProductLaunch} alt="" />;
case 'Business':
return <img src={Business} alt="" />;
case 'ShutdownSwitch':
return <img src={ShutdownSwitch} alt="" />;
case 'PartsBatchMaintain':
return <img src={PartsBatchMaintain} alt="" />;
case 'ProductCatalog':
return <img src={ProductCatalog} alt="" />;
case 'AreaManagement':
case 'CombinationManage':
return <img src={ProductShelves} alt="" />;
case 'ProjectPublishManagement':
case 'ProjectCheck':
return <img src={ProjectPublishManagement} alt="" />;
case 'ProjectFileUpload':
case 'ProjectFileCheck':
return <img src={ProjectFileUpload} alt="" />;
case 'ProjectReleaseManagement':
return <img src={ProductShelves} alt="" />;
case 'SolutionParamConfig':
return <img src={SolutionParamConfig} alt="" />;
case 'AccountManage':
case 'AccountExt':
return <img src={AccountManage} alt="" />;
case 'AuthManage':
return <img src={AuthManage} alt="" />;
case 'ErrorFeedBack':
return <img src={ErrorFeedback} alt="" />;
case 'EvaluatedMaintain':
return <img src={EvaluatedMaintain} alt="" />;
case 'OperationLog':
return <img src={OperationLog} alt="" />;
case 'PublishNotice':
return <img src={Notice} alt="" />;
case 'PublishNoticeAudit':
return <img src={Notice} alt="" />;
case 'OperatorFileUpload':
case 'OperatorFileCheck':
return <img src={OperatorDataUpload} alt="" />;
case 'BrandPromotionFileUpload':
return <img src={menuForPromotionUpload} alt="" />;
case 'BrandParamConfig':
return <img src={menuForPromotionParams} alt="" />;
case 'SubscriptManage':
return <img src={SubscriptManage} alt="" />;
case 'ToolMaintain':
case 'ToolSetting':
case 'ToolCheck':
return <img src={ToolImg} alt="" />;
case 'GenealogyManage':
case 'MetaDocumentUpload':
case 'MetaFileCheck':
return <img src={GeneIcon} alt="" />;
case 'CounterpartProduct':
case 'CounterpartProductEn':
return <img src={CounterpartProduct} alt="" />;
case 'KnowledgeBase':
return <img src={KnowledgeBase} alt="" />;
case 'BatchEditSpec':
return <img src={batchEditIcon} alt="" />;
case 'CustomizedProductMaintenance':
return <img src={CustomizedProductMaintenance} />;
case 'ThirdPartDocking':
return <img src={thirdPart} />;
case 'PointExchangeRecord ':
return <img src={exchanged} alt="" />;
case 'ImageOverlay':
return <img src={picOverlay} alt="pic" />;
case 'QuotationAndProduct':
return <img src={quot} alt="" />;
case 'ProductModuleCheck ':
return <img src={SpecCheck} alt="pic" />;
case 'ProductSelection':
return <img src={TemplateManage} alt="pic" />;
case 'BehaviorAnalysis':
return <img src={BehaviorAnalysis} alt="pic" />;
case 'WorkHandover':
case 'WorkReception':
return <img src={handover} alt="pic" />;
case 'SupportProduct':
return <img src={supportProduct} alt="pic" />;
case 'BrandDataUpload':
return <img src={menuForPromotionUpload} alt="pic" />;
case 'BrandDataManage':
return <img src={menuForPromotionParams} alt="pic" />;
case 'OnlineHelp':
return <img src={helpIcon} alt="pic" />;
case 'ServiceNews':
case 'ServiceNewsCheck':
return <img src={ServiceNewsIcon} alt="pic" />;
case 'SaleCountry':
return <img src={saleCountry} alt="pic" />;
default:
return <></>;
}
};
const customEmpty = () => (
<div className={styles.layout_customEmpty_wrapper}>
<img src={empty} />
<span>{intl.formatMessage({ id: 'No data' })}</span>
</div>
);
interface MenuType {
path?: string;
icon?: React.ReactElement;
name?: string;
id?: number;
parentId?: number;
routes?: MenuType[];
}
const Layouts = (props: any) => {
const { children } = props;
// 控制左侧栏菜单展开/收起
const [collapsed, setCollapsed] = useState(false);
// 获取到当前的菜单列表
const [menuList] = useMenus();
// 当前选中的一级菜单
const [currentFirstMenu, setCurrentFirstMenu] = useState<any>(0);
// 当前格式化后的菜单列表
const [menus, setMenus] = useState<MenuType[]>([]);
// 当前平铺的菜单
const [allMenus, setAllMenus] = useState<MenuType[]>([]);
// 工作台logo
const [workLogo, setWorkLogo] = useState<string>('');
// 浏览器不兼容提示
const [browserWarningType, setBrowserWarningType] = useState<number>(0);
useEffect(() => {
const ua = navigator.userAgent;
// 当前浏览器是否为大于79版本的Chrome内核
if (ua.indexOf('Chrome') === -1) {
setBrowserWarningType(1);
} else if (!(Number(ua.match(/Chrome\/(\d+)/)?.[1]) >= 79)) {
setBrowserWarningType(2);
}
}, []);
// 全局注入国际化
window.intl = useIntl();
// 全局注入多选规格枚举值分隔符
window.intl.separator = BUILD_ENV !== 'zh-CN' ? '|' : '|';
// const [version, setVersion] = useState('');
const [showRefreshMessage, setShowRefreshMessage] = useState(false);
useEffect(() => {
checkVersion();
const intervalId = setInterval(checkVersion, 1800000); // 每30分钟检查一次版本
return () => clearInterval(intervalId); // 清除定时器
}, []);
async function checkVersion() {
// 发送请求检查应用程序版本
const response = await axios.get('/bench/version.json'); // 比较当前版本和最新版本是否一致
if (localStorage.version === undefined) {
localStorage.setItem('version', response.data.version);
} else {
if (String(localStorage.version) !== String(response.data.version)) {
// setVersion(response.data.version);
setShowRefreshMessage(true);
}
}
}
/**
* @method 刷新页面以加载最新版本
* @param
*/
const _handleRefresh = () => {
localStorage.removeItem('version');
window.location.reload();
};
/**
* @method 跳过更新
*/
const _noRefresh = () => {
localStorage.removeItem('version');
setShowRefreshMessage(false);
};
// 标准化数据和存储所有的数据
useEffect(() => {
if (Array.isArray(menuList) && menuList.length > 0) {
const routes: MenuType[] = [];
const allData: MenuType[] = [];
const format = (data: any, result: MenuType[]) => {
data.forEach((item: any) => {
const newItem: MenuType = {
name: item.name,
id: item.id,
parentId: item.parentId
};
allData.push({
...item,
name: item.name,
id: item.id,
parentId: item.parentId
});
if (item.icon) {
newItem.icon = getIcon(item.icon);
}
if (item.path) {
newItem.path = item.path;
}
if (Array.isArray(item.children) && item.children.length > 0) {
newItem.routes = [];
format(item.children, newItem.routes);
}
result.push(newItem);
});
return result;
};
format(
menuList.filter((item: any) => item.type !== '6'),
routes
);
let newRoutes: Array<any> = [];
let newData: Array<any> = [];
if (BUILD_ENV === 'zh-CN') {
newData = allData.filter(
(item: any) => item.path !== '/CounterpartProductEn'
);
newRoutes = routes.map((item: any) => {
const { path, routes } = item;
let tempRoutes: Array<any> = [];
if (path === '/ProductLaunch') {
tempRoutes = routes.filter(
(item: any) => item.path !== '/CounterpartProductEn'
);
return {
...item,
routes: tempRoutes
};
} else {
return item;
}
});
} else {
newData = allData.filter(
(item: any) => item.path !== '/CounterpartProduct'
);
newRoutes = routes.map((item: any) => {
const { path, routes } = item;
let tempRoutes: Array<any> = [];
if (path === '/ProductLaunch') {
tempRoutes = routes.filter(
(item: any) => item.path !== '/CounterpartProduct'
);
return {
...item,
routes: tempRoutes
};
} else {
return item;
}
});
}
setMenus(newRoutes);
setAllMenus(newData);
}
}, [menuList]);
// 当菜单发生改变,设置默认选中一级菜单
// useEffect(() => {
// if (Array.isArray(menus) && menus.length > 0 && currentFirstMenu) {
// setCurrentFirstMenu(menus[0] ? menus[0].id : 0);
// }
// }, [menus]);
// 获取logo信息
const getLogoImg = async () => {
const result = await getBusinessInfo({});
if (result && result.code === 0) {
const { data = {}} = result;
setWorkLogo(data.workLogoUrl);
}
};
useEffect(() => {
getLogoImg();
}, []);
// 选中一级菜单后,设置左侧栏的子菜单
const menuFormat = useMemo(() => {
if (menus && menus.length > 0) {
const menu: MenuType | undefined = menus.find(
(item: MenuType) => item.id === currentFirstMenu
);
return { routes: menu ? menu.routes : [] };
}
return { routes: [] };
}, [currentFirstMenu, menus]);
// 刷新路由时,设置选中的一级、子菜单
useEffect(() => {
if (Array.isArray(menus) && menus.length > 0 && window.location.pathname) {
const res = getAppFromUrl(window.location.pathname);
if (res) {
let currentItem: MenuType = {};
const getId = (list: MenuType[]) => {
for (let i = 0; i < list.length; i++) {
const item: MenuType = list[i];
if (item.path === res) {
currentItem = item;
break;
} else if (Array.isArray(item.routes) && item.routes.length > 0) {
getId(item.routes);
}
}
};
getId(menus);
if (currentItem && currentItem.id && currentItem.parentId) {
let firstMenu = 0;
const findFirstMenu = (cItem: MenuType) => {
const parentItem = allMenus.find(
(item: MenuType) => item.id === cItem?.parentId
);
if (!parentItem) {
firstMenu = cItem.id as number;
} else {
findFirstMenu(parentItem);
}
};
findFirstMenu(currentItem);
setCurrentFirstMenu(firstMenu);
// console.log('数据权限又足了吗', currentItem, menus, firstMenu);
}
// } else {
// console.log('数据权限不足吗');
// console.log('currentItemcurrentItem', currentItem, menus);
// UNVMessageBox.warn(
// intl.formatMessage({
// id: 'No product data permission. Please contact admin'
// })
// );
// history.push('/Home');
// }
}
}
}, [window.location.pathname, menus]);
// 设置当前的选中路由
const getLocation = useMemo(() => {
if (window.location.pathname) {
if (currentFirstMenu) {
const res = getAppFromUrl(window.location.pathname);
return res || '';
}
return '';
}
return '';
}, [window.location.pathname, currentFirstMenu]);
const menuClick = (e: { [key: string]: any }) => {
if (e.path) {
history.push(e.path);
} else {
console.error('路由错误');
}
};
const titleTimer = setTimeout(() => {
document.title = intl.formatMessage({ id: 'My Workspace' });
clearTimeout(titleTimer);
});
const menuItemOnClick = (item: any) => {
history.push(item.path);
};
return (
<ConfigProvider autoInsertSpaceInButton={false} renderEmpty={customEmpty}>
{!!browserWarningType && (
<Alert
message={
<div>
{browserWarningType === 1 ?
intl.formatMessage({
id: 'The current browser is not supported. Please use the recommended browser.'
}) :
intl.formatMessage({
id: 'The current browser version is too low. Please upgrade.'
})}
:
<img src={chrome} />
<a href="https://www.google.cn/chrome/index.html" target="_blank">
Chrome
</a>
<img src={msedge} />
<a
href="https://www.microsoft.com/zh-cn/edge/download"
target="_blank"
>
Edge
</a>
<img src={SogouExplorer} />
<a href="https://ie.sogou.com/" target="_blank">
搜狗浏览器
</a>
</div>
}
className={styles.banner}
banner
closable
onClose={() => setBrowserWarningType(0)}
/>
)}
{getAppFromUrl(window.location.pathname).toUpperCase() === '/LOGIN' ||
getAppFromUrl(window.location.pathname).toUpperCase() === '/' ? (
<div
className={
browserWarningType ?
`${styles.baseLayouts} ${styles.haveBanner}` :
styles.baseLayouts
}
>
{children}
</div>
) : (
<ProLayout
className={`
${browserWarningType ? styles.haveBanner : ''}
${
getAppFromUrl(window.location.pathname).toUpperCase() ===
'/HOME' ||
getAppFromUrl(window.location.pathname).toUpperCase() ===
'/HELPCENTER' ||
getAppFromUrl(window.location.pathname).toUpperCase() ===
'/DATAACCOUNT' ||
getAppFromUrl(window.location.pathname).toUpperCase() ===
'/TAKEDOWNNOTICE' ?
`${styles.proContainerNoLeft}` :
''
}
${styles.proContainer}
`}
logo={
<div
className={styles.layouts_index_imgDiv}
title={intl.formatMessage({ id: 'Go to UNV DIMS' })}
onClick={() => {
window.open(
`${window.location.protocol}//${window.location.hostname}`
);
}}
>
{workLogo ? (
<GetImg src={workLogo} alt="pic" />
) : (
<img src={uniview} alt="pic" />
)}
</div>
}
siderWidth={200}
title={intl.formatMessage({ id: 'My Workspace' })}
location={{ pathname: getLocation }}
route={menuFormat}
layout="mix" //上方导航栏固定
headerContentRender={() => {
return (
<Header
menuItemOnClick={menuItemOnClick}
menuList={menus}
activeMenuItem={currentFirstMenu}
setActiveMenuItem={setCurrentFirstMenu}
/>
);
}}
collapsedButtonRender={() => {
return (
<div className={styles.collapsed}>
<span
onClick={() => {
setCollapsed(!collapsed);
}}
>
{collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
</span>
</div>
);
}}
menuItemRender={(_, dom) => {
return (
<div
onClick={() => {
menuClick(_);
}}
>
{dom}
</div>
);
}}
collapsed={collapsed}
>
{/* 将设置选中一级目录的方法,传递到子组件中,主要是home中需要使用 */}
<QiankunMainProvider
value={{ setActiveMenuItem: setCurrentFirstMenu }}
>
<div className={styles.baseLayouts}>{children}</div>
</QiankunMainProvider>
</ProLayout>
)}
{showRefreshMessage && (
<UNVModal
title={intl.formatMessage({ id: 'Version update' })}
onCancel={() => setShowRefreshMessage(false)}
visible={showRefreshMessage}
canDragm
className={styles.addMark}
footer={
<Space>
<Button type="primary" onClick={_handleRefresh}>
{intl.formatMessage({ id: 'Refresh Now' })}
</Button>
<Button onClick={_noRefresh}>
{' '}
{intl.formatMessage({ id: 'Skip updates' })}
</Button>
</Space>
}
>
<p>
{intl.formatMessage({
id: 'Detected that the system version has been updated. Please refresh before using it'
})}
</p>
</UNVModal>
)}
</ConfigProvider>
);
};
export default connectQiankun(Layouts);
@import '../global.less';
.baseLayouts { width: 100%; height: 100%; }
.headerTitle { color: white; width: 100%; text-align: center; font-size: 18px; font-weight: bold;
h1 { font-size: 14px; font-weight: 400; margin: 0 0 0 8px; } }
.proContainer { overflow: hidden; height: 100%; width: 100%;
&.proContainerNoLeft { :global { .ant-layout-sider { display: none; } } }
:global {
.ant-layout-content {
background-color: #f5f5f5;
}
.ant-pro-global-header-logo a img {
height: unset;
}
.ant-pro-sider-link-menu {
background-color: #333333;
}
.ant-menu-item {
height: 48px;
padding-left: 8px !important;
&:hover {
background-color: #31414a;
}
}
.ant-menu-submenu-title {
padding-left: 8px !important;
}
.anticon-menu-unfold {
padding-left: 8px !important;
}
.anticon-menu-fold {
padding-left: 8px
}
.ant-menu-sub {
.ant-menu-title-content {
margin-left: 20px;
}
}
.ant-pro-sider-menu {
background-color: #333333;
}
.ant-menu-sub {
background-color: #333333 !important;
}
.ant-menu-item-selected {
background-color: #2e6381 !important;
}
.ant-pro-menu-item-title {
color: #fff;
margin-left: 10px;
}
.ant-layout-sider-children {
background-color: #333333;
}
.ant-pro-basicLayout-content {
margin: 10px;
}
.ant-pro-sider-logo {
height: 50px;
background-color: #287bab;
}
.ant-pro-global-header-layout-side {
padding: 0;
box-shadow: none;
line-height: 50px;
}
.ant-pro-global-header-logo {
background-color: #287bab;
height: 51px;
padding-left: 15px;
>a>h1 {
margin-left: 5px;
height: 30px;
font-size: 14px;
font-weight: 400;
}
}
.ant-pro-global-header {
padding: 0;
>div:first-child {
width: 220px;
}
>div:last-child {
width: calc(100% - 220px);
}
}
.ant-menu-item-only-child {
margin: 0 !important;
height: 48px !important;
}
.ant-menu-submenu-inline {
.ant-menu-submenu-title {
margin: 0;
}
}
} }
.layouts_index_imgDiv { height: 50px !important; max-width: 110px; }
.layouts_index_imgDiv+h1 { cursor: text; }
.layout_customEmpty_wrapper { margin: 0 auto; padding: 10px 0; color: rgba(0, 0, 0, 0.7); text-align: center;
span { display: block; margin-top: 6px; }
img { max-width: 160px; min-width: 60px; width: 100%; } }
:global { .ant-menu-item-selected { background-color: #2e6381 !important; } }
.haveBanner { height: calc(100% - 38px); min-height: calc(100% - 38px);
:global { .ant-pro-fixed-header { top: 38px !important; } } }
.banner { text-align: center;
img { margin: 0 2px 3px 10px; width: 16px; height: 16px; }
a { text-decoration: underline; } }