diff --git a/package.json b/package.json
index d1a438c..927de28 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,9 @@
"next-themes": "^0.4.6",
"react": "^19.2.4",
"react-dom": "^19.2.4",
- "react-icons": "^5.6.0"
+ "react-icons": "^5.6.0",
+ "react-lorem-ipsum": "^1.4.10",
+ "zustand": "^5.0.12"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8e10530..b3ffd56 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,7 +19,7 @@ importers:
version: 11.14.0(@types/react@19.2.14)(react@19.2.4)
antd:
specifier: ^6.3.5
- version: 6.3.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ version: 6.3.5(date-fns@2.30.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -32,6 +32,12 @@ importers:
react-icons:
specifier: ^5.6.0
version: 5.6.0(react@19.2.4)
+ react-lorem-ipsum:
+ specifier: ^1.4.10
+ version: 1.4.10
+ zustand:
+ specifier: ^5.0.12
+ version: 5.0.12(@types/react@19.2.14)(react@19.2.4)
devDependencies:
'@eslint/js':
specifier: ^9.39.4
@@ -1151,6 +1157,10 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ date-fns@2.30.0:
+ resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
+ engines: {node: '>=0.11'}
+
dayjs@1.11.20:
resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==}
@@ -1583,6 +1593,9 @@ packages:
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-lorem-ipsum@1.4.10:
+ resolution: {integrity: sha512-PCEuauLZTGJkm++oxJeUycEgQOBg3qmmD7pn5sUyq9e0OvvNbW32RKQsSgalAYGUIbS91UkDgxvt6iHVAsqYJw==}
+
react@19.2.4:
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
engines: {node: '>=0.10.0'}
@@ -1773,6 +1786,24 @@ packages:
zod@4.3.6:
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
+ zustand@5.0.12:
+ resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==}
+ engines: {node: '>=12.20.0'}
+ peerDependencies:
+ '@types/react': '>=18.0.0'
+ immer: '>=9.0.6'
+ react: '>=18.0.0'
+ use-sync-external-store: '>=1.2.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ use-sync-external-store:
+ optional: true
+
snapshots:
'@ant-design/colors@8.0.1':
@@ -2364,7 +2395,7 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
- '@rc-component/picker@1.9.1(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ '@rc-component/picker@1.9.1(date-fns@2.30.0)(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@rc-component/overflow': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/resize-observer': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -2374,6 +2405,7 @@ snapshots:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
optionalDependencies:
+ date-fns: 2.30.0
dayjs: 1.11.20
'@rc-component/portal@2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
@@ -3297,7 +3329,7 @@ snapshots:
dependencies:
color-convert: 2.0.1
- antd@6.3.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ antd@6.3.5(date-fns@2.30.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
'@ant-design/colors': 8.0.1
'@ant-design/cssinjs': 2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -3323,7 +3355,7 @@ snapshots:
'@rc-component/mutate-observer': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/notification': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/pagination': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
- '@rc-component/picker': 1.9.1(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ '@rc-component/picker': 1.9.1(date-fns@2.30.0)(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/progress': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/qrcode': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@rc-component/rate': 1.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@@ -3426,6 +3458,11 @@ snapshots:
csstype@3.2.3: {}
+ date-fns@2.30.0:
+ dependencies:
+ '@babel/runtime': 7.29.2
+ optional: true
+
dayjs@1.11.20: {}
debug@4.4.3:
@@ -3799,6 +3836,8 @@ snapshots:
react-is@18.3.1: {}
+ react-lorem-ipsum@1.4.10: {}
+
react@19.2.4: {}
resolve-from@4.0.0: {}
@@ -3942,3 +3981,8 @@ snapshots:
zod: 4.3.6
zod@4.3.6: {}
+
+ zustand@5.0.12(@types/react@19.2.14)(react@19.2.4):
+ optionalDependencies:
+ '@types/react': 19.2.14
+ react: 19.2.4
diff --git a/src/App.css b/src/App.css
index 508f9f1..e69de29 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,70 +0,0 @@
-.height_40 {
- height: 40px;
-}
-
-.height_40_center {
- height: 40px;
- line-height: 40px;
-}
-
-.display_inline_block {
- display: inline-block;
-}
-
-.text_center {
- text-align: center;
-}
-
-.width_300 {
- width: 300px;
-}
-
-.width_400 {
- width: 400px;
-}
-
-.margin_3_0 {
- margin: 3px 0;
-}
-
-.margin_10_20 {
- margin: 10px 20px;
-}
-
-.margin_10_0 {
- margin: 10px 0;
-}
-
-.margin_0_20 {
- margin: 0 20px;
-}
-
-.margin_0_10 {
- margin: 0 10px;
-}
-
-.margin_10_10 {
- margin: 10px;
-}
-
-.margin_20_10 {
- margin: 20px 10px;
-}
-
-.margin_0_5 {
- margin: 0 5px;
-}
-
-.width_600 {
- width: 600px;
-}
-
-.margin_left_600 {
- margin-left: 600px;
-}
-
-.right-align-container {
- margin-left: auto;
- display: flex;
- align-items: center;
-}
\ No newline at end of file
diff --git a/src/App.tsx b/src/App.tsx
index ce1c484..6a511b5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,147 +1,14 @@
// import { useState } from 'react'
import './App.css'
+import { Provider } from "@/components/ui/provider"
-import { HomeOutlined, SettingOutlined, ApiOutlined, FolderOutlined, ClearOutlined, UserOutlined, CommentOutlined, AlertOutlined, UploadOutlined } from '@ant-design/icons';
-import type { MenuProps } from 'antd';
-import { Menu } from 'antd';
-import React, { useState } from 'react';
-import { Input, Avatar } from 'antd';
-import { SearchOutlined } from '@ant-design/icons';
-
-const items: MenuProps['items'] = [
-
- {
- label: '主页',
- key: 'home',
- icon: ,
- },
- {
- label: '工具大全',
- key: 'tools',
- icon: ,
- },
- {
- label: '文章资源',
- key: 'articles',
- icon: ,
- },
- {
- label: '消息',
- key: 'xx',
- icon: ,
- children:[
- {
- label: '回复我的',
- key: 'xx1',
- },
- {
- label: '@我的',
- key: 'xx2',
- },
- {
- label: '收到的赞',
- key: 'xx3',
- },
- {
- label: '系统消息',
- key: 'xx4',
- },
- {
- label: '我的消息',
- key: 'xx5',
- }
- ]
- },
- {
- label: 'bug反馈',
- key: 'bug',
- icon: ,
- },
- {
- label: (}
- />),
- key: 'search',
- disabled: true,
- className: "right-align-container",
- },
- {
- label: (
-
- } className='margin_3_0'/>
-
- 用户: 10086
-
- ),
- key: 'home',
- children: [
- {
- className: "width_300",
- type: 'group',
- label: (
-
用户10086
- ),
- children: [
- {
- label: '个人中心',
- key: 'setting:1',
- icon:
- },
- {
- label: '个人设置',
- key: 'setting:2',
- icon: ,
- },
-
- {
- label: '浏览历史',
- key: 'setting:2',
- icon:
- },
- {
- label: (
-
- ),
- disabled: true,
- key: 'divider',
- },
- {
- label: '退出登录',
- key: 'setting:3',
- icon:
- }
- ],
- }
- ],
- className: "right-align-container",
- },
-];
-
+import Navbar from '@/components/Navbar/Navbar';
const App: React.FC = () => {
- const [current, setCurrent] = useState('mail');
-
- const onClick: MenuProps['onClick'] = e => {
- console.log('click ', e);
- setCurrent(e.key);
- };
return (
-
-
-
-
-
-
+
+
+
);
};
diff --git a/src/components/Navbar/Navbar.css b/src/components/Navbar/Navbar.css
new file mode 100644
index 0000000..ca57e66
--- /dev/null
+++ b/src/components/Navbar/Navbar.css
@@ -0,0 +1,16 @@
+.right-align-container {
+ margin-left: auto;
+ display: flex;
+ align-items: center;
+}
+
+.not-font-select {
+ -webkit-user-select: none;
+ /* Safari */
+ -moz-user-select: none;
+ /* Firefox */
+ -ms-user-select: none;
+ /* Internet Explorer */
+ user-select: none;
+ /* 标准语法 */
+}
\ No newline at end of file
diff --git a/src/components/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx
new file mode 100644
index 0000000..8d1b523
--- /dev/null
+++ b/src/components/Navbar/Navbar.tsx
@@ -0,0 +1,568 @@
+import {
+ HomeOutlined,
+ SettingOutlined,
+ ApiOutlined,
+ FolderOutlined,
+ ClearOutlined,
+ UserOutlined,
+ CommentOutlined,
+ AlertOutlined,
+ UploadOutlined,
+ ClockCircleTwoTone,
+ PlusCircleTwoTone,
+ ControlTwoTone,
+ MessageTwoTone,
+} from "@ant-design/icons";
+import type { MenuProps } from "antd";
+import { Menu } from "antd";
+import React, { useState } from "react";
+import { Input, Avatar } from "antd";
+import { SearchOutlined } from "@ant-design/icons";
+
+import "./Navbar.css";
+
+import { Dialog, Portal, createOverlay, CloseButton } from "@chakra-ui/react";
+import { PasswordInput } from "@/components/ui/password-input";
+
+import { Input as ChakraInput, InputGroup, Box } from "@chakra-ui/react";
+
+import { QRCode, Button } from "antd";
+// import { PasswordInput } from "@/components/ui/password-input"
+
+import { Tabs } from "antd";
+
+import { Space } from "antd";
+
+import { Flex } from "antd";
+
+interface DialogProps {
+ title: string;
+ description?: string;
+ content?: React.ReactNode;
+}
+
+const login_dialog = createOverlay((props) => {
+ const { ...rest } = props;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ 扫描二维码登录
+
+
+
+ 使用APP扫码登录
+
+
+ 扫描登录或者扫码下载APP
+
+
+
+
+
+
+ 账号密码登录
+
+ ),
+ key: "1",
+ children: (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+ },
+ {
+ label: (
+
+ 邮箱验证码登录
+
+ ),
+ key: "2",
+ children: (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+ },
+ ]}
+ />
+
+
+
+ 其他登录方式
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 未注册过账号的手机号/邮箱,我们将自动帮你注册账号{" "}
+
+
+ 登录或完成注册即代表你同意
+
+ 和
+
+
+
+
+
+
+
+ );
+});
+
+// login_dialog.open({});
+
+const Navbar: React.FC = () => {
+ const [current, setCurrent] = useState("mail");
+ const [isLogin, setIsLogin] = useState(false);
+
+ const items: MenuProps["items"] = [
+ {
+ label: "主页",
+ key: "home",
+ icon: ,
+ },
+ {
+ label: "工具大全",
+ key: "tools",
+ icon: ,
+ },
+ {
+ label: "文章资源",
+ key: "articles",
+ icon: ,
+ },
+ {
+ label: "消息",
+ key: "xx",
+ icon: ,
+ children: [
+ {
+ label: "回复我的",
+ key: "xx1",
+ },
+ {
+ label: "@我的",
+ key: "xx2",
+ },
+ {
+ label: "收到的赞",
+ key: "xx3",
+ },
+ {
+ label: "系统消息",
+ key: "xx4",
+ },
+ {
+ label: "我的消息",
+ key: "xx5",
+ },
+ ],
+ },
+ {
+ label: "bug反馈",
+ key: "bug",
+ icon: ,
+ },
+ {
+ label: (
+ }
+ />
+ ),
+ key: "search",
+ disabled: true,
+ className: "right-align-container",
+ },
+ {
+ label: (
+ {
+ login_dialog.open({});
+ }}
+ >
+ } className="margin_3_0" />
+
+ 用户: 10086
+
+
+ ),
+ key: "my",
+ children: isLogin
+ ? [
+ {
+ className: "width_300",
+ type: "group",
+ label: (
+ 用户10086
+ ),
+ children: [
+ {
+ label: "个人中心",
+ key: "setting:1",
+ icon: ,
+ },
+ {
+ label: "个人设置",
+ key: "setting:2",
+ icon: ,
+ },
+
+ {
+ label: "浏览历史",
+ key: "setting:3",
+ icon: ,
+ },
+ {
+ label: (
+
+ ),
+ disabled: true,
+ key: "divider",
+ },
+ {
+ label: "退出登录",
+ key: "setting:4",
+ icon: ,
+ },
+ ],
+ },
+ ]
+ : [
+ {
+ label: (
+
+ ),
+ key: "login",
+ disabled: true,
+ },
+ {
+ label: (
+ <>
+ {" "}
+ 你发布评论后,也可以收到别人的回复
+ >
+ ),
+ disabled: true,
+ },
+ {
+ label: (
+ <>
+ {" "}
+ 查看自己的历史浏览记录
+ >
+ ),
+ disabled: true,
+ },
+ {
+ label: (
+ <>
+ {" "}
+ 收藏需要的工具和文章
+ >
+ ),
+ disabled: true,
+ },
+ {
+ label: (
+ <>
+ {" "}
+ 部分登录才可以使用的功能
+ >
+ ),
+ disabled: true,
+ },
+ {
+ label: (
+
+ ),
+ key: "divider",
+ disabled: true,
+ },
+ {
+ label: (
+
+ 首次登录?{" "}
+
+
+ ),
+ disabled: true,
+ },
+ ],
+ className: "right-align-container",
+ },
+ ];
+
+ const onClick: MenuProps["onClick"] = (e) => {
+ console.log("click ", e);
+ setCurrent(e.key);
+
+ if (e.key == "home") {
+ login_dialog.open({});
+ }
+ };
+ return (
+
+
+
+
+ );
+};
+
+export default Navbar;
diff --git a/src/components/ui/password-input.tsx b/src/components/ui/password-input.tsx
new file mode 100644
index 0000000..3b9af80
--- /dev/null
+++ b/src/components/ui/password-input.tsx
@@ -0,0 +1,159 @@
+"use client"
+
+import type {
+ ButtonProps,
+ GroupProps,
+ InputProps,
+ StackProps,
+} from "@chakra-ui/react"
+import {
+ Box,
+ HStack,
+ IconButton,
+ Input,
+ InputGroup,
+ Stack,
+ mergeRefs,
+ useControllableState,
+} from "@chakra-ui/react"
+import * as React from "react"
+import { LuEye, LuEyeOff } from "react-icons/lu"
+
+export interface PasswordVisibilityProps {
+ /**
+ * The default visibility state of the password input.
+ */
+ defaultVisible?: boolean
+ /**
+ * The controlled visibility state of the password input.
+ */
+ visible?: boolean
+ /**
+ * Callback invoked when the visibility state changes.
+ */
+ onVisibleChange?: (visible: boolean) => void
+ /**
+ * Custom icons for the visibility toggle button.
+ */
+ visibilityIcon?: { on: React.ReactNode; off: React.ReactNode }
+}
+
+export interface PasswordInputProps
+ extends InputProps,
+ PasswordVisibilityProps {
+ rootProps?: GroupProps
+}
+
+export const PasswordInput = React.forwardRef<
+ HTMLInputElement,
+ PasswordInputProps
+>(function PasswordInput(props, ref) {
+ const {
+ rootProps,
+ defaultVisible,
+ visible: visibleProp,
+ onVisibleChange,
+ visibilityIcon = { on: , off: },
+ ...rest
+ } = props
+
+ const [visible, setVisible] = useControllableState({
+ value: visibleProp,
+ defaultValue: defaultVisible || false,
+ onChange: onVisibleChange,
+ })
+
+ const inputRef = React.useRef(null)
+
+ return (
+ {
+ if (rest.disabled) return
+ if (e.button !== 0) return
+ e.preventDefault()
+ setVisible(!visible)
+ }}
+ >
+ {visible ? visibilityIcon.off : visibilityIcon.on}
+
+ }
+ {...rootProps}
+ >
+
+
+ )
+})
+
+const VisibilityTrigger = React.forwardRef(
+ function VisibilityTrigger(props, ref) {
+ return (
+
+ )
+ },
+)
+
+interface PasswordStrengthMeterProps extends StackProps {
+ max?: number
+ value: number
+}
+
+export const PasswordStrengthMeter = React.forwardRef<
+ HTMLDivElement,
+ PasswordStrengthMeterProps
+>(function PasswordStrengthMeter(props, ref) {
+ const { max = 4, value, ...rest } = props
+
+ const percent = (value / max) * 100
+ const { label, colorPalette } = getColorPalette(percent)
+
+ return (
+
+
+ {Array.from({ length: max }).map((_, index) => (
+
+ ))}
+
+ {label && {label}}
+
+ )
+})
+
+function getColorPalette(percent: number) {
+ switch (true) {
+ case percent < 33:
+ return { label: "Low", colorPalette: "red" }
+ case percent < 66:
+ return { label: "Medium", colorPalette: "orange" }
+ default:
+ return { label: "High", colorPalette: "green" }
+ }
+}
diff --git a/src/css.t.ts b/src/css.t.ts
new file mode 100644
index 0000000..e29340f
--- /dev/null
+++ b/src/css.t.ts
@@ -0,0 +1,4 @@
+declare module '*.css' {
+ const classes: { [key: string]: string };
+ export default classes;
+}
\ No newline at end of file
diff --git a/src/global.css b/src/global.css
new file mode 100644
index 0000000..7965aa2
--- /dev/null
+++ b/src/global.css
@@ -0,0 +1,64 @@
+.height_40 {
+ height: 40px;
+}
+
+.height_40_center {
+ height: 40px;
+ line-height: 40px;
+}
+
+.display_inline_block {
+ display: inline-block;
+}
+
+.text_center {
+ text-align: center;
+}
+
+.width_300 {
+ width: 300px;
+}
+
+.width_400 {
+ width: 400px;
+}
+
+.margin_3_0 {
+ margin: 3px 0;
+}
+
+.margin_10_20 {
+ margin: 10px 20px;
+}
+
+.margin_10_0 {
+ margin: 10px 0;
+}
+
+.margin_0_20 {
+ margin: 0 20px;
+}
+
+.margin_0_10 {
+ margin: 0 10px;
+}
+
+.margin_10_10 {
+ margin: 10px;
+}
+
+.margin_20_10 {
+ margin: 20px 10px;
+}
+
+.margin_0_5 {
+ margin: 0 5px;
+}
+
+.width_600 {
+ width: 600px;
+}
+
+.margin_left_600 {
+ margin-left: 600px;
+}
\ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
index 28ede35..ca1efa2 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -4,6 +4,8 @@ import './index.css'
import 'antd/dist/antd.css';
import App from './App.tsx'
+import './global.css'
+
createRoot(document.getElementById('root')!).render(
diff --git a/src/stores/Store.ts b/src/stores/Store.ts
new file mode 100644
index 0000000..e69de29
diff --git a/tsconfig.json b/tsconfig.json
index 1ffef60..14b7c11 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,27 @@
+// {
+// "files": [],
+// "references": [
+// { "path": "./tsconfig.app.json" },
+// { "path": "./tsconfig.node.json" }
+// ]
+// }
{
- "files": [],
- "references": [
- { "path": "./tsconfig.app.json" },
- { "path": "./tsconfig.node.json" }
- ]
-}
+ "compilerOptions": {
+ "types": ["node"],
+ "target": "ES2023",
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "paths": {
+ "@/*": ["./src/*"]
+ },
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true
+ },
+ "include": ["src"]
+}
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 3a219a0..e886103 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,5 +1,6 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+import path from 'path';
// https://vite.dev/config/
export default defineConfig({
@@ -10,4 +11,9 @@ export default defineConfig({
],
},
plugins: [react()],
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'), // 实际上使用了,但可能没被检测到
+ },
+ },
})