Skip to content

Commit 2af2400

Browse files
committed
feat: sync update
1 parent 16a0bfd commit 2af2400

File tree

19 files changed

+262
-136
lines changed

19 files changed

+262
-136
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"cssnano",
66
"datetime",
77
"ianvs",
8+
"Sider",
89
"tailwindcss",
910
"unocss"
1011
]

src/components/FormFilter/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { FormInstance } from "antd";
22
import type { FormListProps } from "../FormList";
33
import { Button, Card } from "antd";
4-
54
import { memo, useRef } from "react";
65
import FormList from "../FormList";
76

@@ -12,10 +11,11 @@ export interface FormFilterProps extends Pick<FormListProps, "form" | "onOk" | "
1211
loading?: boolean;
1312
compact?: boolean;
1413
searchBtn?: boolean;
14+
onRefresh?: () => void;
1515
}
1616

1717
function FormFilter(props: FormFilterProps) {
18-
const { className, filterInfo, reset, loading, compact = false, searchBtn = true, onForm, ...resetProps } = props;
18+
const { className, filterInfo, reset, loading, compact = false, searchBtn = true, onForm, onRefresh, ...resetProps } = props;
1919

2020
const formInstance = useRef<FormInstance<any> | null>(null);
2121

@@ -28,6 +28,12 @@ function FormFilter(props: FormFilterProps) {
2828
<div className={compact ? "ml-10" : "absolute bottom-0 right-0"}>
2929
{reset ? <Button htmlType="reset">重置</Button> : null}
3030

31+
{onRefresh && (
32+
<Button className="ml-6" loading={loading} onClick={onRefresh}>
33+
刷新
34+
</Button>
35+
)}
36+
3137
<Button className="ml-6" htmlType="submit" type="primary" loading={loading}>
3238
查询
3339
</Button>

src/components/LazyLoadSelect.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
import type { ResponseList } from "&src/types/api";
2-
import type { AnyObject, PagingSwrProps } from "@wanp/use-swr-data";
2+
import type { PagingSwrProps } from "@wanp/use-swr-data";
33
import type { SelectProps } from "antd";
4-
54
import useSwrData from "@wanp/use-swr-data";
65
import { Select, Spin } from "antd";
76
import debounce from "lodash/debounce";
87
import { useEffect, useMemo, useState } from "react";
98

10-
interface LazyLoadSelectProps<P extends AnyObject, R extends ResponseList<any>> {
11-
value?: SelectProps["value"];
12-
searchKey: string;
9+
interface LazyLoadSelectProps<P extends AnyObject, R extends ResponseList<any>> extends Pick<SelectProps, "fieldNames" | "onChange" | "value" | "disabled"> {
10+
reqKey: string;
1311
reqFunc: PagingSwrProps<R, P>["req"];
14-
fieldNames?: SelectProps["fieldNames"];
1512
reqParams?: PagingSwrProps<R, P>["params"];
16-
onChange?: SelectProps["onChange"];
13+
searchKey?: string;
1714
}
1815

1916
export default function LazyLoadSelect<P extends AnyObject, R extends ResponseList<any>>(props: LazyLoadSelectProps<P, R>) {
20-
const { value, fieldNames, searchKey = "name", reqParams, reqFunc, onChange } = props;
21-
17+
const { reqKey, reqFunc, reqParams, searchKey, onChange, ...reset } = props;
2218
const [list, setList] = useState<any[]>([]);
2319

2420
const { data, pageInfo, onSearch, setPage } = useSwrData({
25-
reqKey: reqFunc.name,
21+
reqKey,
2622
req: reqFunc,
2723
params: reqParams,
2824
paging: true,
@@ -66,6 +62,9 @@ export default function LazyLoadSelect<P extends AnyObject, R extends ResponseLi
6662
}, [list, data, pageInfo]);
6763

6864
const onSearchData = debounce((value) => {
65+
if (!searchKey)
66+
return;
67+
6968
onSearch({ [searchKey]: value } as PagingSwrProps["defaultSearch"]);
7069
setList([]);
7170
}, 500);
@@ -75,13 +74,11 @@ export default function LazyLoadSelect<P extends AnyObject, R extends ResponseLi
7574

7675
return (
7776
<Select
78-
showSearch
7977
allowClear
80-
value={value}
8178
filterOption={false}
8279
options={displayList}
83-
fieldNames={fieldNames}
84-
onSearch={onSearchData}
80+
showSearch={!!searchKey}
81+
onSearch={searchKey ? onSearchData : undefined}
8582
onPopupScroll={(e) => {
8683
const container = e.target as HTMLDivElement;
8784
const scrollTop = container?.scrollTop;
@@ -91,9 +88,10 @@ export default function LazyLoadSelect<P extends AnyObject, R extends ResponseLi
9188
onloadData();
9289
}}
9390
onChange={(value) => {
94-
onSearch({ [searchKey]: "" } as PagingSwrProps["defaultSearch"]);
91+
onSearch({});
9592
onChange?.(value);
9693
}}
94+
{...reset}
9795
/>
9896
);
9997
}

src/components/Loading/index.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Layout, Spin } from "antd";
1+
import { Spin } from "antd";
22
import classnames from "classnames";
33
import { memo } from "react";
44

@@ -11,15 +11,10 @@ interface LoadingProps {
1111

1212
function Loading({ full, text, size, className }: LoadingProps) {
1313
return (
14-
<Layout
15-
className={classnames(className, "flex items-center justify-center", {
16-
"h-screen": full,
17-
"bg-transparent": !full,
18-
})}
19-
>
14+
<div className={classnames({ "size-full": full }, "flex items-center justify-center", className)}>
2015
<Spin size={size} />
2116
<div className="mt-3 text-primary">{text}</div>
22-
</Layout>
17+
</div>
2318
);
2419
}
2520

src/components/tools.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import type { ReactNode } from "react";
12
import { Checkbox, DatePicker, Input, InputNumber, Radio, Select, Switch, TreeSelect } from "antd";
23

34
const { RangePicker } = DatePicker;
45

5-
export function getFormElement(type: FormItem["type"], info: FormItem) {
6+
export function getFormElement(type: FormItem["type"], info: FormItem): ReactNode {
67
switch (type) {
78
case "radio":
89
return (
@@ -35,11 +36,11 @@ export function getFormElement(type: FormItem["type"], info: FormItem) {
3536
<Select
3637
showSearch
3738
allowClear
39+
className="min-w-36"
3840
mode={info.otherOptions?.mode}
3941
placeholder={info.placeholder}
4042
disabled={info.disable}
4143
options={info.options as { value: string }[]}
42-
className="min-w-[150px]"
4344
filterOption={(input, option: any) => {
4445
if (typeof option.label === "string") {
4546
return option.label.includes(input);
@@ -82,5 +83,8 @@ export function getFormElement(type: FormItem["type"], info: FormItem) {
8283
{...info.otherOptions}
8384
/>
8485
);
86+
87+
default:
88+
return null;
8589
}
8690
}

src/layout/header.tsx

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ import dark_img from "&src/assets/images/dark.svg";
33
import light_img from "&src/assets/images/light.svg";
44
import useRootStore from "&src/store";
55
import { UserOutlined } from "@ant-design/icons";
6-
import { Avatar, Dropdown, Layout } from "antd";
6+
import { Avatar, Dropdown } from "antd";
77

88
import classnames from "classnames";
99
import { useNavigate } from "react-router-dom";
1010
import { useShallow } from "zustand/react/shallow";
1111
import lessStyle from "./index.module.less";
1212

13-
const { Header } = Layout;
14-
1513
interface MenuHeaderProps {
1614
tabId: string;
1715
tabList: MenuItem[];
1816
}
1917

18+
const headClass = "z-[999] box-border flex h-14 items-center justify-between p-7 py-3 shadow-ch";
19+
const tabItemClass = "relative mx-4 h-14 cursor-pointer select-none px-3 text-base leading-[3.5rem]";
20+
2021
function MenuHeader({ tabId, tabList }: MenuHeaderProps) {
2122
const navigate = useNavigate();
2223
const { userInfo, darkMode, setLogin, setDarkMode } = useRootStore(
@@ -52,66 +53,66 @@ function MenuHeader({ tabId, tabList }: MenuHeaderProps) {
5253
};
5354

5455
return (
55-
<Header className={`relative z-[999] box-border flex h-14 items-center justify-between p-7 py-3 shadow-ch ${darkMode ? "bg-slate-900" : "bg-white"} `}>
56+
<div className={classnames(headClass, darkMode ? "bg-slate-900 text-white" : "bg-white")}>
5657
<div className="flex items-center">
5758
<h1 className="mr-28 flex items-center text-lg">
5859
<img alt="logo" className="mr-2 w-8" src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />
59-
管理系统
60+
<span>管理系统</span>
6061
</h1>
6162

6263
{tabList.map((e) => {
6364
return (
64-
<div
65+
<ul
6566
key={e.key}
6667
onClick={() => {
6768
itemClick(e.path);
6869
}}
69-
className={classnames("relative mx-4 h-14 cursor-pointer select-none px-3 text-base leading-[56px]", {
70+
className={classnames(tabItemClass, {
7071
[`${lessStyle.tabItem_active} text-primary`]: e.key === tabId,
7172
})}
7273
>
73-
{e.label}
74+
<li>{e.label}</li>
7475

7576
<div className={lessStyle.line}></div>
76-
</div>
77+
</ul>
7778
);
7879
})}
7980
</div>
8081

81-
<div className="flex items-center">
82-
<div className="mr-10 flex w-5 cursor-pointer items-center">
82+
<div className="flex items-center gap-10">
83+
<div className="flex w-5 cursor-pointer items-center">
8384
{darkMode
8485
? (
8586
<img
87+
alt="暗黑模式"
8688
src={dark_img}
8789
className="w-full"
88-
alt="暗黑模式"
8990
onClick={() => {
9091
setDarkMode(false);
9192
}}
9293
/>
9394
)
9495
: (
9596
<img
97+
alt="明亮模式"
9698
src={light_img}
9799
className="w-full"
98-
alt="明亮模式"
99100
onClick={() => {
100101
setDarkMode(true);
101102
}}
102103
/>
103104
)}
104105
</div>
105106

106-
<Dropdown menu={{ items }} placement="bottomRight" className="cursor-pointer" arrow={{ pointAtCenter: false }}>
107-
<div className="flex items-center leading-[32px]">
108-
<div className="mr-3">{userInfo?.account}</div>
107+
<Dropdown menu={{ items }} placement="bottomRight" arrow={{ pointAtCenter: false }}>
108+
<div className="flex h-8 cursor-pointer items-center gap-3">
109+
<div>{userInfo?.account}</div>
109110

110111
<Avatar icon={<UserOutlined />} />
111112
</div>
112113
</Dropdown>
113114
</div>
114-
</Header>
115+
</div>
115116
);
116117
}
117118

src/layout/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ function AppLayout({ children }: { children: React.ReactNode }) {
9999
{sideMenu.length ? <SiderCom selectKey={menuId} menu={sideMenu} /> : null}
100100

101101
<Layout>
102-
<Content className="m-3 my-0">
102+
<Content className="mx-3">
103103
<BreadCrumb routerPath={routerPathMapping} />
104104

105105
<div className="h-[calc(100%-4.5rem)] overflow-auto">{children}</div>
@@ -112,4 +112,8 @@ function AppLayout({ children }: { children: React.ReactNode }) {
112112
);
113113
}
114114

115+
if (process.env.PUBLIC_ENV === "development") {
116+
AppLayout.displayName = "AppLayout";
117+
}
118+
115119
export default AppLayout;

src/main.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ const root = createRoot(dom);
1212
root.render(
1313
<StrictMode>
1414
<AppRouter />
15-
</StrictMode>
15+
</StrictMode>,
1616
);

src/pages/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ function System({ children }: RoutePageProps) {
44
return <Layout>{children}</Layout>;
55
}
66

7+
if (process.env.PUBLIC_ENV === "development") {
8+
System.displayName = "System";
9+
}
10+
711
export default System;

src/pages/login/index.tsx

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,40 @@ import lessStyle from "./index.module.less";
1313

1414
function Login() {
1515
const navigate = useNavigate();
16-
const { setLogin, setDynamicRoutes } = useRootStore(useShallow(store => ({ setLogin: store.setLogin, setDynamicRoutes: store.setDynamicRoutes })));
17-
18-
const [loading, loadingHandle] = useState(false);
16+
const { setLogin, setDynamicRoutes } = useRootStore(
17+
useShallow(store => ({
18+
setLogin: store.setLogin,
19+
setDynamicRoutes: store.setDynamicRoutes,
20+
}))
21+
);
1922

23+
const [loading, setLoading] = useState(false);
2024
const onFinish = async (values: AccountApi.Login) => {
21-
loadingHandle(true);
22-
const res = await loginReq(values);
23-
localStorage.setItem(LOCAL_TOKEN, res.data.token);
24-
localStorage.setItem(LOCAL_USER_INFO, JSON.stringify(res.data.userInfo));
25-
localStorage.setItem(LOCAL_DYNAMIC_ROUTER, JSON.stringify(GLOBAL_ROUTERS.APP_PAGE));
25+
try {
26+
setLoading(true);
27+
const res = await loginReq(values);
28+
localStorage.setItem(LOCAL_TOKEN, res.data.token);
29+
localStorage.setItem(LOCAL_USER_INFO, JSON.stringify(res.data.userInfo));
30+
localStorage.setItem(LOCAL_DYNAMIC_ROUTER, JSON.stringify(GLOBAL_ROUTERS.APP_PAGE));
2631

27-
// 设置登录态 用户信息 动态路由配置
28-
setLogin({ login: true, userInfo: res.data.userInfo });
29-
setDynamicRoutes(GLOBAL_ROUTERS.APP_PAGE);
30-
loadingHandle(false);
31-
navigate("/");
32+
// 设置登录态 用户信息 动态路由配置
33+
setLogin({ login: true, userInfo: res.data.userInfo });
34+
setDynamicRoutes(GLOBAL_ROUTERS.APP_PAGE);
35+
setLoading(false);
36+
navigate("/");
37+
}
38+
catch {
39+
setLoading(false);
40+
}
3241
};
3342

43+
// 已登录则跳转到首页
3444
useEffect(() => {
3545
if (getLocalStorage(LOCAL_TOKEN)) {
3646
navigate("/");
3747
}
38-
}, [navigate]);
48+
// eslint-disable-next-line react-hooks/exhaustive-deps
49+
}, []);
3950

4051
return (
4152
<Layout className={lessStyle.content}>
@@ -44,7 +55,14 @@ function Login() {
4455

4556
<h1 className="mb-9 text-center text-2xl">欢迎登录</h1>
4657

47-
<Form name="basic" layout="vertical" onFinish={onFinish} requiredMark="optional" initialValues={{ account: "管理小明", password: "123" }} className="w-80">
58+
<Form
59+
name="basic"
60+
className="w-80"
61+
layout="vertical"
62+
onFinish={onFinish}
63+
requiredMark="optional"
64+
initialValues={{ account: "管理小明", password: "123" }}
65+
>
4866
<Form.Item label="账号" name="account" rules={[{ required: true, message: "请输入你的账号!" }]}>
4967
<Input className={lessStyle.login_input} placeholder="请输入你的账号" />
5068
</Form.Item>

0 commit comments

Comments
 (0)