封装axios && 引入zustand
This commit is contained in:
118
package-lock.json
generated
118
package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"antd": "^5.19.3",
|
||||
"apexcharts": "^3.41.0",
|
||||
"axios": "^1.7.2",
|
||||
"flatpickr": "^4.6.13",
|
||||
"headlessui": "^0.0.0",
|
||||
"jsvectormap": "^1.5.3",
|
||||
@@ -24,7 +25,8 @@
|
||||
"sass": "^1.77.8",
|
||||
"sort-by": "^0.0.2",
|
||||
"vditor": "^3.10.4",
|
||||
"vite-plugin-sass-dts": "^1.3.25"
|
||||
"vite-plugin-sass-dts": "^1.3.25",
|
||||
"zustand": "^4.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.17",
|
||||
@@ -1108,13 +1110,13 @@
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.17.tgz",
|
||||
"integrity": "sha512-u+e7OlgPPh+aryjOm5UJMX32OvB2E3QASOAqVMY6Ahs90djagxwv2ya0IctglNbNTexC12qCSMZG47KPfy1hAA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@@ -1134,7 +1136,7 @@
|
||||
"version": "0.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.0.3",
|
||||
@@ -1475,6 +1477,11 @@
|
||||
"resolved": "https://registry.npmmirror.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
|
||||
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.14",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
|
||||
@@ -1508,6 +1515,16 @@
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.2.tgz",
|
||||
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -1706,6 +1723,17 @@
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
@@ -1779,6 +1807,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
@@ -2021,6 +2057,38 @@
|
||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
|
||||
"integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw=="
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
|
||||
@@ -2426,7 +2494,6 @@
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@@ -2435,7 +2502,6 @@
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
@@ -2820,6 +2886,11 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
@@ -4111,6 +4182,14 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@@ -4288,6 +4367,33 @@
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmmirror.com/zustand/-/zustand-4.5.4.tgz",
|
||||
"integrity": "sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==",
|
||||
"dependencies": {
|
||||
"use-sync-external-store": "1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": ">=16.8",
|
||||
"immer": ">=9.0.6",
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"immer": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"dependencies": {
|
||||
"antd": "^5.19.3",
|
||||
"apexcharts": "^3.41.0",
|
||||
"axios": "^1.7.2",
|
||||
"flatpickr": "^4.6.13",
|
||||
"headlessui": "^0.0.0",
|
||||
"jsvectormap": "^1.5.3",
|
||||
@@ -30,7 +31,8 @@
|
||||
"sass": "^1.77.8",
|
||||
"sort-by": "^0.0.2",
|
||||
"vditor": "^3.10.4",
|
||||
"vite-plugin-sass-dts": "^1.3.25"
|
||||
"vite-plugin-sass-dts": "^1.3.25",
|
||||
"zustand": "^4.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.17",
|
||||
|
||||
@@ -3,7 +3,11 @@ import Vditor from "vditor";
|
||||
import "vditor/dist/index.css";
|
||||
import "./index.scss"
|
||||
|
||||
const VditorEditor = () => {
|
||||
interface VditorProps {
|
||||
getValue: (value: string) => void
|
||||
}
|
||||
|
||||
const VditorEditor = ({ getValue }: VditorProps) => {
|
||||
const [vd, setVd] = useState<Vditor>();
|
||||
useEffect(() => {
|
||||
const vditor = new Vditor("vditor", {
|
||||
@@ -12,9 +16,13 @@ const VditorEditor = () => {
|
||||
// enable: true,
|
||||
// position: 'left'
|
||||
// },
|
||||
input: (value) => {
|
||||
// 把数据传给父组件
|
||||
getValue(value)
|
||||
},
|
||||
after: () => {
|
||||
vditor.setValue("`Vditor` 最小代码示例");
|
||||
vditor.setTheme("classic","","github")
|
||||
|
||||
setVd(vditor);
|
||||
}
|
||||
})
|
||||
@@ -25,8 +33,8 @@ const VditorEditor = () => {
|
||||
setVd(undefined);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <div id="vditor" className="vditor"/>;
|
||||
|
||||
return <div id="vditor" className="vditor" />;
|
||||
};
|
||||
|
||||
export default VditorEditor;
|
||||
|
||||
@@ -10,6 +10,11 @@ const Create = () => {
|
||||
const [content, setContent] = useState('');
|
||||
const [publishOpen, setPublishOpen] = useState(false)
|
||||
|
||||
// 获取编辑器的内容
|
||||
const getVditorData = (value: string) => {
|
||||
console.log(111, value);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log(content);
|
||||
}, [content])
|
||||
@@ -22,7 +27,7 @@ const Create = () => {
|
||||
<BiSave className='text-base' /> 保存</Button>
|
||||
</div>
|
||||
|
||||
<VditorEditor />
|
||||
<VditorEditor getValue={getVditorData} />
|
||||
|
||||
<Drawer
|
||||
title="发布文章"
|
||||
|
||||
3
src/stores/index.ts
Normal file
3
src/stores/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import useUserStore from './modules/user'
|
||||
|
||||
export { useUserStore }
|
||||
25
src/stores/modules/user.ts
Normal file
25
src/stores/modules/user.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { create } from 'zustand'
|
||||
|
||||
interface UserStore {
|
||||
token: string;
|
||||
user: User;
|
||||
setData: (data: User) => void;
|
||||
quitLogin: () => void
|
||||
}
|
||||
|
||||
export default create<UserStore>((set) => ({
|
||||
token: "",
|
||||
user: {} as User,
|
||||
setData: (data: User) => set(() => ({ user: data })),
|
||||
// 退出登录
|
||||
quitLogin: () => set(() => {
|
||||
localStorage.clear()
|
||||
sessionStorage.clear()
|
||||
location.href = "/login"
|
||||
|
||||
return {
|
||||
user: {} as User,
|
||||
token: ""
|
||||
}
|
||||
})
|
||||
}))
|
||||
15
src/types/response.d.ts
vendored
Normal file
15
src/types/response.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
interface Response<T> {
|
||||
code: number,
|
||||
message: string
|
||||
data: T
|
||||
}
|
||||
|
||||
interface Paginate<T> {
|
||||
next: boolean,
|
||||
prev: boolean,
|
||||
page: number,
|
||||
size: number,
|
||||
pages: number,
|
||||
total: number,
|
||||
result: T
|
||||
}
|
||||
26
src/types/user.d.ts
vendored
Normal file
26
src/types/user.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
interface Login {
|
||||
username: string,
|
||||
password: string
|
||||
}
|
||||
|
||||
interface UserInfo {
|
||||
id?: number,
|
||||
name: string,
|
||||
email: string,
|
||||
avatar: string,
|
||||
info: string,
|
||||
role?: string
|
||||
}
|
||||
|
||||
type User = Login & UserInfo
|
||||
|
||||
interface account {
|
||||
token: string,
|
||||
user: User
|
||||
}
|
||||
|
||||
interface editUser {
|
||||
username: string,
|
||||
oldPassword: string,
|
||||
newPassword: string
|
||||
}
|
||||
87
src/utils/request.ts
Normal file
87
src/utils/request.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from "axios";
|
||||
import { useUserStore } from "@/stores";
|
||||
import { Modal, notification } from "antd";
|
||||
|
||||
// 配置项目API域名
|
||||
export const baseURL = "http://localhost:5000/api";
|
||||
|
||||
// 创建 axios 实例
|
||||
export const instance = axios.create({
|
||||
// 项目API根路径
|
||||
baseURL,
|
||||
// 请求超时的时间
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
// 请求拦截
|
||||
instance.interceptors.request.use(
|
||||
(config: InternalAxiosRequestConfig) => {
|
||||
const token = useUserStore((state) => state.token)
|
||||
|
||||
// 如果有token就把赋值给请求头
|
||||
if (token) config.headers["Authorization"] = `Bearer ${token}`;
|
||||
|
||||
return config;
|
||||
},
|
||||
(err: AxiosError) => {
|
||||
notification.error({
|
||||
message: '程序异常',
|
||||
description: err.message,
|
||||
})
|
||||
|
||||
return Promise.reject(err);
|
||||
}
|
||||
);
|
||||
|
||||
// 响应拦截
|
||||
instance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
// 如果code为401就证明认证失败
|
||||
if (res.data.code === 401) {
|
||||
const quitLogin = useUserStore((state) => state.quitLogin)
|
||||
|
||||
return Modal.error({
|
||||
title: '暂无权限',
|
||||
content: '🔒️ 登录已过期,是否重新登录?',
|
||||
okText: "去登录",
|
||||
onOk: () => {
|
||||
quitLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 只要code不等于200, 就相当于响应失败
|
||||
if (res.data?.code !== 200) {
|
||||
notification.error({
|
||||
message: '程序异常',
|
||||
description: res.data?.message || "未知错误",
|
||||
})
|
||||
|
||||
return Promise.reject(res.data);
|
||||
}
|
||||
|
||||
return res.data;
|
||||
},
|
||||
(err: AxiosError) => {
|
||||
// 服务器异常:网络错误、请求超时、状态码不在200-299之间等等
|
||||
notification.error({
|
||||
message: '服务器异常',
|
||||
description: err.message || "未知错误",
|
||||
})
|
||||
|
||||
return Promise.reject(err);
|
||||
}
|
||||
);
|
||||
|
||||
// 如果是GET传参就自动识别为query,POST为data
|
||||
const Request = <T>(method: string, url: string, reqParams?: object) => {
|
||||
if (!method) method = "GET";
|
||||
|
||||
return instance.request<any, Response<T>>({
|
||||
method,
|
||||
url,
|
||||
[method.toLocaleUpperCase() === "GET" ? "params" : "data"]: reqParams,
|
||||
});
|
||||
};
|
||||
|
||||
export default Request;
|
||||
Reference in New Issue
Block a user