Skip to content

Commit

Permalink
新增了多页签,有bug后边再调整
Browse files Browse the repository at this point in the history
  • Loading branch information
a3318375 committed Apr 25, 2024
1 parent 6af47aa commit 4c2f910
Show file tree
Hide file tree
Showing 9 changed files with 1,288 additions and 250 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
},
"dependencies": {
"@ant-design/icons": "^5.3.1",
"@ant-design/pro-components": "^2.6.49",
"@ant-design/pro-components": "^2.7.1",
"@generouted/react-router": "^1.18.5",
"@types/node": "^20.11.25",
"antd": "^5.15.1",
"antd": "^5.16.4",
"antd-style": "^3.6.1",
"axios": "^1.6.7",
"md-editor-rt": "^4.13.3",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"react": "^18.2.0",
Expand Down
1,038 changes: 826 additions & 212 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

29 changes: 25 additions & 4 deletions src/hook/useMenuStore.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
import { create } from 'zustand'
import { create, StateCreator } from 'zustand'
import { MenuDataItem } from "@ant-design/pro-components";
import { createJSONStorage, persist } from "zustand/middleware";

interface BearState {
menu: MenuDataItem[]
setMenu: (menu: MenuDataItem[]) => void
}

const menuPersist = (initializer: StateCreator<BearState>) =>
persist(initializer, {
name: 'menu',
storage: createJSONStorage(() => sessionStorage),
})

const menuOnePersist = (initializer: StateCreator<BearState>) =>
persist(initializer, {
name: 'menu-one',
storage: createJSONStorage(() => sessionStorage),
})

export const useMenuStore = create<BearState>()(
(set) => ({
menuPersist((set) => ({
menu: [],
setMenu: (menu: MenuDataItem[]) => set({ menu: menu }),
})),
)

export const useMenuOneStore = create<BearState>()(
menuOnePersist((set) => ({
menu: [],
setMenu: (menu) => set({ menu: menu }),
}))
setMenu: (menu: MenuDataItem[]) => set({ menu: menu }),
})),
)
23 changes: 18 additions & 5 deletions src/pages/(auth)/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
WeiboOutlined,
} from '@ant-design/icons';
import {
LoginFormPage,
LoginFormPage, MenuDataItem,
ProFormCaptcha,
ProFormCheckbox,
ProFormText,
Expand All @@ -19,6 +19,7 @@ import { useState } from 'react';
import http from "@/services/axios.ts";
import { useNavigate } from "react-router-dom";
import { useTokenStore } from "@/hook/useTokenStore.tsx";
import {useMenuOneStore, useMenuStore} from "@/hook/useMenuStore.tsx";

type LoginType = 'phone' | 'account';

Expand All @@ -32,6 +33,8 @@ const iconStyles: CSSProperties = {
export default function Login() {
const naigate = useNavigate()
const tokenHook = useTokenStore()
const menuHook = useMenuStore()
const menuOneHook = useMenuOneStore()
const handleSubmit = async (values: API.LoginParams) => {
try {
// 登录
Expand All @@ -40,11 +43,15 @@ export default function Login() {
tokenHook.setToken(token)
message.success('登录成功!');
const paw = useTokenStore.getState().token
console.log(3333, paw)
console.log(111, paw)
const userInfo = await http.get('/api/getUserInfo');
if (userInfo) {
console.log(111, userInfo)
}
console.log(222, userInfo)
const menuList = await http.get<MenuDataItem[]>('/api/getMenuList')
console.log(333, userInfo)
const allChildren: MenuDataItem[] = getAllChildren(menuList);
menuHook.setMenu(menuList)
menuOneHook.setMenu(allChildren)

const urlParams = new URL(window.location.href).searchParams;
naigate(urlParams.get('redirect') || '/');
return;
Expand All @@ -54,6 +61,12 @@ export default function Login() {
message.error('登录失败,请重试!');
}
}
const getAllChildren: (items: MenuDataItem[]) => any[] = (items: MenuDataItem[]) => {
return items.flatMap(item => {
const { routes = [], ...rest } = item;
return [ rest, ...getAllChildren(routes) ];
});
}
const items = [
{ label: '账户密码登录', key: 'account', },
{ label: '手机号登录', key: 'phone', },
Expand Down
128 changes: 102 additions & 26 deletions src/pages/(base)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Suspense, useState } from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
import { Loading } from '@/pages/loading';
import { useMemo, useState } from 'react';
import { useLocation, useMatches, useNavigate, useOutlet } from 'react-router-dom';
import type { ProSettings } from '@ant-design/pro-components';
import {
PageContainer,
Expand All @@ -16,15 +15,103 @@ import {
} from '@ant-design/icons';
import { ConfigProvider, Dropdown } from "antd";
import SearchInput from '@/components/layout/SearchInput'
import http from "@/services/axios.ts";
import { useTokenStore } from "@/hook/useTokenStore";
import { isPublicPath } from "@/router/publicPath";
import { useMenuOneStore, useMenuStore } from "@/hook/useMenuStore.tsx";

export interface KeepAliveTab {
title: string;
routePath: string;
key: string;
pathname: string;
icon?: any;
children: any;
}

export default function BaseLayout() {
const [ tabs, setTabs ] = useState<KeepAliveTab[]>([]);
const [ activeKey, setActiveKey ] = useState('');
const [ routeList, setRouteList ] = useState<string[]>([]);
const navigate = useNavigate()
const onTabsChange = (newActiveKey: string) => {
setActiveKey(newActiveKey);
};
const menuStore = useMenuStore()
const menuOneStore = useMenuOneStore()

const matches = useMatches();
const children = useOutlet();
const { pathname } = useLocation();
if(activeKey === '') {
setActiveKey(pathname);
}
if(!routeList.includes(pathname)){
setRouteList([ ...routeList, pathname ]);

const lastRoute = matches.at(-1);
const lastRouteName = lastRoute?.pathname !== '/' && lastRoute?.pathname.endsWith("/") ? lastRoute.pathname.substring(0,lastRoute.pathname.length -1): lastRoute?.pathname
if(lastRouteName?.includes('/add')){
const existKeepAliveTab = tabs.find(o => o.routePath === pathname);
// 如果不存在则需要插入
if (!existKeepAliveTab) {
setTabs([ ...tabs, {
title: '新增',
key: new Date().getTime().toString(),
routePath: pathname,
pathname,
children,
} ]);
setActiveKey(pathname);
}
}else{
const menuObj = menuOneStore.menu.find(o => o.path === lastRouteName);
const existKeepAliveTab = tabs.find(o => o.routePath === menuObj?.path);
// 如果不存在则需要插入
if (!existKeepAliveTab && menuObj) {
setTabs([ ...tabs, {
title: menuObj.name || '',
key: new Date().getTime().toString(),
routePath: menuObj?.path || '/',
pathname,
children,
} ]);
setActiveKey(pathname);
}
}

const menuObj = menuOneStore.menu.find(o => o.path === lastRouteName);
const existKeepAliveTab = tabs.find(o => o.routePath === menuObj?.path);
// 如果不存在则需要插入
if (!existKeepAliveTab && menuObj) {
setTabs([ ...tabs, {
title: menuObj.name || '',
key: new Date().getTime().toString(),
routePath: menuObj?.path || '/',
pathname,
children,
} ]);
}
}

const tabItems = useMemo(() => {
return tabs.map(tab => ({
label: (
<>
{tab.title}
</>
),
key: tab.routePath,
children: (
<div className='px-[16px]'>
{tab.children}
</div>
),
closable: tabs.length > 1, // 剩最后一个就不能删除了
}))
}, [ tabs ]);

const token = useTokenStore.getState().token
console.log(2222, token, !isPublicPath())
if(!isPublicPath() && !token){
if (!isPublicPath() && !token) {
navigate('/login')
}

Expand All @@ -34,7 +121,7 @@ export default function BaseLayout() {
splitMenus: false,
});

const [ pathname, setPathname ] = useState('/list/sub-page/sub-sub-page1');
const [ layoutPathName, setLayoutPathName ] = useState('/list/sub-page/sub-sub-page1');
if (typeof document === 'undefined') {
return <div/>;
}
Expand Down Expand Up @@ -76,11 +163,11 @@ export default function BaseLayout() {
]}
menu={{
request: async () => {
return await http.get('/api/getMenuList')
return menuStore.menu;
},
}}
location={{
pathname,
pathname: layoutPathName,
}}
token={{
header: {
Expand Down Expand Up @@ -140,8 +227,8 @@ export default function BaseLayout() {
menuItemRender={(item, dom) => (
<div
onClick={() => {
console.log(333, item)
setPathname(item.path || '/welcome')
onTabsChange(item.path || '/welcome')
setLayoutPathName(item.path || '/welcome')
navigate(item.path || '/welcome')
}}
>
Expand All @@ -151,17 +238,7 @@ export default function BaseLayout() {
{...settings}
>
<PageContainer
tabList={[
{
tab: '基本信息',
key: 'base',
closable: false,
},
{
tab: '详细信息',
key: 'info',
},
]}
tabList={tabItems}
tabProps={{
type: 'editable-card',
hideAdd: true,
Expand All @@ -170,14 +247,13 @@ export default function BaseLayout() {
token={{
paddingBlockPageContainerContent: 0,
}}
onTabChange={onTabsChange}
tabActiveKey={activeKey}
>
<Suspense fallback={<Loading/>}>
<Outlet/>
</Suspense>
</PageContainer>

<SettingDrawer
pathname={pathname}
pathname={layoutPathName}
enableDarkTheme
getContainer={(e: any) => {
if (typeof window === 'undefined') return e;
Expand Down
89 changes: 89 additions & 0 deletions src/pages/(base)/article/blog/add.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useState } from "react";
import {
ProForm, ProFormSelect, ProFormSwitch,
ProFormText,
} from '@ant-design/pro-components';
import { Form, message } from 'antd';
import { MdEditor } from "md-editor-rt";
import 'md-editor-rt/lib/style.css';
import http from "@/services/axios.ts";

export default function BlogAdd() {
const [ text, setText ] = useState('');
return (
<ProForm
title="新建表单"
onFinish={async (values: any) => {
console.log(values);
message.success('提交成功');
return true;
}}
>
<ProFormText
width="md"
name="title"
label="标题"
tooltip="最长为 24 位"
placeholder="请输入名称"
/>

<ProFormText
width="md"
name="summary"
label="摘要"
placeholder="请输入名称"
/>
<ProForm.Group>
<ProFormSelect
options={[
{
value: 'chapter',
label: '盖章后生效',
},
]}
width="md"
name="typeList"
label='分类'
request={async () => {
const tags = await http.get('/api/type/list');
const tagResp = []
tags.forEach((tag) => {
const obj = {};
obj.label = tag.name;
obj.value = tag.id;
obj.obj = tag;
tagResp.push(obj);
})
return tagResp;
}}
/>
<ProFormSelect
width="md"
name="tagList"
label='标签'
mode='multiple'
request={async () => {
const tags = await http.get('/api/tag/list');
const tagResp = []
tags.forEach((tag) => {
const obj = {};
obj.label = tag.name;
obj.value = tag.id;
obj.obj = tag;
tagResp.push(obj);
})
return tagResp;
}}
/>
</ProForm.Group>
<ProForm.Group>
<ProFormSwitch name="status" label="是否发布"/>
<ProFormSwitch name="isHot" label="是否热门"/>
<ProFormSwitch name="isComment" label="是否开启评论"/>
</ProForm.Group>
<Form.Item name={[ "article", "context" ]} label="正文" valuePropName={text}>
<MdEditor modelValue={text} onChange={setText}/>
</Form.Item>
</ProForm>
);
}
Loading

0 comments on commit 4c2f910

Please sign in to comment.