新项目, antd6, react19

This commit is contained in:
zhengw
2026-01-05 17:06:16 +08:00
commit fcb43c0cbd
84 changed files with 6939 additions and 0 deletions

View 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;