Переглянути джерело

feat:优化验证码的代码,迁移到 components 目录下
feat:在 register.vue、code-login.vue 里,增加验证码

YunaiV 4 місяців тому
батько
коміт
39c9d18403

+ 1 - 1
env/.env

@@ -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 - 0
pnpm-lock.yaml

@@ -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: {}

+ 6 - 37
src/api/login.ts

@@ -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

+ 1 - 0
src/components/verifition/index.ts

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

+ 1 - 0
src/pages/auth/components/Verifition/utils/ase.ts

@@ -1,4 +1,5 @@
 import CryptoJS from 'crypto-js'
+
 /**
  * @word 要加密的内容
  * @keyWord String  服务器随机返回的关键字

+ 2 - 2
src/pages/auth/components/Verifition/Verify.vue

@@ -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: {

src/pages/auth/components/Verifition/Verify/VerifyPoints.vue → src/components/verifition/verify/verify-points.vue


src/pages/auth/components/Verifition/Verify/VerifySlide.vue → src/components/verifition/verify/verify-slide.vue


+ 1 - 1
src/http/http.ts

@@ -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)
           }

+ 1 - 0
src/http/types.ts

@@ -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'

+ 32 - 0
src/pages/auth/code-login.vue

@@ -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,

+ 10 - 4
src/pages/auth/login.vue

@@ -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 {
     // 调用登录接口

+ 32 - 0
src/pages/auth/register.vue

@@ -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,