feat:优化验证码的代码,迁移到 components 目录下

feat:在 register.vue、code-login.vue 里,增加验证码
This commit is contained in:
YunaiV
2025-12-15 21:55:56 +08:00
parent 87821086ef
commit 39c9d18403
13 changed files with 95 additions and 45 deletions

2
env/.env vendored
View File

@@ -36,7 +36,7 @@ VITE_COPY_NATIVE_RES_ENABLE = false
# 租户开关
VITE_APP_TENANT_ENABLE=true
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true
VITE_APP_CAPTCHA_ENABLE=false
# 默认账户密码
VITE_APP_DEFAULT_LOGIN_TENANT_ID = 1
VITE_APP_DEFAULT_LOGIN_USERNAME = admin

8
pnpm-lock.yaml generated
View File

@@ -63,6 +63,9 @@ importers:
abortcontroller-polyfill:
specifier: ^1.7.8
version: 1.7.8
crypto-js:
specifier: ^4.2.0
version: 4.2.0
dayjs:
specifier: 1.11.10
version: 1.11.10
@@ -2947,6 +2950,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
crypto-js@4.2.0:
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
css-font-size-keywords@1.0.0:
resolution: {integrity: sha512-Q+svMDbMlelgCfH/RVDKtTDaf5021O486ZThQPIpahnIjUkMUslC+WuOQSWTgGSrNCH08Y7tYNEmmy0hkfMI8Q==}
@@ -9802,6 +9808,8 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
crypto-js@4.2.0: {}
css-font-size-keywords@1.0.0: {}
css-font-stretch-keywords@1.0.1: {}

View File

