docs: update docs

This commit is contained in:
fonghehe 2026-04-30 19:42:47 +08:00
parent 8ab84371b4
commit 43058ec878
5 changed files with 116 additions and 34 deletions

View File

@ -308,7 +308,7 @@ service.interceptors.request.use(
// do something with request error
console.log(error); // for debug
return Promise.reject(error);
}
},
);
// respone拦截器
service.interceptors.response.use(
@ -331,7 +331,7 @@ service.interceptors.response.use(
Toast.clear();
console.log("err" + error); // for debug
return Promise.reject(error);
}
},
);
export default service;
```

View File

@ -30,7 +30,7 @@ service.interceptors.request.use(
});
}
if (store.getters.token) {
config.headers["X-Token"] = "";
config.headers["X-Token"] = store.getters.token;
}
return config;
},
@ -38,7 +38,7 @@ service.interceptors.request.use(
// do something with request error
console.log(error); // for debug
return Promise.reject(error);
}
},
);
// respone拦截器
service.interceptors.response.use(
@ -48,7 +48,7 @@ service.interceptors.response.use(
if (res.status && res.status !== 200) {
// 登录超时,重新登录
if (res.status === 401) {
store.dispatch("FedLogOut").then(() => {
store.dispatch("fedLogOut").then(() => {
location.reload();
});
}
@ -61,7 +61,7 @@ service.interceptors.response.use(
Toast.clear();
console.log("err" + error); // for debug
return Promise.reject(error);
}
},
);
export default service;
```

View File

@ -6,28 +6,52 @@
前往: [vue.config.js 基础配置](#base)
### 路由配置 (router.config.js)
```javascript
export const constantRouterMap = [
{
path: "/",
component: () => import("@/views/layouts/index"),
redirect: "/home",
meta: { title: "首页", keepAlive: false },
children: [
{
path: "/home",
name: "Home",
component: () => import("@/views/home/index"),
meta: { title: "首页", keepAlive: false },
},
{
path: "/about",
name: "About",
component: () => import("@/views/home/about"),
meta: { title: "关于我", keepAlive: false },
},
],
},
// 404 catch-all
{
path: "*",
redirect: "/home",
},
];
```
### 路由实例 (router/index.js)
```javascript
import Vue from "vue";
import Router from "vue-router";
import { constantRouterMap } from "./router.config.js";
Vue.use(Router);
export const router = [
{
path: "/",
name: "index",
component: () => import("@/views/home/index"), // 路由懒加载
meta: {
title: "首页", // 页面标题
keepAlive: false, // keep-alive 标识
},
},
];
const createRouter = () =>
new Router({
// mode: 'history', // 如果你是 history模式 需要配置 vue.config.js publicPath
// base: '/app/',
scrollBehavior: () => ({ y: 0 }),
routes: router,
routes: constantRouterMap,
});
export default createRouter();

View File

@ -24,7 +24,46 @@ new Vue({
});
```
使用
### Store 模块modules/app.js
```javascript
const state = {
userName: "",
token: "",
};
const mutations = {
SET_USER_NAME(state, name) {
state.userName = name;
},
SET_TOKEN(state, token) {
state.token = token;
},
};
const actions = {
setUserName({ commit }, name) {
commit("SET_USER_NAME", name);
},
// 前端登出
fedLogOut({ commit }) {
return new Promise((resolve) => {
commit("SET_TOKEN", "");
commit("SET_USER_NAME", "");
resolve();
});
},
};
```
### Getters
```javascript
const getters = {
userName: (state) => state.app.userName,
token: (state) => state.app.token,
};
```
### 使用
```html
<script>
@ -39,7 +78,7 @@ new Vue({
doDispatch() {
this.$store.dispatch(
"setUserName",
"真乖,赶紧关注公众号,组织都在等你~"
"真乖,赶紧关注公众号,组织都在等你~",
);
},
},

View File

@ -17,15 +17,20 @@ import type {
InternalAxiosRequestConfig,
} from "axios";
import { showToast } from "vant";
import { useUserStore } from "@/store/modules/user";
const service: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || "",
withCredentials: false,
timeout: 10000,
timeout: 15000,
});
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const userStore = useUserStore();
if (userStore.token) {
config.headers.Authorization = `Bearer ${userStore.token}`;
}
return config;
},
(error: AxiosError) => {
@ -37,15 +42,22 @@ service.interceptors.response.use(
(response: AxiosResponse) => {
const res = response.data;
if (res.code !== 200) {
showToast(res.msg);
return Promise.reject(res.msg || "Error");
} else {
return res.data;
showToast(res.msg || "Error");
return Promise.reject(new Error(res.msg || "Error"));
}
return res.data;
},
(error: AxiosError) => {
showToast(error.message);
return Promise.reject(error.message);
const status = error.response?.status;
if (status === 401) {
const userStore = useUserStore();
userStore.$reset();
window.location.hash = "#/login";
}
const message =
(error.response?.data as any)?.msg || error.message || "Network Error";
showToast(message);
return Promise.reject(error);
},
);
@ -75,26 +87,31 @@ export const http = {
export default service;
```
### 主要特点
- **请求拦截器**:自动从 Pinia store 注入 `Authorization` token
- **响应拦截器**:统一处理业务错误码和 HTTP 错误
- **401 处理**:自动清除登录态并跳转登录页
- **泛型支持**`http.get<UserInfo>(url)` 获得正确的类型推导
## useFetchApi 封装
项目同时提供了基于 `@vueuse/core``createFetch` 封装,支持响应式的请求:
```typescript
import { createFetch } from "@vueuse/core";
import { useCookies } from "@vueuse/integrations/useCookies";
import { showNotify } from "vant";
import { useUserStore } from "@/store/modules/user";
const useFetchApi = createFetch({
baseUrl: "",
options: {
async beforeFetch({ options }) {
const myToken =
useCookies().get(
(import.meta.env.VITE_TOKEN_KEY as string) || "Authorization",
) || "";
const userStore = useUserStore();
const token = userStore.token || "";
options.headers = {
...options.headers,
Authorization: `Bearer ${myToken}`,
Authorization: `Bearer ${token}`,
};
return { options };
},
@ -108,6 +125,8 @@ const useFetchApi = createFetch({
export default useFetchApi;
```
> 两种请求方案均统一从 Pinia `useUserStore` 获取 token保持认证策略一致。
## 接口管理
`src/api/index.ts` 中统一管理接口: