264 lines
8.9 KiB
TypeScript
264 lines
8.9 KiB
TypeScript
|
|
import { CloseOutlined } from '@ant-design/icons';
|
||
|
|
import { Menu } from 'antd';
|
||
|
|
import type React from 'react';
|
||
|
|
import { useEffect, useRef, useState } from 'react';
|
||
|
|
import { Colors, DefaultERPName, headerHeight } from '@/configs/config';
|
||
|
|
import { getHash } from '@/router/routerUtils';
|
||
|
|
import { useCompanyStore } from '@/store/CompanyStore';
|
||
|
|
import { useRefreshStore } from '@/store/RefreshStore';
|
||
|
|
import { getDevice } from '@/utils/common';
|
||
|
|
import styles from './index.module.css';
|
||
|
|
|
||
|
|
interface IUrl {
|
||
|
|
url: string;
|
||
|
|
title: string;
|
||
|
|
search: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
const TabNavPlugin: React.FC = () => {
|
||
|
|
const [urlList, setUrlList] = useState<IUrl[]>([]);
|
||
|
|
const urlListRef = useRef<IUrl[]>([]);
|
||
|
|
const isPhone = getDevice() == 'phone';
|
||
|
|
const refreshStore = useRefreshStore();
|
||
|
|
const [pathname, setPathname] = useState('');
|
||
|
|
|
||
|
|
const boxScrollRef = useRef<any>(null);
|
||
|
|
// 删除模式 不进行滚动
|
||
|
|
const modeRef = useRef('');
|
||
|
|
const company = useCompanyStore().company;
|
||
|
|
|
||
|
|
const callback = () => {
|
||
|
|
const span = document.querySelector('.urlList-active');
|
||
|
|
if (urlListRef.current && span && modeRef.current != 'del') {
|
||
|
|
// urlListRef.current
|
||
|
|
const boxCenterWidth = boxScrollRef.current.parentNode.clientWidth / 2;
|
||
|
|
const scrollWidth = (span as HTMLElement).offsetLeft + span.clientWidth / 2;
|
||
|
|
let scrollLeft = 0;
|
||
|
|
if (scrollWidth >= boxCenterWidth) {
|
||
|
|
scrollLeft = scrollWidth - boxCenterWidth;
|
||
|
|
}
|
||
|
|
// console.log((span as HTMLElement).offsetLeft);
|
||
|
|
setTimeout(() => {
|
||
|
|
boxScrollRef.current?.scroll(scrollLeft, 0);
|
||
|
|
}, 17);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const observer = new MutationObserver(callback);
|
||
|
|
|
||
|
|
const [menuStyle, setMenuStyle] = useState({
|
||
|
|
left: 0,
|
||
|
|
top: 0,
|
||
|
|
display: 'none',
|
||
|
|
});
|
||
|
|
const menu = [
|
||
|
|
{ key: '1', label: '刷新页面' },
|
||
|
|
{ key: '2', label: '关闭当前' },
|
||
|
|
{ key: '3', label: '关闭其他' },
|
||
|
|
{ key: '4', label: '关闭所有' },
|
||
|
|
];
|
||
|
|
const menu2 = [
|
||
|
|
{ key: '1', label: '刷新页面' },
|
||
|
|
{ key: '3', label: '关闭其他' },
|
||
|
|
{ key: '4', label: '关闭所有' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const selectRecordRef = useRef<IUrl>({ url: '', title: '', search: '' });
|
||
|
|
const isActiveTag = useRef<boolean>(false);
|
||
|
|
|
||
|
|
function hideMenu() {
|
||
|
|
menuStyle.display = 'none';
|
||
|
|
setMenuStyle({ ...menuStyle });
|
||
|
|
}
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!isPhone) {
|
||
|
|
boxScrollRef.current.addEventListener(
|
||
|
|
'wheel',
|
||
|
|
(event: WheelEvent) => {
|
||
|
|
event.preventDefault();
|
||
|
|
event.stopPropagation();
|
||
|
|
boxScrollRef.current.scrollLeft += event.deltaY;
|
||
|
|
},
|
||
|
|
{ passive: false },
|
||
|
|
);
|
||
|
|
observer.observe(boxScrollRef.current, {
|
||
|
|
childList: true, // 观察目标子节点的变化,是否有添加或者删除
|
||
|
|
attributes: true, // 观察属性变动
|
||
|
|
subtree: true, // 观察后代节点,默认为 false
|
||
|
|
});
|
||
|
|
}
|
||
|
|
document.addEventListener('click', hideMenu);
|
||
|
|
window.addEventListener('scroll', hideMenu);
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
document.removeEventListener('click', hideMenu);
|
||
|
|
window.removeEventListener('scroll', hideMenu);
|
||
|
|
};
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
modeRef.current = '';
|
||
|
|
const handle = () => {
|
||
|
|
const pathname = getHash();
|
||
|
|
setPathname(pathname);
|
||
|
|
|
||
|
|
let flag = true;
|
||
|
|
if ((document.title == '404' || pathname == '/temp' || pathname == '/') && !isPhone) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (const el of urlListRef.current) {
|
||
|
|
if (el.url === pathname) {
|
||
|
|
flag = false;
|
||
|
|
// el.search = lo.search;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (flag) {
|
||
|
|
urlListRef.current.push({
|
||
|
|
url: pathname,
|
||
|
|
title: `${document.title}`.replace(` - ${DefaultERPName}`, ''),
|
||
|
|
search: '',
|
||
|
|
});
|
||
|
|
setUrlList([...urlListRef.current]);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
handle();
|
||
|
|
window.addEventListener('hashchange', handle);
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
window.removeEventListener('hashchange', handle);
|
||
|
|
};
|
||
|
|
}, []);
|
||
|
|
// if (!urlListRef.current.includes(lo.pathname)) {
|
||
|
|
// urlListRef.current.push(lo.pathname);
|
||
|
|
// setUrlList([...urlListRef.current]);
|
||
|
|
// }
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
{isPhone ? null : (
|
||
|
|
<>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
position: 'fixed',
|
||
|
|
zIndex: 101,
|
||
|
|
left: menuStyle.left,
|
||
|
|
top: menuStyle.top,
|
||
|
|
display: menuStyle.display,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<Menu
|
||
|
|
selectedKeys={[]}
|
||
|
|
items={selectRecordRef.current && selectRecordRef.current.url == '/' ? menu2 : menu}
|
||
|
|
onClick={(item) => {
|
||
|
|
if (item.key == '1') {
|
||
|
|
if (selectRecordRef.current) {
|
||
|
|
if (isActiveTag.current) {
|
||
|
|
refreshStore.updateRefresh(refreshStore.refresh + 1);
|
||
|
|
} else {
|
||
|
|
location.hash = selectRecordRef.current.url;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (item.key == '2') {
|
||
|
|
if (selectRecordRef.current) {
|
||
|
|
for (let index = 0; index < urlListRef.current.length; index++) {
|
||
|
|
if (urlListRef.current[index].url == selectRecordRef.current.url) {
|
||
|
|
urlListRef.current.splice(index, 1);
|
||
|
|
if (selectRecordRef.current.url == pathname) {
|
||
|
|
if (urlListRef.current.length) {
|
||
|
|
location.hash = urlListRef.current[urlListRef.current.length - 1].url;
|
||
|
|
} else {
|
||
|
|
location.hash = '/';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
setUrlList([...urlListRef.current]);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (item.key == '3') {
|
||
|
|
if (selectRecordRef.current) {
|
||
|
|
urlListRef.current = [{ ...selectRecordRef.current }];
|
||
|
|
location.hash = selectRecordRef.current.url;
|
||
|
|
|
||
|
|
setUrlList([...urlListRef.current]);
|
||
|
|
}
|
||
|
|
} else if (item.key == '4') {
|
||
|
|
urlListRef.current = [];
|
||
|
|
location.hash = '/';
|
||
|
|
setUrlList([...urlListRef.current]);
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className={styles.box} style={{ top: headerHeight }}>
|
||
|
|
<div className={styles.boxScroll} ref={boxScrollRef}>
|
||
|
|
{urlList.map((el) => (
|
||
|
|
<span
|
||
|
|
title={el.title}
|
||
|
|
onContextMenu={(event) => {
|
||
|
|
event.preventDefault();
|
||
|
|
return false;
|
||
|
|
}}
|
||
|
|
key={el.url}
|
||
|
|
onClick={() => {
|
||
|
|
location.hash = el.url;
|
||
|
|
}}
|
||
|
|
onMouseDown={(event: any) => {
|
||
|
|
if (event.button == 2) {
|
||
|
|
menuStyle.top = event.pageY - document.documentElement.scrollTop + 2;
|
||
|
|
menuStyle.left = event.pageX + 2;
|
||
|
|
menuStyle.display = 'block';
|
||
|
|
isActiveTag.current = pathname == el.url;
|
||
|
|
selectRecordRef.current = el;
|
||
|
|
setMenuStyle({ ...menuStyle });
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
className={`${styles.tag} ${pathname == el.url ? styles.tagActive : ''} urlList-${
|
||
|
|
pathname == el.url ? 'active' : ''
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
<span
|
||
|
|
className={styles.title}
|
||
|
|
style={{
|
||
|
|
color: pathname == el.url ? Colors.primary : '#000',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{el.title}
|
||
|
|
</span>
|
||
|
|
<CloseOutlined
|
||
|
|
style={{ fontSize: 12, height: 32 }}
|
||
|
|
onClick={(event) => {
|
||
|
|
event.stopPropagation();
|
||
|
|
modeRef.current = 'del';
|
||
|
|
for (let index = 0; index < urlListRef.current.length; index++) {
|
||
|
|
if (urlListRef.current[index].url == el.url) {
|
||
|
|
if (urlListRef.current.length == 1 && company.staff_type == 3) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
urlListRef.current.splice(index, 1);
|
||
|
|
if (el.url == pathname) {
|
||
|
|
if (urlListRef.current.length) {
|
||
|
|
location.hash = urlListRef.current[urlListRef.current.length - 1].url;
|
||
|
|
} else {
|
||
|
|
location.hash = '/';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
setUrlList([...urlListRef.current]);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</span>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default TabNavPlugin;
|