Skip to content

Commit e3f0cd1

Browse files
authored
Merge branch 'release-admin' into rancong_branch
2 parents 32fbe60 + fb7a4b3 commit e3f0cd1

File tree

15 files changed

+708
-261
lines changed

15 files changed

+708
-261
lines changed

apps/admin/.env.development

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ VITE_PUBLIC_PATH: './'
44

55
VITE_PORT: 3100
66

7-
VITE_USE_MOCK: true
7+
VITE_USE_MOCK: true
8+
9+
VITE_APP_HOMEPAGE = '/home'

apps/admin/.env.production

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ VITE_APP_BASE_API:
22

33
VITE_PUBLIC_PATH: '/react-antd-admin-pnpm/'
44

5-
VITE_USE_MOCK: true
5+
VITE_USE_MOCK: true
6+
7+
VITE_APP_HOMEPAGE = '/home'

apps/admin/mock/_assets.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ const MANAGEMENT_PERMISSION = {
7171
children: [
7272
{
7373
id: '4359580910369984',
74-
parentId: '0249937641030250',
74+
parentId: '0901673425580518',
7575
label: '授权管理',
7676
name: 'Permission',
7777
type: PermissionType.MENU,
@@ -80,7 +80,7 @@ const MANAGEMENT_PERMISSION = {
8080
},
8181
{
8282
id: '1689241785490759',
83-
parentId: '0249937641030250',
83+
parentId: '0901673425580518',
8484
label: '角色管理',
8585
name: 'Role',
8686
type: PermissionType.MENU,
@@ -89,7 +89,7 @@ const MANAGEMENT_PERMISSION = {
8989
},
9090
{
9191
id: '0157880245365433',
92-
parentId: '0249937641030250',
92+
parentId: '0901673425580518',
9393
label: '用户管理',
9494
name: 'User',
9595
type: PermissionType.MENU,

apps/admin/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"lodash-es": "^4.17.21",
4545
"mockjs": "^1.1.0",
4646
"react": "^18.2.0",
47+
"react-beautiful-dnd": "^13.1.1",
4748
"react-countup": "^6.5.0",
4849
"react-cropper": "^2.3.3",
4950
"react-dom": "^18.2.0",
@@ -78,6 +79,7 @@
7879
"@types/lodash-es": "^4.17.11",
7980
"@types/node": "^20.9.2",
8081
"@types/react": "^18.2.37",
82+
"@types/react-beautiful-dnd": "^13.1.8",
8183
"@types/react-dom": "^18.2.15",
8284
"@types/sortablejs": "^1.15.5",
8385
"@types/video-react": "^0.15.4",

apps/admin/src/hooks/web/useKeepAlive.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,15 @@ export default function useKeepAlive() {
7777
/**
7878
* 检测是否已经存在,如果不存在就添加
7979
*/
80-
// useEffect(() => {
81-
// if (!currentRouteMeta) return;
82-
// const existed = tabs.find((item) => item.key === currentRouteMeta.key);
83-
// if (!existed) {
84-
// setTabs((prev) => [...prev, { ...currentRouteMeta, children: currentRouteMeta.outlet, timeStamp: getKey() }]);
85-
// }
86-
// setActiveTabRoutePath(currentRouteMeta.key);
87-
// }, [currentRouteMeta]);
80+
useEffect(() => {
81+
debugger;
82+
if (!currentRouteMeta) return;
83+
const existed = tabs.find((item) => item.key === currentRouteMeta.key);
84+
if (!existed) {
85+
setTabs((prev) => [...prev, { ...currentRouteMeta, children: currentRouteMeta.outlet, timeStamp: getKey() }]);
86+
}
87+
setActiveTabRoutePath(currentRouteMeta.key);
88+
}, [currentRouteMeta]);
8889
return {
8990
tabs,
9091
activeTabRoutePath,

apps/admin/src/layout/multi-tab/index.tsx

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { Dropdown, type MenuProps, Tabs, TabsProps } from 'antd';
1+
import { Dropdown, type MenuProps, Tabs, type TabsProps } from 'antd';
22
import { useCallback, useMemo, useRef, useState } from 'react';
3+
import { DragDropContext, Draggable, Droppable, type OnDragEndResponder } from 'react-beautiful-dnd';
34
import { useTranslation } from 'react-i18next';
45

56
import IconifyIcon from '@/components/iconify-icon';
67

78
import useKeepAlive, { type KeepAliveTab } from '@/hooks/web/useKeepAlive';
89

10+
import { useRouter } from '@/router/hooks';
11+
import { replaceDynamicParams } from '@/router/hooks/use-match-route-meta';
12+
13+
import useStyles from './style';
14+
915
import { MultiTabOperation, ThemeLayout } from '#/enum';
1016

1117
type Props = {
@@ -14,7 +20,10 @@ type Props = {
1420

1521
export default function MultiTabs({ offsetTop = true }: Props) {
1622
const { t } = useTranslation();
23+
const { push } = useRouter();
24+
const { styles } = useStyles();
1725
const tabContentRef = useRef(null);
26+
const scrollContainer = useRef<HTMLDivElement>(null);
1827
const [openDropdownTabKey, setopenDropdownTabKey] = useState('');
1928

2029
const [hoveringTabKey, setHoveringTabKey] = useState('');
@@ -160,6 +169,66 @@ export default function MultiTabs({ offsetTop = true }: Props) {
160169
),
161170
}));
162171
}, [tabs, renderTabLabel]);
172+
/**
173+
* 拖拽结束事件
174+
*/
175+
const onDragEnd: OnDragEndResponder = ({ destination, source }) => {
176+
// 拖拽到非法非 droppable区域
177+
if (!destination) {
178+
return;
179+
}
180+
// 原地放下
181+
if (destination.droppableId === source.droppableId && destination.index === source.index) {
182+
return;
183+
}
184+
185+
const newTabs = Array.from(tabs);
186+
const [movedTab] = newTabs.splice(source.index, 1);
187+
newTabs.splice(destination.index, 0, movedTab);
188+
setTabs(newTabs);
189+
};
190+
const handleTabClick = ({ key, params = {} }: KeepAliveTab) => {
191+
const tabKey = replaceDynamicParams(key, params);
192+
push(tabKey);
193+
};
194+
const renderTabBar: TabsProps['renderTabBar'] = () => {
195+
return (
196+
<div className={styles.tab_bar}>
197+
<DragDropContext onDragEnd={onDragEnd}>
198+
<Droppable droppableId='tabsDroppable' direction='horizontal'>
199+
{(provided) => (
200+
<div ref={provided.innerRef} {...provided.droppableProps} className='flex w-full'>
201+
<div ref={scrollContainer} className='hide-scrollbar flex w-full px-2'>
202+
{tabs.map((tab, index) => (
203+
<div
204+
id={`tab-${index}`}
205+
className='flex-shrink-0'
206+
key={tab.key}
207+
onClick={() => handleTabClick(tab)}
208+
>
209+
<Draggable key={tab.key} draggableId={tab.key} index={index}>
210+
{(provided) => (
211+
<div
212+
ref={provided.innerRef}
213+
{...provided.draggableProps}
214+
{...provided.dragHandleProps}
215+
className='w-auto'
216+
>
217+
{renderTabLabel(tab)}
218+
</div>
219+
)}
220+
</Draggable>
221+
</div>
222+
))}
223+
</div>
224+
{provided.placeholder}
225+
</div>
226+
)}
227+
</Droppable>
228+
</DragDropContext>
229+
</div>
230+
);
231+
};
163232

164233
return (
165234
<Tabs
@@ -168,7 +237,7 @@ export default function MultiTabs({ offsetTop = true }: Props) {
168237
tabBarGutter={4}
169238
activeKey={activeTabRoutePath}
170239
items={tabItems}
171-
renderTabBar={() => <></>}
240+
renderTabBar={renderTabBar}
172241
/>
173242
);
174243
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createStyles } from 'antd-style';
2+
3+
const useStyles = createStyles(({ token }) => ({
4+
tab_bar: {
5+
width: '100%',
6+
zIndex: '20',
7+
position: 'absolute',
8+
top: '64px',
9+
left: 0,
10+
height: '32px',
11+
backgroundColor: token.colorBgElevated,
12+
borderBottom: `1px solid ${token.colorBorder}`,
13+
transition: 'top 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
14+
},
15+
}));
16+
export default useStyles;

apps/admin/src/router/hooks/use-match-route-meta.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useEffect, useState } from 'react';
2-
import { useMatches, useOutlet } from 'react-router-dom';
2+
import { type Params, useMatches, useOutlet } from 'react-router-dom';
33

44
import { useFlattenedRoutes } from './use-flattened-routes';
55
import { useRouter } from './use-router';
@@ -15,7 +15,6 @@ export function useMatchRouteMeta() {
1515
const children = useOutlet();
1616
// 获取所有匹配到路由
1717
const matches = useMatches();
18-
debugger;
1918
// 获取拍平后到路由菜单
2019
const flattenedRoutes = useFlattenedRoutes();
2120
// const pathname = usePathname();
@@ -38,3 +37,27 @@ export function useMatchRouteMeta() {
3837
}, [matches]);
3938
return matchRouteMeta;
4039
}
40+
41+
/**
42+
* replace `user/:id` to `/user/1234512345`
43+
*/
44+
export const replaceDynamicParams = (menuKey: string, params: Params<string>) => {
45+
let replacedPathName = menuKey;
46+
47+
// 解析路由路径中的参数名称
48+
const paramNames = menuKey.match(/:\w+/g);
49+
50+
if (paramNames) {
51+
paramNames.forEach((paramName) => {
52+
// 去掉冒号,获取参数名称
53+
const paramKey = paramName.slice(1);
54+
// 检查params对象中是否有这个参数
55+
if (params[paramKey]) {
56+
// 使用params中的值替换路径中的参数
57+
replacedPathName = replacedPathName.replace(paramName, params[paramKey]!);
58+
}
59+
});
60+
}
61+
62+
return replacedPathName;
63+
};

apps/admin/src/router/hooks/use-permission-routes.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ function resolveComponent(path: string) {
2424
*/
2525
export function usePermissionRoutes() {
2626
const permissions = useUserPermissions();
27-
debugger;
2827
return useMemo(() => {
2928
const flattenedPermissions = flattenTree(permissions!);
3029
const permissionRoutes = transformPermissionToMenuRoutes(permissions || [], flattenedPermissions);

apps/admin/src/router/routes/compo.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ const CompoRoute: RouteObject = {
1919
orderNo: 6,
2020
},
2121
children: [
22+
{
23+
path: 'point-cloud',
24+
name: 'pointCloud',
25+
element: LazyLoad(lazy(() => import('@/views/compo/point-cloud'))),
26+
meta: {
27+
title: '10w点云',
28+
key: 'pointCloud',
29+
},
30+
},
2231
{
2332
path: 'image-upload',
2433
name: 'ImageUpload',

0 commit comments

Comments
 (0)