Skip to content

Commit

Permalink
feat: 登录与欢迎页
Browse files Browse the repository at this point in the history
  • Loading branch information
kanyxmo committed Oct 24, 2024
1 parent 8a7cb25 commit 5d5e48e
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default defineConfigWithTheme ({
link:"/en/index",
...enGetConfig,
themeConfig:{
logo: '/images/logo.svg',
logo: '/logo.svg',
nav: enGetNavs,
sidebar:enGetSidebar,
outline:{
Expand All @@ -45,7 +45,7 @@ export default defineConfigWithTheme ({
}
},
themeConfig: {
logo: '/images/logo.svg',
logo: '/logo.svg',
outline:{
label: '页面导航',
level: [2, 4],
Expand Down
File renamed without changes
79 changes: 78 additions & 1 deletion docs/zh/front/advanced/login-welcome.md
Original file line number Diff line number Diff line change
@@ -1 +1,78 @@
# 登录与欢迎页
# 登录与欢迎页

:::tip
本章节讲解登录页面、登录代码调用、以及登录后默认跳转的页面配置
:::

## 登录页面

页面在 `src/modules/base/views/login/index.vue`,这个页面实际是个整合页面,登录分为很多小组件,由 `index.vue` 引入整合在一起。
其中,`<LoginForm />` 为表单登录功能,在 `IDE``ctrl(苹果:COMMAND) + 单击` 即可追踪进去查看代码。

::: info 修改建议:
首先说明一点,登录页的表单并非 `Element plus` 组件库,而是使用了 `MineAdmin` 自身的 `基础组件库`,这些组件非常简陋、仅仅支持最普通的功能。
如果需要修改此页面,不建议直接修改源码,以免影响后续 `升级` 的问题。

`3.0`的前端支持了[插件](/zh/front/high/plugin.md)功能,建议通过插件的形式,来改变 `login` 路由的 `component` 属性,达到`替换登录页面`的效果

:::

```vue
<template>
<div class="h-full min-w-[380px] w-full flex items-center justify-center overflow-hidden border-1 bg-blue-950 lg:justify-between lg:bg-white">
<div class="relative hidden h-full w-10/12 md:hidden lg:flex">
<div class="gradient-rainbow" />
<Dashed />
<Light />
<Slogan />
<OneWord />
</div>
<div class="login-form-container">
<Logo />
<LoginForm />
<CopyRight />
</div>
<!-- 下面兼容移动端的 -->
<div class="min-[380px] relative left-0 top-0 z-4 h-full max-w-[1024px] w-full flex lg:hidden">
<Dashed />
<Light />
</div>
</div>
</template>
```

## 登录代码调用

::: info
如果实际开发中只是修改`UI`,不需要修改 `登录流程` 可跳过此段落。
:::

登录调用过程:

- `src/store/modules/useUserStore.ts` 下的 `login()` 方法,内部执行了保存 `token``refresh_token``expire_at` 等认证数据。
- 页面执行跳转欢迎页后,被 `路由守卫` 拦截,去请求用户基础数据。
- `src/store/modules/useUserStore.ts` 下的 `requestUserInfo()` 方法,请求了 `用户数据、菜单权限、角色` 等基础数据。
-`requestUserInfo()` 还执行了重要的一步:初始化 `路由数据`,调用代码:`routeStore.initRoutes()`

以上就是整个登录调用流程,如果还不懂,可以到交流群里咨询或者联系我们。

## 默认欢迎页配置

登录后,如果有指定跳转的路由:`/#/login?redirect=[登录成功跳转的路由地址]`,则会跳转到参数所携带的页面,但这个一般在身份认证过期后
跳转登录页才会携带之前页面地址,默认情况下,我们登录成功后都是跳转到系统内置的默认页面,比如:`index`, `dashboard` 等等。

```ts
welcomePage: {
name: 'welcome',
path: '/welcome',
title: '欢迎页',
icon: 'icon-park-outline:jewelry',
}
```

::: info 配置建议
`3.0` 可配置默认欢迎页面以及名称、图标、描述等,打开 `src/provider/settings/index.ts` 文件,找到 `welcomePage` 配置项,可配置此项。

但不建议直接修改这个文件,可将部分参数 `copy` 到同级目录的 `settings.config.ts` 文件中,系统会自动合并配置参数,而影响默认配置。
:::

130 changes: 125 additions & 5 deletions docs/zh/front/advanced/request.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# 请求与拦截器
MineAdmin基于 [axios](https://github.com/axios/axios) 作为请求库,同时提供了请求拦截器,方便开发者对请求进行统一处理。

## 说明
## 请求

### 说明

系统内封装了两种请求处理:
- 一种仅对 `MineAdmin` 后端的请求封装,只适合 `MineAdmin`**后端**
- 一种是可请求外部网络或者其他后端接口的封装。

## 使用
### 使用
在前端全局任何位置,且无需显性加载,即可使用 `useHttp()`,注意,这个方式仅对 `MineAdmin` 后端有效

```ts
Expand All @@ -29,10 +31,10 @@ http.delete('/xxxx/2')
以上请求,系统会自动处理 `token``error` 等,开发者无需关心,
如果需要传入其他配置,例如: `header``timeout` 等参数,只需要在后面加参数传入即可。

## token刷新
### token刷新
`useHttp()` 内部已经封装了自动续期 `token` 功能,具体原理可查看 [后端文档](/zh/backend/security/passport.md) 这里不再赘述。

## 请求外部网络
### 请求外部网络
以上都是针对 `MineAdmin` 后端请求的说明,外部网络请求方式如下:
```ts
import request from '@/utils/http'
Expand All @@ -51,4 +53,122 @@ const requestHome = async () => {
}

console.log(requestHome())
```
```

## 拦截器

`MineAdmin` 已经封装了拦截器,但需要说明只适配 `MineAdmin` 的后端接口,如果需要调整、修改,打开 `src/utils/http.ts` 文件
找到下面这段代码:
```ts:line-numbers
http.interceptors.response.use(
async (response: AxiosResponse): Promise<any> => {
isLoading.value = false
const userStore = useUserStore()
await usePluginStore().callHooks('networkResponse', response)
const config = response.config
if ((response.request.responseType === 'blob'
|| response.request.responseType === 'arraybuffer')
&& !/^application\/json/.test(response.headers['content-type'])
&& response.status === ResultCode.SUCCESS
) {
return Promise.resolve(response.data)
}
if (response?.data?.code === ResultCode.SUCCESS) {
return Promise.resolve(response.data)
}
else {
switch (response?.data?.code) {
case ResultCode.UNAUTHORIZED: {
const logout = useDebounceFn(
async () => {
Message.error('登录状态已过期,需要重新登录', { zIndex: 9999 })
await useUserStore().logout()
},
3000,
{ maxWait: 5000 },
)
// 检查token是否需要刷新
if (userStore.isLogin && !isRefreshToken.value) {
isRefreshToken.value = true
if (!cache.get('refresh_token')) {
await logout()
break
}
try {
const refreshTokenResponse = await createHttp(null, {
headers: {
Authorization: `Bearer ${cache.get('refresh_token')}`,
},
}).post('/admin/passport/refresh')
if (refreshTokenResponse.data.code !== 200) {
await logout()
break
}
else {
const { data } = refreshTokenResponse.data
userStore.token = data.access_token
cache.set('token', data.access_token)
cache.set('expire', useDayjs().unix() + data.expire_at, { exp: data.expire_at })
cache.set('refresh_token', data.refresh_token)
config.headers!.Authorization = `Bearer ${userStore.token}`
requestList.value.map((cb: any) => cb())
requestList.value = []
return http(config)
}
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e: any) {
requestList.value.map((cb: any) => cb())
await logout()
break
}
finally {
requestList.value = []
isRefreshToken.value = false
}
}
else {
return new Promise((resolve) => {
requestList.value.push(() => {
config.headers!.Authorization = `Bearer ${cache.get('token')}`
resolve(http(config))
})
})
}
}
case ResultCode.NOT_FOUND:
Message.error('服务器资源不存在', { zIndex: 9999 })
break
case ResultCode.FORBIDDEN:
Message.error('没有权限访问此接口', { zIndex: 9999 })
break
case ResultCode.METHOD_NOT_ALLOWED:
Message.error('请求方法不被允许', { zIndex: 9999 })
break
case ResultCode.FAIL:
Message.error('服务器内部错误', { zIndex: 9999 })
break
default:
Message.error(response?.data?.message ?? '未知错误', { zIndex: 9999 })
break
}
return Promise.reject(response.data ? response.data : null)
}
},
async (error: any) => {
isLoading.value = false
const serverError = useDebounceFn(async () => {
if (error && error.response && error.response.status === 500) {
Message.error(error.message ?? '服务器内部错误', { zIndex: 9999 })
}
}, 3000, { maxWait: 5000 })
await serverError()
return Promise.reject(error)
},
)
```
2 changes: 1 addition & 1 deletion docs/zh/front/component/ma-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

### useForm 方式

<div style="margin-top: 20px;">
<div class="mt-5 shadow-lg">
<ma-form ref="form" :items="[
{ label: '用户名', prop: 'username', render: 'input' },
{ label: '昵称', prop: 'nickname', render: 'input' },
Expand Down

0 comments on commit 5d5e48e

Please sign in to comment.