feat: 添加vite的proxy代理设置
This commit is contained in:
6
components.d.ts
vendored
6
components.d.ts
vendored
@@ -25,8 +25,11 @@ declare module 'vue' {
|
|||||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||||
NGlobalStyle: typeof import('naive-ui')['NGlobalStyle']
|
NGlobalStyle: typeof import('naive-ui')['NGlobalStyle']
|
||||||
NInput: typeof import('naive-ui')['NInput']
|
NInput: typeof import('naive-ui')['NInput']
|
||||||
|
NInputOtp: typeof import('naive-ui')['NInputOtp']
|
||||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||||
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||||
|
NQrCode: typeof import('naive-ui')['NQrCode']
|
||||||
|
NSpace: typeof import('naive-ui')['NSpace']
|
||||||
NThemeEditor: typeof import('naive-ui')['NThemeEditor']
|
NThemeEditor: typeof import('naive-ui')['NThemeEditor']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
@@ -48,8 +51,11 @@ declare global {
|
|||||||
const NFormItem: typeof import('naive-ui')['NFormItem']
|
const NFormItem: typeof import('naive-ui')['NFormItem']
|
||||||
const NGlobalStyle: typeof import('naive-ui')['NGlobalStyle']
|
const NGlobalStyle: typeof import('naive-ui')['NGlobalStyle']
|
||||||
const NInput: typeof import('naive-ui')['NInput']
|
const NInput: typeof import('naive-ui')['NInput']
|
||||||
|
const NInputOtp: typeof import('naive-ui')['NInputOtp']
|
||||||
const NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
const NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||||
const NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
const NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||||
|
const NQrCode: typeof import('naive-ui')['NQrCode']
|
||||||
|
const NSpace: typeof import('naive-ui')['NSpace']
|
||||||
const NThemeEditor: typeof import('naive-ui')['NThemeEditor']
|
const NThemeEditor: typeof import('naive-ui')['NThemeEditor']
|
||||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
const RouterView: typeof import('vue-router')['RouterView']
|
const RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
@@ -15,12 +15,22 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
component: () => import('@/views/auth/login.vue')
|
component: () => import('@/views/auth/Login.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'register',
|
path: 'register',
|
||||||
name: 'Register',
|
name: 'Register',
|
||||||
component: () => import('@/views/auth/register.vue')
|
component: () => import('@/views/auth/Register.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'phone-login',
|
||||||
|
name: 'PhoneLogin',
|
||||||
|
component: () => import('@/views/auth/PhoneLogin.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'qrcode-login',
|
||||||
|
name: 'QRCodeLogin',
|
||||||
|
component: () => import('@/views/auth/QRCodeLogin.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/utils/useDebouncedRef.ts
Normal file
30
src/utils/useDebouncedRef.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { customRef } from 'vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建防抖的响应式引用
|
||||||
|
* @param value - 初始值
|
||||||
|
* @param delay - 防抖延迟时间(毫秒),默认 200ms
|
||||||
|
* @returns 防抖的响应式引用
|
||||||
|
*/
|
||||||
|
export function useDebouncedRef<T>(value: T, delay: number = 300) {
|
||||||
|
let timeout: ReturnType<typeof setTimeout> | null = null
|
||||||
|
|
||||||
|
return customRef((track, trigger) => {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
track()
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
set(newValue: T) {
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
value = newValue
|
||||||
|
trigger()
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -32,14 +32,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item>
|
<n-form-item>
|
||||||
<n-button :loading="loginLoading" style="width: 100%" type="primary" @click="userLoginFun"
|
<n-button :loading="loading" style="width: 100%" type="primary" @click="userLoginFun"
|
||||||
>登录</n-button
|
>登录
|
||||||
>
|
</n-button>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<div class="flex-center flex-1 gap-4">
|
||||||
|
<n-button class="flex-1" @click="router.push('/auth/phone-login')"> 手机登录 </n-button>
|
||||||
|
<n-button class="flex-1" @click="router.push('/auth/qrcode-login')"> 扫码登录 </n-button>
|
||||||
|
</div>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item>
|
<n-form-item>
|
||||||
<div class="flex-center flex-1">
|
<div class="flex-center flex-1">
|
||||||
<span>没有账号?</span>
|
<span>没有账号?</span>
|
||||||
<router-link to="/auth/register" style="color: #2080f0">注册</router-link>
|
<router-link to="/auth/register" style="color: #2080f0">创建账号</router-link>
|
||||||
</div>
|
</div>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
@@ -50,23 +56,26 @@
|
|||||||
import { reactive, ref, useTemplateRef } from 'vue'
|
import { reactive, ref, useTemplateRef } from 'vue'
|
||||||
import type { FormItemRule, FormRules, FormInst } from 'naive-ui'
|
import type { FormItemRule, FormRules, FormInst } from 'naive-ui'
|
||||||
import { useAccountStore } from '@/stores'
|
import { useAccountStore } from '@/stores'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
const accountStore = useAccountStore()
|
const accountStore = useAccountStore()
|
||||||
const formRef = useTemplateRef<FormInst>('formRef')
|
const formRef = useTemplateRef<FormInst>('formRef')
|
||||||
const loginModel = reactive({
|
const loginModel = reactive({
|
||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
const loginLoading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
const rules: FormRules = {
|
const rules: FormRules = {
|
||||||
username: [
|
username: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入登陆账号',
|
|
||||||
trigger: ['blur'],
|
trigger: ['blur'],
|
||||||
validator: (rule: FormItemRule, value: string) => {
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
if (value.length < 2) {
|
if (!value) {
|
||||||
|
return new Error('请输入登陆账号')
|
||||||
|
} else if (value.length < 2) {
|
||||||
return new Error('账号长度不能小于2位')
|
return new Error('账号长度不能小于2位')
|
||||||
} else if (value.length > 20) {
|
} else if (value.length > 20) {
|
||||||
return new Error('账号长度不能大于20位')
|
return new Error('账号长度不能大于20位')
|
||||||
@@ -80,11 +89,12 @@ const rules: FormRules = {
|
|||||||
password: [
|
password: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入登陆密码',
|
|
||||||
trigger: ['blur'],
|
trigger: ['blur'],
|
||||||
validator: (rule: FormItemRule, value: string) => {
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
if (value.length < 6) {
|
if (!value) {
|
||||||
return new Error('密码长度不能小于6位')
|
return new Error('请输入密码')
|
||||||
|
} else if (value.length < 8) {
|
||||||
|
return new Error('密码长度不能小于8位')
|
||||||
} else if (value.length > 20) {
|
} else if (value.length > 20) {
|
||||||
return new Error('密码长度不能大于20位')
|
return new Error('密码长度不能大于20位')
|
||||||
} else if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/.test(value)) {
|
} else if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/.test(value)) {
|
||||||
@@ -99,12 +109,12 @@ const rules: FormRules = {
|
|||||||
const userLoginFun = () => {
|
const userLoginFun = () => {
|
||||||
formRef.value?.validate((errors) => {
|
formRef.value?.validate((errors) => {
|
||||||
if (!errors) {
|
if (!errors) {
|
||||||
loginLoading.value = true
|
loading.value = true
|
||||||
console.log('登录成功')
|
console.log('登录成功')
|
||||||
// TODO 登录方法
|
// TODO 登录方法
|
||||||
accountStore.token = '123456'
|
accountStore.token = '123456'
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loginLoading.value = false
|
loading.value = false
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
123
src/views/auth/PhoneLogin.vue
Normal file
123
src/views/auth/PhoneLogin.vue
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex-col-center">
|
||||||
|
<div class="w-full">
|
||||||
|
<h2 class="text-3xl/9 mb-3 font-bold lg:text-4xl">欢迎回来 📲</h2>
|
||||||
|
<p>
|
||||||
|
<span style="color: #71717a">请输入手机号码登录账号以进入对战</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="loginModel"
|
||||||
|
:rules="rules"
|
||||||
|
:show-label="false"
|
||||||
|
class="w-full mt-10"
|
||||||
|
>
|
||||||
|
<n-form-item path="phoneNumber">
|
||||||
|
<n-input v-model:value="loginModel.phoneNumber" placeholder="手机号码" :maxlength="20" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item path="code">
|
||||||
|
<div class="flex flex-1 gap-4">
|
||||||
|
<n-input-otp
|
||||||
|
block
|
||||||
|
v-model:value="loginModel.code"
|
||||||
|
:allow-input="onlyAllowNumber"
|
||||||
|
style="gap: 0; flex: 2"
|
||||||
|
/>
|
||||||
|
<n-button style="flex: 1" @click="getPhoneCodeFun">获取验证码</n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<n-button :loading="loading" style="width: 100%" type="primary" @click="phoneLoginFun"
|
||||||
|
>登录
|
||||||
|
</n-button>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<div class="flex-center flex-1 gap-4">
|
||||||
|
<n-button class="flex-1" @click="router.push('/auth/login')"> 返回 </n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, useTemplateRef } from 'vue'
|
||||||
|
import type { FormItemRule, FormRules, FormInst } from 'naive-ui'
|
||||||
|
import { useAccountStore } from '@/stores'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
const formRef = useTemplateRef<FormInst>('formRef')
|
||||||
|
const loginModel = reactive({
|
||||||
|
phoneNumber: '',
|
||||||
|
code: []
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value)
|
||||||
|
const rules: FormRules = {
|
||||||
|
phoneNumber: [
|
||||||
|
{
|
||||||
|
key: 'phoneNumber',
|
||||||
|
required: true,
|
||||||
|
trigger: ['blur'],
|
||||||
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
|
if (!/^1[3-9]\d{9}$/.test(value)) {
|
||||||
|
return new Error('请输入手机号码')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
code: [
|
||||||
|
{
|
||||||
|
key: 'code',
|
||||||
|
required: true,
|
||||||
|
trigger: ['blur'],
|
||||||
|
validator: (_, value: string[] | null) => {
|
||||||
|
if (value === null) {
|
||||||
|
return new Error('请输入验证码')
|
||||||
|
}
|
||||||
|
if (value.filter(Boolean).length !== 6) {
|
||||||
|
return new Error('请输入验证码')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPhoneCodeFun = () => {
|
||||||
|
formRef.value?.validate(
|
||||||
|
(errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
console.log('获取验证码成功')
|
||||||
|
// TODO 获取验证码方法
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(rule) => {
|
||||||
|
if (rule.key === 'phoneNumber') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const phoneLoginFun = () => {
|
||||||
|
formRef.value?.validate((errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
loading.value = true
|
||||||
|
console.log('登录成功')
|
||||||
|
// TODO 登录方法
|
||||||
|
accountStore.token = '123456'
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
35
src/views/auth/QRCodeLogin.vue
Normal file
35
src/views/auth/QRCodeLogin.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex-col-center">
|
||||||
|
<div class="w-full">
|
||||||
|
<h2 class="text-3xl/9 mb-3 font-bold lg:text-4xl">欢迎回来 📱</h2>
|
||||||
|
<p>
|
||||||
|
<span style="color: #71717a">请用手机扫描二维码登录</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<n-form :show-label="false" class="w-full mt-10">
|
||||||
|
<n-form-item>
|
||||||
|
<n-space vertical style="align-items: center; flex: 1">
|
||||||
|
<n-qr-code v-model:value="qrcode" :size="180" />
|
||||||
|
<p>扫码后点击 '确认',即可完成登录</p>
|
||||||
|
</n-space>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<div class="flex-center flex-1 gap-4">
|
||||||
|
<n-button class="flex-1" @click="router.push('/auth/login')"> 返回 </n-button>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useAccountStore } from '@/stores'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
const qrcode = ref('')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
214
src/views/auth/Register.vue
Normal file
214
src/views/auth/Register.vue
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex-col-center">
|
||||||
|
<div class="w-full">
|
||||||
|
<h2 class="text-3xl/9 mb-3 font-bold lg:text-4xl">创建一个账号 🚀</h2>
|
||||||
|
<p>
|
||||||
|
<span style="color: #71717a">创建账号进入对战</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="registerModel"
|
||||||
|
:rules="rules"
|
||||||
|
:show-label="false"
|
||||||
|
class="w-full mt-10"
|
||||||
|
>
|
||||||
|
<n-form-item path="username">
|
||||||
|
<n-input v-model:value="registerModel.username" placeholder="请输入账号" :maxlength="20" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item path="password">
|
||||||
|
<div class="flex flex-col flex-1">
|
||||||
|
<n-input
|
||||||
|
v-model:value="registerModel.password"
|
||||||
|
type="password"
|
||||||
|
show-password-on="mousedown"
|
||||||
|
placeholder="密码"
|
||||||
|
:maxlength="20"
|
||||||
|
/>
|
||||||
|
<div class="flex flex-1 gap-1 mt-2">
|
||||||
|
<div class="flex-1 h-2 rounded-xl relative bg-gray-200 overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="securityLevel > 0 ? 'w-full' : 'w-0'"
|
||||||
|
class="absolute left-0 top-0 h-full bg-red-500 transition-all duration-500"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 h-2 rounded-xl relative bg-gray-200 overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="securityLevel > 1 ? 'w-full' : 'w-0'"
|
||||||
|
class="absolute left-0 top-0 h-full bg-red-500 transition-all duration-500"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 h-2 rounded-xl relative bg-gray-200 overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="securityLevel > 2 ? 'w-full' : 'w-0'"
|
||||||
|
class="absolute left-0 top-0 h-full bg-red-500 transition-all duration-500"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 h-2 rounded-xl relative bg-gray-200 overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="securityLevel > 3 ? 'w-full' : 'w-0'"
|
||||||
|
class="absolute left-0 top-0 h-full bg-red-500 transition-all duration-500"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 h-2 rounded-xl relative bg-gray-200 overflow-hidden">
|
||||||
|
<div
|
||||||
|
:class="securityLevel > 4 ? 'w-full' : 'w-0'"
|
||||||
|
class="absolute left-0 top-0 h-full bg-red-500 transition-all duration-500"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs mt-2" style="color: #71717a">
|
||||||
|
使用 8 个或更多字符,混合大小写字母、数字
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item path="confirmPassword">
|
||||||
|
<n-input
|
||||||
|
v-model:value="registerModel.confirmPassword"
|
||||||
|
type="password"
|
||||||
|
show-password-on="mousedown"
|
||||||
|
placeholder="确认密码"
|
||||||
|
:maxlength="20"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item path="agreement">
|
||||||
|
<div class="flex flex-1">
|
||||||
|
<n-checkbox v-model:checked="registerModel.agreement">我同意</n-checkbox>
|
||||||
|
<a href="javascript:void(0)" style="color: #2080f0">隐私政策 & 条款</a>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<n-button :loading="loading" style="width: 100%" type="primary" @click="userRegisterFun"
|
||||||
|
>登录
|
||||||
|
</n-button>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item>
|
||||||
|
<div class="flex-center flex-1">
|
||||||
|
<span>已经有账号了?</span>
|
||||||
|
<router-link to="/auth/login" style="color: #2080f0">去登录</router-link>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, useTemplateRef, watch } from 'vue'
|
||||||
|
import { type FormInst, type FormItemRule, type FormRules } from 'naive-ui'
|
||||||
|
|
||||||
|
const formRef = useTemplateRef<FormInst>('formRef')
|
||||||
|
const registerModel = reactive({
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
agreement: false
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
const securityLevel = ref(0)
|
||||||
|
watch(
|
||||||
|
() => registerModel.password,
|
||||||
|
(value) => {
|
||||||
|
checkPasswordStrength(value)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const checkPasswordStrength = (password: string) => {
|
||||||
|
let strength = 0
|
||||||
|
if (password.length >= 8) {
|
||||||
|
strength++
|
||||||
|
}
|
||||||
|
if (/[a-z]/.test(password)) {
|
||||||
|
strength++
|
||||||
|
}
|
||||||
|
if (/[A-Z]/.test(password)) {
|
||||||
|
strength++
|
||||||
|
}
|
||||||
|
if (/[0-9]/.test(password)) {
|
||||||
|
strength++
|
||||||
|
}
|
||||||
|
strength = Math.min(strength, 5)
|
||||||
|
securityLevel.value = strength
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
username: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
trigger: ['blur'],
|
||||||
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
return new Error('请输入登陆账号')
|
||||||
|
} else if (value.length < 2) {
|
||||||
|
return new Error('账号长度不能小于2位')
|
||||||
|
} else if (value.length > 20) {
|
||||||
|
return new Error('账号长度不能大于20位')
|
||||||
|
} else if (!/^[A-Za-z][A-Za-z0-9]*$/.test(value)) {
|
||||||
|
return new Error('账号以字母开头,只能包含字母和数字')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
trigger: ['blur'],
|
||||||
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
return new Error('请输入密码')
|
||||||
|
} else if (value.length < 8) {
|
||||||
|
return new Error('密码长度不能小于8位')
|
||||||
|
} else if (value.length > 20) {
|
||||||
|
return new Error('密码长度不能大于20位')
|
||||||
|
} else if (!/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/.test(value)) {
|
||||||
|
return new Error('密码必须包含大小写字母和数字')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
confirmPassword: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
trigger: ['blur'],
|
||||||
|
validator: (rule: FormItemRule, value: string) => {
|
||||||
|
if (!value) {
|
||||||
|
return new Error('请再次输入密码')
|
||||||
|
}
|
||||||
|
if (registerModel.password !== value) {
|
||||||
|
return new Error('密码不一致')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
agreement: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
trigger: 'change',
|
||||||
|
validator: (rule: FormItemRule, value: boolean) => {
|
||||||
|
console.log(value)
|
||||||
|
if (!value) {
|
||||||
|
return new Error('请勾选同意协议')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const userRegisterFun = () => {
|
||||||
|
formRef.value?.validate((errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
loading.value = true
|
||||||
|
console.log('注册成功')
|
||||||
|
// TODO 注册方法
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<template>$END$</template>
|
|
||||||
|
|
||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
Reference in New Issue
Block a user