Animo-Web/src/components/login/Login.vue
Grand-cocoa 846c8ce882 feat(auth): 实现用户登录和注册功能
- 新增登录和注册接口调用
- 添加通行密钥认证支持
- 实现登录表单和注册表单界面
- 添加状态管理和错误处理
- 更新环境变量配置和代理设置
- 优化登录流程动画和样式布局
2025-11-10 19:08:02 +08:00

110 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<t-form labelWidth="0">
<t-form-item>
<t-input v-model="username" placeholder="请输入用户名"></t-input>
</t-form-item>
<t-form-item>
<t-input v-model="password" placeholder="请输入密码"></t-input>
</t-form-item>
<t-space class="login-button-box" direction="vertical" size="small">
<t-button class="login-button" theme="primary" :loading="loading" @click="handleLogin"
>登录</t-button
>
<t-button
class="login-button"
theme="default"
:disabled="!passkey"
@click="handleUsePasskey"
>使用通行密钥</t-button
>
<t-link @click="handleRegister">没有账号?去注册</t-link>
</t-space>
</t-form>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, toRefs } from 'vue'
import { assertion, assertion_options, login } from '@/api/auth.ts'
const emits = defineEmits(['complete', 'register'])
const { username, password } = toRefs(
reactive({
username: '',
password: '',
}),
)
const loading = ref(false)
function handleLogin() {
loading.value = true
login({ user: username.value, password: password.value })
.then((x: any) => {
if (x.code === 200) {
emits('complete')
}
})
.catch((e: any) => {
console.error(e)
})
.finally(() => {
loading.value = false
})
}
const passkey = ref(true)
if (!navigator.credentials) {
passkey.value = false
}
function base64ToArrayBuffer(base64: string): ArrayBuffer {
// 处理base64url格式替换字符并添加填充
let normalizedBase64 = base64.replace(/-/g, '+').replace(/_/g, '/')
// 添加必要的填充
while (normalizedBase64.length % 4 !== 0) {
normalizedBase64 += '='
}
try {
const binaryString = atob(normalizedBase64)
const bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
return bytes.buffer
} catch (e) {
console.error('Base64 decoding failed:', e, 'Input was:', base64)
throw e
}
}
function handleUsePasskey() {
assertion_options().then((x: any) => {
const parse = JSON.parse(x.data)
parse.publicKey.challenge = base64ToArrayBuffer(parse.publicKey?.challenge)
console.log(parse)
navigator.credentials.get(parse).then((x: any) => {
assertion(x).then((x: any) => {
if (x.code === 200) {
emits('complete')
}
})
})
})
// emits('complete')
}
function handleRegister() {
emits('register')
}
</script>
<style scoped lang="scss">
.login-button-box {
width: 100%;
.login-button {
display: block;
width: 100%;
}
}
</style>