feat: 使用后端的验证码

This commit is contained in:
valarchie 2023-06-23 17:03:53 +08:00
parent 6130cd3149
commit 95a9675c7c
14 changed files with 90 additions and 25 deletions

View File

@ -6,3 +6,6 @@ VITE_PUBLIC_PATH = ./
# 开发环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash"
# 后端地址
VITE_APP_BASE_API = '/dev-api'

View File

@ -10,4 +10,7 @@ VITE_CDN = false
# 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
# 压缩时删除原始文件的配置gzip-clear、brotli-clear、both-clear同时开启 gzip 与 brotli 压缩、none不开启压缩默认
VITE_COMPRESSION = "none"
VITE_COMPRESSION = "none"
# 后端地址
VITE_APP_BASE_API = '/prod-api'

View File

@ -14,3 +14,6 @@ VITE_CDN = true
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
# 压缩时删除原始文件的配置gzip-clear、brotli-clear、both-clear同时开启 gzip 与 brotli 压缩、none不开启压缩默认
VITE_COMPRESSION = "none"
# 后端地址
VITE_APP_BASE_API = '/stage-api'

View File

@ -7,7 +7,8 @@ const wrapperEnv = (envConfigs: Recordable): ViteEnv => {
VITE_ROUTER_HISTORY: "",
VITE_CDN: false,
VITE_HIDE_HOME: "false",
VITE_COMPRESSION: "none"
VITE_COMPRESSION: "none",
VITE_APP_BASE_API: ""
};
for (const configName of Object.keys(envConfigs)) {

38
src/api/common.ts Normal file
View File

@ -0,0 +1,38 @@
import { http } from "@/utils/http";
/** 可以做成泛型 */
export type CaptchaResult = {
success: boolean;
data: CaptchaDTO;
};
export type CaptchaDTO = {
/** 验证码开关 */
isCaptchaOn: boolean;
/** */
uuid: string;
/** `token` */
img: string;
};
export type RefreshTokenResult = {
success: boolean;
data: {
/** `token` */
accessToken: string;
/** 用于调用刷新`accessToken`的接口时所需的`token` */
refreshToken: string;
/** `accessToken`的过期时间(格式'xxxx/xx/xx xx:xx:xx' */
expires: Date;
};
};
/** 验证码接口 */
export const getCaptchaCode = () => {
return http.request<CaptchaResult>("get", "/captchaImage");
};
/** 刷新token */
export const refreshTokenApi = (data?: object) => {
return http.request<RefreshTokenResult>("post", "/refreshToken", { data });
};

View File

@ -30,6 +30,7 @@ export const useImageVerify = (width = 120, height = 40) => {
};
};
/** 前端自己生成验证码 */
function randomNum(min: number, max: number) {
const num = Math.floor(Math.random() * (max - min) + min);
return num;

View File

@ -14,10 +14,13 @@ import NProgress from "../progress";
import { getToken, formatToken } from "@/utils/auth";
import { useUserStoreHook } from "@/store/modules/user";
const { VITE_APP_BASE_API } = import.meta.env;
// 相关配置请参考www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
// 请求超时时间
timeout: 10000,
// 后端请求地址
baseURL: VITE_APP_BASE_API,
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",

View File

@ -90,7 +90,7 @@ function onBack() {
:loading="loading"
@click="onLogin(ruleFormRef)"
>
{{ "登录" }}
登录
</el-button>
</el-form-item>
</Motion>
@ -98,7 +98,7 @@ function onBack() {
<Motion :delay="200">
<el-form-item>
<el-button class="w-full" size="default" @click="onBack">
{{ "返回" }}
返回
</el-button>
</el-form-item>
</Motion>

View File

@ -21,7 +21,7 @@ const $pageEmit = defineEmits(["update:currentPage"]);
</Motion>
<Motion :delay="150">
<el-button class="w-full mt-4" @click="$pageEmit('update:currentPage', 0)">
{{ "返回" }}
返回
</el-button>
</Motion>
</template>

View File

@ -159,12 +159,8 @@ function onBack() {
<Motion :delay="300">
<el-form-item>
<el-checkbox v-model="checked">
{{ "我已仔细阅读并接受" }}
</el-checkbox>
<el-button link type="primary">
{{ "隐私政策" }}
</el-button>
<el-checkbox v-model="checked"> 我已仔细阅读并接受 </el-checkbox>
<el-button link type="primary"> 隐私政策 </el-button>
</el-form-item>
</Motion>
@ -177,7 +173,7 @@ function onBack() {
:loading="loading"
@click="onUpdate(ruleFormRef)"
>
{{ "确定" }}
确定
</el-button>
</el-form-item>
</Motion>
@ -185,7 +181,7 @@ function onBack() {
<Motion :delay="400">
<el-form-item>
<el-button class="w-full" size="default" @click="onBack">
{{ "返回" }}
返回
</el-button>
</el-form-item>
</Motion>

View File

@ -138,7 +138,7 @@ function onBack() {
:loading="loading"
@click="onUpdate(ruleFormRef)"
>
{{ "确定" }}
确定
</el-button>
</el-form-item>
</Motion>
@ -146,7 +146,7 @@ function onBack() {
<Motion :delay="300">
<el-form-item>
<el-button class="w-full" size="default" @click="onBack">
{{ "返回" }}
返回
</el-button>
</el-form-item>
</Motion>

View File

@ -16,7 +16,6 @@ import { useLayout } from "@/layout/hooks/useLayout";
import { useUserStoreHook } from "@/store/modules/user";
import { initRouter, getTopMenu } from "@/router/utils";
import { bg, avatar, illustration } from "./utils/static";
import { ReImageVerify } from "@/components/ReImageVerify";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
@ -24,12 +23,13 @@ import dayIcon from "@/assets/svg/day.svg?component";
import darkIcon from "@/assets/svg/dark.svg?component";
import Lock from "@iconify-icons/ri/lock-fill";
import User from "@iconify-icons/ri/user-3-fill";
import * as CommonAPI from "@/api/common";
defineOptions({
name: "Login"
});
const imgCode = ref("");
const captchaCodeBase64 = ref("");
const router = useRouter();
const loading = ref(false);
const checked = ref(false);
@ -80,7 +80,13 @@ function onkeypress({ code }: KeyboardEvent) {
}
}
onMounted(() => {
function getCaptchaCode() {
CommonAPI.getCaptchaCode().then(res => {
captchaCodeBase64.value = `data:image/gif;base64,${res.data.img}`;
});
}
onMounted(async () => {
window.document.addEventListener("keypress", onkeypress);
});
@ -169,7 +175,13 @@ onBeforeUnmount(() => {
:prefix-icon="useRenderIcon('ri:shield-keyhole-line')"
>
<template v-slot:append>
<ReImageVerify v-model:code="imgCode" />
<img
width="120"
height="40"
class="cursor-pointer"
:src="captchaCodeBase64"
@click="getCaptchaCode"
/>
</template>
</el-input>
</el-form-item>
@ -178,11 +190,9 @@ onBeforeUnmount(() => {
<Motion :delay="250">
<el-form-item>
<div class="w-full h-[20px] flex justify-between items-center">
<el-checkbox v-model="checked">
{{ "记住密码" }}
</el-checkbox>
<el-checkbox v-model="checked"> 记住密码 </el-checkbox>
<el-button link type="primary" @click="currentPage = 4">
{{ "忘记密码" }}
忘记密码
</el-button>
</div>
<el-button
@ -192,7 +202,7 @@ onBeforeUnmount(() => {
:loading="loading"
@click="onLogin(ruleFormRef)"
>
{{ "登录" }}
登录
</el-button>
</el-form-item>
</Motion>

1
types/global.d.ts vendored
View File

@ -64,6 +64,7 @@ declare global {
VITE_CDN: boolean;
VITE_HIDE_HOME: string;
VITE_COMPRESSION: ViteCompression;
VITE_APP_BASE_API: string;
}
/**

View File

@ -43,7 +43,13 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
port: VITE_PORT,
host: "0.0.0.0",
// 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
proxy: {}
proxy: {
"/dev-api": {
target: "http://localhost:8080",
changeOrigin: true,
rewrite: path => path.replace(/^\/dev-api/, "")
}
}
},
plugins: getPluginsList(command, VITE_CDN, VITE_COMPRESSION),
// https://cn.vitejs.dev/config/dep-optimization-options.html#dep-optimization-options