新项目, antd6, react19
This commit is contained in:
263
src/components/TabNavPlugin/index.tsx
Normal file
263
src/components/TabNavPlugin/index.tsx
Normal file
@@ -0,0 +1,263 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user