添加账户渠道显示

This commit is contained in:
SunWuyuan 2025-10-07 14:45:09 +08:00
parent 934cdb7040
commit 2363bb3c32
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
4 changed files with 66 additions and 14 deletions

View File

@ -20,14 +20,16 @@
v-for="provider in providers"
:key="provider.id"
@click="handleLogin(provider)"
class="w-full flex items-center gap-3 px-4 py-3 border rounded-lg hover:bg-accent transition-colors"
:style="{ borderColor: provider.color + '20' }"
class="w-full flex items-center gap-3 px-4 py-3 border rounded-lg transition-colors hover:bg-accent"
:style="{
borderColor: (provider.color || '#666')
}"
>
<div class="w-10 h-10 flex items-center justify-center rounded-lg" :style="{ backgroundColor: provider.color + '10' }">
<component :is="getProviderIcon(provider.icon)" class="w-6 h-6" :style="{ color: provider.color }" />
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-muted">
<component :is="getProviderIcon(provider.icon)" class="w-6 h-6" />
</div>
<div class="flex-1 text-left">
<div class="font-medium">{{ provider.name }}</div>
<div class="font-medium">{{ provider.displayName || provider.name }}</div>
<div class="text-sm text-muted-foreground">{{ provider.description }}</div>
</div>
<ChevronRight class="w-5 h-5 text-muted-foreground" />
@ -96,7 +98,9 @@ const getProviderIcon = (icon) => {
const loadProviders = async () => {
try {
const response = await apiClient.getOAuthProviders()
providers.value = response.data || []
const list = response.data || []
// order
providers.value = list
} catch (error) {
console.error('Failed to load OAuth providers:', error)
toast.error('无法加载登录方式', {
@ -142,8 +146,11 @@ const handleLogin = (provider) => {
authWindow.close()
}
const display = event.data.providerName || event.data.provider
const color = event.data.providerColor
toast.success('登录成功', {
description: `已通过 ${event.data.provider} 登录`
description: `已通过 ${display} 登录`,
style: color ? { borderLeft: `4px solid ${color}` } : undefined
})
//
@ -180,11 +187,13 @@ const handleLogin = (provider) => {
// localStoragetoken
const token = localStorage.getItem('auth_token')
const authProvider = localStorage.getItem('auth_provider')
const authProvider = localStorage.getItem('auth_provider_name') || localStorage.getItem('auth_provider')
const providerColor = localStorage.getItem('auth_provider_color')
if (token) {
toast.success('登录成功', {
description: `已通过 ${authProvider} 登录`
description: `已通过 ${authProvider || '账户'} 登录`,
style: providerColor ? { borderLeft: `4px solid ${providerColor}` } : undefined
})
//
@ -211,7 +220,7 @@ const handleLogin = (provider) => {
description: '请重试'
})
}
}, 30000)
}, 300000)
}
onMounted(() => {

View File

@ -13,7 +13,7 @@ export function useOAuthCallback() {
const accountStore = useAccountStore()
const handleOAuthCallback = async () => {
const { token, provider, success, error } = route.query
const { token, provider, color, success, error } = route.query
// 检查是否是OAuth回调
if (!success && !error) {
@ -26,13 +26,14 @@ export function useOAuthCallback() {
// 保存token到localStorage
localStorage.setItem('auth_token', token)
localStorage.setItem('auth_provider', provider)
if (color) localStorage.setItem('auth_provider_color', color)
// 登录到store
await accountStore.login(token)
// 显示成功提示
toast.success('登录成功', {
description: `已通过 ${provider} 登录`
description: `已通过 ${provider} 登录`,
})
// 清除URL参数
@ -51,7 +52,7 @@ export function useOAuthCallback() {
window.opener.postMessage({
type: 'oauth_success',
token,
provider
provider,
}, window.location.origin)
// 延迟关闭窗口,确保消息已发送

View File

@ -418,9 +418,27 @@ onMounted(async () => {
>
<User v-else class="h-4 w-4" />
<span class="hidden sm:inline">{{ accountStore.userName }}</span>
<span v-if="accountStore.profile?.providerInfo"
class="hidden md:inline px-1.5 py-0.5 rounded text-[10px]"
:style="{
backgroundColor: (accountStore.profile.providerInfo.color || '#999') + '22',
color: accountStore.profile.providerInfo.color || 'inherit',
border: `1px solid ${(accountStore.profile.providerInfo.color || '#999')}55`
}"
>
{{ accountStore.profile.providerInfo.displayName }}
</span>
<ChevronDown class="h-3.5 w-3.5" :class="{ 'rotate-180': open }" />
</Button>
</template>
<DropdownItem @click="$router.push('/device-management')" :style="{
backgroundColor: (accountStore.profile.providerInfo.color || '#999') + '22',
color: accountStore.profile.providerInfo.color || 'inherit',
border: `1px solid ${(accountStore.profile.providerInfo.color || '#999')}55`
}">
<Layers class="h-4 w-4" />
账户渠道{{ accountStore.profile.providerInfo.displayName }}
</DropdownItem>
<DropdownItem @click="$router.push('/device-management')">
<Layers class="h-4 w-4" />
@ -447,6 +465,8 @@ onMounted(async () => {
</Button>
<Button
variant="outline"
size="icon"

View File

@ -8,11 +8,15 @@ export const useAccountStore = defineStore('account', () => {
const profile = ref(null)
const devices = ref([])
const loading = ref(false)
const providerName = ref(localStorage.getItem('auth_provider') || '')
const providerColor = ref(localStorage.getItem('auth_provider_color') || '')
// 计算属性
const isAuthenticated = computed(() => !!token.value)
const userName = computed(() => profile.value?.name || '')
const userAvatar = computed(() => profile.value?.avatarUrl || '')
const userProviderDisplay = computed(() => profile.value?.providerInfo?.displayName || profile.value?.providerInfo?.name || providerName.value || profile.value?.provider || '')
const userProviderColor = computed(() => profile.value?.providerInfo?.color || providerColor.value || '')
// 方法
const setToken = (newToken) => {
@ -22,6 +26,9 @@ export const useAccountStore = defineStore('account', () => {
} else {
localStorage.removeItem('auth_token')
localStorage.removeItem('auth_provider')
localStorage.removeItem('auth_provider_color')
providerName.value = ''
providerColor.value = ''
}
}
@ -32,6 +39,14 @@ export const useAccountStore = defineStore('account', () => {
try {
const response = await apiClient.getAccountProfile(token.value)
profile.value = response.data
// 若后端返回 providerInfo则回填前端展示字段
const p = profile.value?.providerInfo
if (p) {
providerName.value = p.displayName || p.name || profile.value?.provider || providerName.value
providerColor.value = p.color || providerColor.value
localStorage.setItem('auth_provider', providerName.value)
if (providerColor.value) localStorage.setItem('auth_provider_color', providerColor.value)
}
} catch (error) {
console.error('Failed to load profile:', error)
// Token可能无效清除
@ -86,6 +101,9 @@ export const useAccountStore = defineStore('account', () => {
devices.value = []
localStorage.removeItem('auth_token')
localStorage.removeItem('auth_provider')
localStorage.removeItem('auth_provider_color')
providerName.value = ''
providerColor.value = ''
}
// 初始化时加载用户信息
@ -100,10 +118,14 @@ export const useAccountStore = defineStore('account', () => {
profile,
devices,
loading,
providerName,
providerColor,
// 计算属性
isAuthenticated,
userName,
userAvatar,
userProviderDisplay,
userProviderColor,
// 方法
setToken,
loadProfile,