<script setup lang="ts">
|
import { onMounted, reactive, ref } from 'vue'
|
import { useRoute, useRouter } from 'vue-router'
|
import cityImage from '../assets/login-city-aerial.jpg'
|
import { loginAdmin } from '../api/auth'
|
import { useAppStore } from '../stores/app'
|
|
const rememberedCredentialsKey = 'talent-card-admin-remembered-credentials'
|
|
function rememberedCredentials() {
|
try {
|
return JSON.parse(localStorage.getItem(rememberedCredentialsKey) || '{}') as { account?: string; password?: string }
|
} catch {
|
return {}
|
}
|
}
|
|
const router = useRouter()
|
const route = useRoute()
|
const appStore = useAppStore()
|
const submitting = ref(false)
|
const storedCredentials = rememberedCredentials()
|
const form = reactive({
|
account: storedCredentials.account || '',
|
password: storedCredentials.password || '',
|
remember: Boolean(storedCredentials.account && storedCredentials.password),
|
})
|
const errors = reactive({ account: '', password: '' })
|
|
// Visiting /login is also the supported account-switch flow. Remove the
|
// previous browser session before rendering the form so requests cannot keep
|
// using the old administrator while the new credentials are being entered.
|
onMounted(() => {
|
if (appStore.isLoggedIn) appStore.logout()
|
})
|
|
function clearError(field: 'account' | 'password') {
|
if (errors[field]) errors[field] = ''
|
}
|
|
async function submit() {
|
const account = form.account.trim()
|
errors.account = account ? '' : '请输入账号'
|
errors.password = form.password ? '' : '请输入密码'
|
if (errors.account || errors.password) return
|
submitting.value = true
|
try {
|
const result = await loginAdmin(account, form.password)
|
if (form.remember) {
|
localStorage.setItem(rememberedCredentialsKey, JSON.stringify({ account, password: form.password }))
|
} else {
|
localStorage.removeItem(rememberedCredentialsKey)
|
}
|
appStore.login(
|
result.accessToken,
|
{ name: result.operator.name, role: result.operator.roleCode === 'platform_admin' ? '平台管理' : result.operator.roleCode, permissionCodes: result.operator.permissionCodes || [] },
|
form.remember,
|
)
|
await router.replace(String(route.query.redirect || '/dashboard'))
|
} finally {
|
submitting.value = false
|
}
|
}
|
</script>
|
|
<template>
|
<main class="login-page">
|
<div class="login-city" aria-hidden="true"><img :src="cityImage" alt="" /></div>
|
<section class="login-content">
|
<h1>攀枝花市东区人才服务平台</h1>
|
<el-form class="login-form" :model="form" @submit.prevent="submit">
|
<h2>登录</h2>
|
<label class="login-field">
|
<span>账号 <em v-if="errors.account">{{ errors.account }}</em></span>
|
<el-input
|
v-model="form.account"
|
:class="{ 'is-error': errors.account }"
|
maxlength="32"
|
autocomplete="username"
|
placeholder="请输入"
|
@input="clearError('account')"
|
@keyup.enter="submit"
|
/>
|
</label>
|
<label class="login-field">
|
<span>密码 <em v-if="errors.password">{{ errors.password }}</em></span>
|
<el-input
|
v-model="form.password"
|
:class="{ 'is-error': errors.password }"
|
type="password"
|
maxlength="64"
|
autocomplete="current-password"
|
placeholder="请输入"
|
show-password
|
@input="clearError('password')"
|
@keyup.enter="submit"
|
/>
|
</label>
|
<el-checkbox v-model="form.remember" class="remember-check">记住我</el-checkbox>
|
<el-button type="primary" native-type="submit" class="login-button" :loading="submitting">登录</el-button>
|
</el-form>
|
</section>
|
</main>
|
</template>
|