feat: 双token

This commit is contained in:
2026-06-16 16:16:47 +08:00
parent d9b8567b6d
commit 172c83ea73
8 changed files with 455 additions and 79 deletions

View File

@@ -27,7 +27,7 @@
</n-form-item>
<n-form-item>
<div class="flex flex-1 items-center justify-between">
<n-checkbox>记住账号</n-checkbox>
<n-checkbox v-model:checked="rememberAccount">记住账号</n-checkbox>
<a href="javascript:void(0)" style="color: #2080f0">忘记密码</a>
</div>
</n-form-item>
@@ -53,26 +53,43 @@
</template>
<script setup lang="ts">
import { reactive, ref, useTemplateRef } from 'vue'
import { reactive, ref, useTemplateRef, onMounted } from 'vue'
import type { FormItemRule, FormRules, FormInst } from 'naive-ui'
import { useMessage } from 'naive-ui'
import { useAccountStore } from '@/stores'
import { useRouter } from 'vue-router'
import { useRouter, useRoute } from 'vue-router'
/** 记住账号的 localStorage key */
const REMEMBER_KEY = 'login_remembered_username'
const router = useRouter()
const route = useRoute()
const accountStore = useAccountStore()
const message = useMessage()
const formRef = useTemplateRef<FormInst>('formRef')
const loginModel = reactive({
username: '',
password: ''
})
const loading = ref(false)
/** 是否记住账号 */
const rememberAccount = ref(false)
/** 页面初始化时恢复已记住的账号 */
onMounted(() => {
const savedUsername = localStorage.getItem(REMEMBER_KEY)
if (savedUsername) {
loginModel.username = savedUsername
rememberAccount.value = true
}
})
const rules: FormRules = {
username: [
{
required: true,
trigger: ['blur'],
validator: (rule: FormItemRule, value: string) => {
validator: (_rule: FormItemRule, value: string) => {
if (!value) {
return new Error('请输入登陆账号')
} else if (value.length < 2) {
@@ -90,7 +107,7 @@ const rules: FormRules = {
{
required: true,
trigger: ['blur'],
validator: (rule: FormItemRule, value: string) => {
validator: (_rule: FormItemRule, value: string) => {
if (!value) {
return new Error('请输入密码')
} else if (value.length < 8) {
@@ -106,16 +123,55 @@ const rules: FormRules = {
]
}
/**
* 获取友好的错误提示信息
* @param error - 捕获的错误对象
* @returns 用户可读的错误文本
*/
function getErrorMessage(error: unknown): string {
if (error instanceof Error) {
// 网络错误
if (error.message?.includes('Network Error') || error.message?.includes('网络')) {
return '网络连接失败,请检查网络后重试'
}
return error.message
}
if (typeof error === 'object' && error !== null) {
const err = error as Record<string, unknown>
if (typeof err.message === 'string' && err.message) {
return err.message
}
}
return '登录失败,请稍后重试'
}
/** 用户登录 */
const userLoginFun = () => {
formRef.value?.validate((errors) => {
if (!errors) {
loading.value = true
console.log('登录成功')
// TODO 登录方法
accountStore.token = '123456'
setTimeout(() => {
loading.value = false
}, 1000)
formRef.value?.validate(async (errors) => {
if (errors) return
loading.value = true
try {
await accountStore.login({
username: loginModel.username,
password: loginModel.password
})
// 记住账号:将用户名存入 localStorage
if (rememberAccount.value) {
localStorage.setItem(REMEMBER_KEY, loginModel.username)
} else {
localStorage.removeItem(REMEMBER_KEY)
}
message.success('登录成功')
// 跳转到目标页面(有 redirect 参数则优先跳回原页面,否则去首页)
const redirectPath = (route.query.redirect as string) || '/'
router.push(redirectPath)
} catch (error: unknown) {
message.error(getErrorMessage(error))
} finally {
loading.value = false
}
})
}