feat: 新增个人中心页面

This commit is contained in:
xlsea
2025-04-28 23:52:26 +08:00
parent d751c14f7b
commit 423a8c031f
22 changed files with 920 additions and 20 deletions

View File

@ -0,0 +1,117 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useLoading } from '@sa/hooks';
import { fetchSocialAuthBinding, fetchSocialAuthUnbinding, fetchSocialList } from '@/service/api/system';
import { useAuthStore } from '@/store/modules/auth';
defineOptions({
name: 'SocialCard'
});
const authStore = useAuthStore();
const { userInfo } = authStore;
const socialList = ref<Api.System.Social[]>([]);
const { loading, startLoading, endLoading } = useLoading();
const { loading: btnLoading, startLoading: startBtnLoading, endLoading: endBtnLoading } = useLoading();
/** 获取SSO账户列表 */
async function getSsoUserList() {
startLoading();
const { data, error } = await fetchSocialList();
if (!error) {
socialList.value = data || [];
}
endLoading();
}
/** 绑定SSO账户 */
async function bindSsoAccount(type: Api.System.SocialSource) {
const { data, error } = await fetchSocialAuthBinding(type, userInfo.user?.tenantId);
if (!error) {
window.location.href = data;
}
}
/** 解绑SSO账户 */
async function unbindSsoAccount(socialId: string) {
startBtnLoading();
const { error } = await fetchSocialAuthUnbinding(socialId);
if (!error) {
window.$message?.success('账户解绑成功');
await getSsoUserList();
}
endBtnLoading();
}
const socialSources = [
{ key: 'wechat_open', icon: 'ic:outline-wechat', color: '#44b549', name: '微信' },
{ key: 'topiam', localIcon: 'topiam', color: '', name: 'TopIAM' },
{ key: 'maxkey', localIcon: 'maxkey', color: '', name: 'MaxKey' },
{ key: 'gitee', icon: 'simple-icons:gitee', color: '#c71d23', name: 'Gitee' },
{ key: 'github', icon: 'mdi:github', color: '#010409', name: 'GitHub' }
];
getSsoUserList();
</script>
<template>
<NSpin :show="loading" class="mt-16px">
<div class="grid grid-cols-1 gap-16px 2xl:grid-cols-3 xl:grid-cols-2">
<div v-for="source in socialSources" :key="source.key" class="relative">
<NCard
class="h-full transition-all duration-300 hover:shadow-md"
:class="[socialList.some(s => s.source === source.key) ? 'border-primary' : 'border-transparent']"
:bordered="true"
>
<template v-if="socialList.some(s => s.source === source.key)">
<div class="flex flex-col items-center gap-16px">
<NAvatar
round
size="large"
:src="socialList.find(s => s.source === source.key)?.avatar"
class="size-80px"
/>
<div class="text-center">
<div class="text-16px font-medium">
{{ socialList.find(s => s.source === source.key)?.nickName }}
</div>
<div class="mt-4px text-12px text-gray-500">
绑定时间{{ socialList.find(s => s.source === source.key)?.createTime }}
</div>
</div>
<NButton
type="error"
size="small"
:loading="btnLoading"
@click="unbindSsoAccount(socialList.find(s => s.source === source.key)?.authId || '')"
>
解绑
</NButton>
</div>
</template>
<template v-else>
<div class="h-full flex flex-col items-center justify-center gap-16px">
<SvgIcon
:local-icon="source.localIcon"
:icon="source.icon"
class="size-48px"
:style="{ color: source.color }"
/>
<div class="text-16px font-medium">{{ source.name }}</div>
<NButton type="primary" size="small" @click="bindSsoAccount(source.key as Api.System.SocialSource)">
绑定
</NButton>
</div>
</template>
</NCard>
</div>
</div>
</NSpin>
</template>
<style scoped>
.border-primary {
border-color: var(--primary-color);
}
</style>