@@ -65,19 +65,12 @@ export interface AuthResetPasswordReqVO {
password: string
}
/**
* 获取验证码
* @returns ICaptcha 验证码
*/
/** 获取验证码 */
export function getCode(data: any) {
return http.post<ICaptcha>('/system/captcha/get', data, null, null, { original: true })
}
/**
* 校验验证码
* @param data 验证码校验参数
* @returns Promise 包含校验结果
*/
/** 校验验证码 */
export function checkCaptcha(data: any) {
return http.post<boolean>('/system/captcha/check', data, null, null, { original: true })
}
@@ -117,24 +110,12 @@ export function smsResetPassword(data: AuthResetPasswordReqVO) {
return http.post<boolean>('/system/auth/reset-password', data)
}
/**
* 刷新token
* @param refreshToken 刷新token
*/
/** 刷新token */
export function refreshToken(refreshToken: string) {
return http.post<IDoubleTokenRes>(`/system/auth/refresh-token?refreshToken=${refreshToken}`)
}
/**
* 获取用户信息
*/
export function getUserInfo() {
return http.get<IUserInfoRes>('/user/info')
}
/**
* 获取权限信息
*/
/** 获取权限信息 */
export function getAuthPermissionInfo() {
return http.get<AuthPermissionInfo>('/system/auth/get-permission-info')
}
@@ -144,20 +125,7 @@ export function logout() {
return http.post<void>('/system/auth/logout')
}
/**
* 修改用户信息
*/
export function updateInfo(data: IUpdateInfo) {
return http.post('/user/updateInfo', data)
}
/**
* 修改用户密码
*/
export function updateUserPassword(data: IUpdatePassword) {
return http.post('/user/updatePassword', data)
}
// TODO @芋艿:三方登录
/**
* 获取微信登录凭证
* @returns Promise 包含微信登录凭证(code)
@@ -172,6 +140,7 @@ export function getWxCode() {
})
}
// TODO @芋艿:三方登录
/**
* 微信登录
* @param params 微信登录参数包含code

View File

@@ -0,0 +1 @@
export { default as Verify } from './verify.vue'

View File

@@ -1,4 +1,5 @@
import CryptoJS from 'crypto-js'
/**
* @word
* @keyWord String

View File

@@ -29,8 +29,8 @@
* @description 分发验证码使用
*/
import { computed, ref, watchEffect } from 'vue'
import VerifyPoints from './Verify/VerifyPoints.vue'
import VerifySlide from './Verify/VerifySlide.vue'
import VerifyPoints from './verify/verify-points.vue'
import VerifySlide from './verify/verify-slide.vue'
defineOptions({
options: {

View File

@@ -100,7 +100,7 @@ export function http<T>(options: CustomRequestOptions) {
// 处理其他成功状态HTTP状态码200-299
if (res.statusCode >= 200 && res.statusCode < 300) {
// add by panda 25.12.10:如果设置了 original 为 true则返回原始数据
// add by panda 25.12.10:如果设置了 original 为 true则返回原始数据。例如说:滑块验证码,有自己的返回格式
if (options.original) {
return resolve(responseData as unknown as T)
}

View File

@@ -34,5 +34,6 @@ export interface PageResult<T> {
list: T[]
total: number
}
/** 加载状态枚举 - 从 wot-design-uni 重新导出 */
export type { LoadMoreState } from 'wot-design-uni/components/wd-loadmore/types'

View File

@@ -24,6 +24,16 @@
:scene="21"
:before-send="validateBeforeSend"
/>
<view v-if="captchaEnabled">
<Verify
ref="verifyRef"
:captcha-type="captchaType"
explain="向右滑动完成验证"
:img-size="{ width: '300px', height: '150px' }"
mode="pop"
@success="verifySuccess"
/>
</view>
<!-- 登录按钮 -->
<view class="mb-2 mt-2 flex justify-between">
@@ -51,6 +61,7 @@ import { isMobile } from "@/utils/validator";
import CodeInput from "./components/code-input.vue";
import Header from "./components/header.vue";
import TenantPicker from "./components/tenant-picker.vue";
import { Verify } from '@/components/verifition';
defineOptions({
name: "SmsLoginPage",
@@ -67,10 +78,14 @@ const toast = useToast();
const loading = ref(false); // 加载状态
const redirectUrl = ref<string>(); // 重定向地址
const tenantPickerRef = ref<InstanceType<typeof TenantPicker>>(); // 租户选择器引用
const captchaEnabled = import.meta.env.VITE_APP_CAPTCHA_ENABLE === 'true'; // 验证码开关
const verifyRef = ref();
const captchaType = ref('blockPuzzle'); // 滑块验证码 blockPuzzle|clickWord
const formData = reactive({
mobile: "",
code: "",
captchaVerification: "", // 验证码校验值
}); // 表单数据
/** 页面加载时处理重定向 */
@@ -85,6 +100,18 @@ function validateBeforeSend(): boolean {
return tenantPickerRef.value?.validate() ?? false;
}
/** 获取验证码 */
async function getCode() {
// 情况一,未开启:则直接登录
if (!captchaEnabled) {
await verifySuccess({});
} else {
// 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行登录
// 弹出验证码
verifyRef.value.show();
}
}
/** 登录处理 */
async function handleLogin() {
// 校验租户
@@ -103,11 +130,16 @@ async function handleLogin() {
toast.warning("请输入验证码");
return;
}
await getCode();
}
/** 验证码验证成功回调 */
async function verifySuccess(params: any) {
loading.value = true;
try {
// 调用短信登录接口
const tokenStore = useTokenStore();
formData.captchaVerification = params.captchaVerification;
await tokenStore.login({
type: "sms",
...formData,

View File

@@ -29,10 +29,15 @@
</view>
<view v-if="captchaEnabled">
<Verify
ref="verifyRef" :captcha-type="captchaType" explain="向右滑动完成验证"
:img-size="{ width: '300px', height: '150px' }" mode="pop" @success="verifySuccess"
ref="verifyRef"
:captcha-type="captchaType"
explain="向右滑动完成验证"
:img-size="{ width: '300px', height: '150px' }"
mode="pop"
@success="verifySuccess"
/>
</view>
<!-- 登录按钮 -->
<view class="mb-2 mt-2 flex justify-between">
<text class="text-28rpx text-[#1890ff]" @click="goToSmsLogin">
@@ -86,7 +91,7 @@ import { useTokenStore } from '@/store/token'
import { ensureDecodeURIComponent, redirectAfterLogin } from '@/utils'
import Header from './components/header.vue'
import TenantPicker from './components/tenant-picker.vue'
import Verify from './components/Verifition/Verify.vue'
import { Verify } from '@/components/verifition';
defineOptions({
name: 'LoginPage',
@@ -149,7 +154,8 @@ async function handleLogin() {
}
await getCode()
}
async function verifySuccess(params) {
async function verifySuccess(params: any) {
loading.value = true
try {
// 调用登录接口

View File

@@ -48,6 +48,16 @@
no-border
/>
</view>
<view v-if="captchaEnabled">
<Verify
ref="verifyRef"
:captcha-type="captchaType"
explain="向右滑动完成验证"
:img-size="{ width: '300px', height: '150px' }"
mode="pop"
@success="verifySuccess"
/>
</view>
<!-- 用户协议 -->
<view class="mb-24rpx flex items-center">
@@ -89,6 +99,7 @@ import { useTokenStore } from "@/store/token";
import { redirectAfterLogin } from "@/utils";
import Header from "./components/header.vue";
import TenantPicker from "./components/tenant-picker.vue";
import { Verify } from '@/components/verifition';
defineOptions({
name: "RegisterPage",
@@ -104,14 +115,30 @@ const toast = useToast();
const loading = ref(false); // 加载状态
const agreePolicy = ref(false); // 用户协议勾选
const tenantPickerRef = ref<InstanceType<typeof TenantPicker>>(); // 租户选择器引用
const captchaEnabled = import.meta.env.VITE_APP_CAPTCHA_ENABLE === 'true'; // 验证码开关
const verifyRef = ref();
const captchaType = ref('blockPuzzle'); // 滑块验证码 blockPuzzle|clickWord
const formData = reactive({
username: "",
nickname: "",
password: "",
confirmPassword: "",
captchaVerification: "", // 验证码校验值
}); // 表单数据
/** 获取验证码 */
async function getCode() {
// 情况一,未开启:则直接注册
if (!captchaEnabled) {
await verifySuccess({});
} else {
// 情况二,已开启:则展示验证码;只有完成验证码的情况,才进行注册
// 弹出验证码
verifyRef.value.show();
}
}
/** 注册处理 */
async function handleRegister() {
if (!tenantPickerRef.value?.validate()) {
@@ -141,11 +168,16 @@ async function handleRegister() {
toast.warning("两次输入的密码不一致");
return;
}
await getCode();
}
/** 验证码验证成功回调 */
async function verifySuccess(params: any) {
loading.value = true;
try {
// 调用注册接口
const tokenStore = useTokenStore();
formData.captchaVerification = params.captchaVerification;
await tokenStore.login({
type: "register",
...formData,