瀏覽代碼

feat: 增加图形验证

lixuan 1 周之前
父節點
當前提交
eca1f3407b

+ 12 - 3
apps/web-velofex/src/api/core/auth.ts

@@ -3,8 +3,10 @@ import { baseRequestClient, requestClient } from '#/api/request';
 export namespace AuthApi {
   /** 登录接口参数 */
   export interface LoginParams {
-    password?: string;
-    username?: string;
+    account?: string;
+    pwd?: string;
+    check_code?: string;
+    check_key?: string;
   }
 
   /** 登录接口返回值 */
@@ -16,13 +18,20 @@ export namespace AuthApi {
     data: string;
     status: number;
   }
+
+  export interface CaptchaUrlResult {
+    w: number;
+    h: number;
+    len: string;
+    key: string;
+  }
 }
 
 /**
  * 登录
  */
 export async function loginApi(data: AuthApi.LoginParams) {
-  return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
+  return requestClient.post<AuthApi.LoginResult>('/api/account/doLogin', data);
 }
 
 /**

+ 78 - 0
apps/web-velofex/src/components/login/CaptchaInput.vue

@@ -0,0 +1,78 @@
+<script setup lang="ts">
+import { onMounted, ref, watch } from 'vue';
+
+interface Props {
+  modelValue?: string;
+  placeholder?: string;
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: '',
+  placeholder: '请输入验证码',
+});
+
+const emit = defineEmits(['update:modelValue', 'refresh']);
+
+const captchaValue = ref(props.modelValue);
+const captchaUrl = ref('');
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    captchaValue.value = val;
+  },
+);
+
+watch(captchaValue, (val) => {
+  emit('update:modelValue', val);
+});
+
+function handleRefresh() {
+  const random = randomString(16);
+  captchaUrl.value = `/File/ImageCheckCode?w=130&h=40&len=4&key=${random}`;
+}
+
+function handleInput(e: Event) {
+  const target = e.target as HTMLInputElement;
+  captchaValue.value = target.value;
+}
+
+function randomString(length: number): string {
+  let result = '';
+  const characters =
+    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+  const charactersLength = characters.length;
+  for (let i = 0; i < length; i++) {
+    result += characters.charAt(Math.floor(Math.random() * charactersLength));
+  }
+  return result;
+}
+
+onMounted(() => {
+  handleRefresh();
+});
+</script>
+
+<template>
+  <div class="flex items-center gap-2">
+    <input
+      :placeholder="placeholder"
+      :value="captchaValue"
+      class="h-[38px] flex-1 rounded-md border border-gray-300 px-3 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-[#8B0046]"
+      type="text"
+      @input="handleInput"
+    />
+    <div
+      class="flex h-[38px] w-[120px] cursor-pointer items-center justify-center overflow-hidden rounded-md border border-gray-300 bg-gray-100"
+      @click="handleRefresh"
+    >
+      <img
+        v-if="captchaUrl"
+        :src="captchaUrl"
+        alt="验证码"
+        class="h-full w-full object-contain"
+      />
+      <span v-else class="text-xs text-gray-500">点击刷新</span>
+    </div>
+  </div>
+</template>

+ 17 - 1
apps/web-velofex/src/components/login/login.vue

@@ -5,6 +5,8 @@ import { computed, reactive, ref, watch } from 'vue';
 
 import { useVbenForm, useVbenModal, VbenButton, z } from '@vben/common-ui';
 
+import CaptchaInput from './CaptchaInput.vue';
+
 defineOptions({
   name: 'LoginComponent',
 });
@@ -39,6 +41,16 @@ const formSchema = computed((): VbenFormSchema[] => {
       label: 'Password',
       rules: z.string().min(1, { message: '请输入密码' }),
     },
+    {
+      component: 'VbenInput',
+      componentProps: {
+        placeholder: '',
+      },
+      fieldName: 'captcha',
+      label: 'Verification Code',
+      rules: z.string().min(1, { message: '请输入验证码' }),
+      formItemClass: 'captcha-form-item',
+    },
   ];
 });
 
@@ -129,7 +141,11 @@ defineExpose({
 
           <div class="my-[20px] h-[1px] w-auto bg-[#E5E5E5]"></div>
 
-          <Form />
+          <Form>
+            <template #captcha="{ field }">
+              <CaptchaInput v-model="field.value" />
+            </template>
+          </Form>
 
           <!-- showRememberMe || showForgetPassword -->
           <div v-if="false" class="mb-6 flex justify-between">

+ 6 - 2
apps/web-velofex/vite.config.mts

@@ -14,8 +14,12 @@ export default defineConfig(async () => {
           '/api': {
             changeOrigin: true,
             rewrite: (path) => path.replace(/^\/api/, ''),
-            // mock代理目标地址
-            target: 'http://localhost:5320/api',
+            target: 'http://a.dev.jbpm.shalu.com/',
+            ws: true,
+          },
+          '/File': {
+            changeOrigin: true,
+            target: 'http://a.dev.jbpm.shalu.com/',
             ws: true,
           },
         },