- Remove extra spaces in CSS property declarations - Consolidate multi-line CSS rules into single lines - Maintain consistent formatting across component styles - Improve readability by removing unnecessary line breaks - Ensure uniform styling structure in scoped CSS blocks
175 lines
5.0 KiB
Vue
175 lines
5.0 KiB
Vue
<script setup lang="ts">
|
||
import { ref, computed } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import { User } from '@element-plus/icons-vue'
|
||
import { authApi } from '../../api/auth'
|
||
import { getOrCreateDeviceId } from '../../utils/deviceId'
|
||
import { splashApi } from '../../api/splash'
|
||
|
||
interface Props {
|
||
modelValue: boolean
|
||
}
|
||
|
||
interface Emits {
|
||
(e: 'update:modelValue', value: boolean): void
|
||
(e: 'loginSuccess', data: { token: string; permissions?: string; expireTime?: string; accountType?: string; deviceTrialExpired?: boolean }): void
|
||
(e: 'showRegister'): void
|
||
(e: 'deviceConflict', username: string): void
|
||
}
|
||
|
||
const props = defineProps<Props>()
|
||
const emit = defineEmits<Emits>()
|
||
|
||
const authForm = ref({ username: '', password: '' })
|
||
const authLoading = ref(false)
|
||
|
||
const visible = computed({
|
||
get: () => props.modelValue,
|
||
set: (value) => emit('update:modelValue', value)
|
||
})
|
||
|
||
async function handleAuth() {
|
||
if (!authForm.value.username || !authForm.value.password) return
|
||
|
||
authLoading.value = true
|
||
try {
|
||
// 获取或生成设备ID
|
||
const deviceId = await getOrCreateDeviceId()
|
||
|
||
// 登录
|
||
const loginRes: any = await authApi.login({
|
||
...authForm.value,
|
||
clientId: deviceId
|
||
})
|
||
|
||
// 保存开屏图片配置和品牌logo(不阻塞登录)
|
||
saveSplashConfigInBackground(authForm.value.username)
|
||
saveBrandLogoInBackground(authForm.value.username)
|
||
|
||
emit('loginSuccess', {
|
||
token: loginRes.data.accessToken || loginRes.data.token,
|
||
permissions: loginRes.data.permissions,
|
||
expireTime: loginRes.data.expireTime,
|
||
accountType: loginRes.data.accountType,
|
||
deviceTrialExpired: loginRes.data.deviceTrialExpired || false
|
||
})
|
||
ElMessage.success('登录成功')
|
||
resetForm()
|
||
} catch (err: any) {
|
||
// 设备冲突/数量达上限:触发设备管理
|
||
if (err.code === 501 ) {
|
||
emit('deviceConflict', authForm.value.username)
|
||
resetForm()
|
||
} else {
|
||
ElMessage.error(err.message || '登录失败')
|
||
}
|
||
} finally {
|
||
authLoading.value = false
|
||
}
|
||
}
|
||
|
||
function cancelAuth() {
|
||
visible.value = false
|
||
resetForm()
|
||
}
|
||
|
||
function resetForm() {
|
||
authForm.value = { username: '', password: '' }
|
||
}
|
||
|
||
function showRegister() {
|
||
emit('showRegister')
|
||
}
|
||
|
||
// 保存开屏图片配置
|
||
async function saveSplashConfigInBackground(username: string) {
|
||
try {
|
||
const res = await splashApi.getSplashImage(username)
|
||
const url = res?.data?.data?.url || res?.data?.url || ''
|
||
await (window as any).electronAPI.saveSplashConfig(username, url)
|
||
} catch (error) {
|
||
console.error('[开屏图片] 保存配置失败:', error)
|
||
}
|
||
}
|
||
|
||
// 保存品牌logo配置
|
||
async function saveBrandLogoInBackground(username: string) {
|
||
try {
|
||
const res = await splashApi.getBrandLogo(username)
|
||
const url = res?.data?.url || ''
|
||
// 保存到本地配置
|
||
await (window as any).electronAPI.saveBrandLogoConfig(username, url)
|
||
// 触发App.vue加载品牌logo
|
||
window.dispatchEvent(new CustomEvent('brandLogoChanged', { detail: url }))
|
||
} catch (error) {
|
||
console.error('[品牌logo] 加载配置失败:', error)
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<el-dialog
|
||
title=""
|
||
v-model="visible"
|
||
:close-on-click-modal="false"
|
||
width="360px"
|
||
center
|
||
class="auth-dialog">
|
||
<div style="padding: 20px 0;">
|
||
<div style="text-align: center; margin-bottom: 16px; color: #666;">
|
||
<img src="/icon/image.png" alt="logo" class="auth-logo" />
|
||
</div>
|
||
<div class="auth-title-wrap">
|
||
<h3 class="auth-title">账号登录</h3>
|
||
<p class="auth-subtitle">登录账户以获取完整服务体验</p>
|
||
</div>
|
||
|
||
<el-input
|
||
v-model="authForm.username"
|
||
placeholder="请输入用户名"
|
||
size="large"
|
||
style="margin-bottom: 15px;"
|
||
:disabled="authLoading"
|
||
@keyup.enter="handleAuth">
|
||
</el-input>
|
||
|
||
<el-input
|
||
v-model="authForm.password"
|
||
placeholder="请输入密码"
|
||
type="password"
|
||
size="large"
|
||
style="margin-bottom: 20px;"
|
||
:disabled="authLoading"
|
||
show-password
|
||
@keyup.enter="handleAuth">
|
||
</el-input>
|
||
|
||
<div>
|
||
<el-button
|
||
type="primary"
|
||
size="large"
|
||
:loading="authLoading"
|
||
:disabled="!authForm.username || !authForm.password || authLoading"
|
||
@click="handleAuth"
|
||
style="width: 100%;">
|
||
登录
|
||
</el-button>
|
||
</div>
|
||
|
||
<div style="margin-top: 20px; text-align: center;">
|
||
<el-button type="text" @click="showRegister" :disabled="authLoading">
|
||
还没有账号?点击注册
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.auth-logo {width: 160px; height: auto;}
|
||
.auth-dialog {--el-color-primary: #1677FF;}
|
||
.auth-dialog :deep(.el-button--primary) {background-color: #1677FF; border-color: #1677FF;}
|
||
.auth-title-wrap {margin-bottom: 12px;}
|
||
.auth-title {margin: 0; font-size: 18px; font-weight: 700; color: #1f1f1f; text-align: left;}
|
||
.auth-subtitle {margin: 6px 0 0; font-size: 12px; color: #8c8c8c; text-align: left;}
|
||
</style> |