Files
Situation-Awareness-Platfor…/src/components/UserInfoCard/index.vue
2025-03-12 18:41:20 +08:00

171 lines
4.6 KiB
Vue

<template>
<div>
<d-skeleton :loading="profileLoading" :rows="4">
<div class="g-user-info-card" :style="{ width: `${width}px` }">
<GAvatar :src="avatarUrl" :name="name" :width="180" :height="180"></GAvatar>
<GLink v-if="isSelf" class="user-info-edit" :to="{ name: 'setting' }">
<Icon name="gt-edit" class="mr-2" /><span style="line-height: 1">编辑个人资料</span>
</GLink>
<slot name="action"></slot>
<div class="username">
<g-text>
{{ name }}
</g-text>
</div>
<div class="namespace">{{ namespace }}</div>
<section v-if="!isPrivate">
<div class="description">
<g-text :config="{ ellipse: true, line: 4, tooltip: false, showAll: true }">
{{ description }}
</g-text>
</div>
<div class="count-info">
<span>
<router-link :to="`/user/${namespace.replace('@', '')}/fans`"
><strong>{{ fansCount }}</strong> 粉丝</router-link
>
</span>
<span>
<router-link :to="`/user/${namespace.replace('@', '')}/following`"
><strong>{{ followCount }}</strong> 关注</router-link
></span
>
</div>
<div class="info-list">
<div class="flex gap-1 items-stretch" v-if="tenant">
<Icon name="gt-organizations" class="w-4" /><g-text class="flex-1">{{ tenant }}</g-text>
</div>
<div class="flex gap-1 items-stretch" v-if="location">
<Icon name="gt-location" class="w-4" /><g-text class="flex-1">{{ location }}</g-text>
</div>
<GLink class="flex items-stretch" :href="`mailto:${email}`" v-if="email">
<Icon name="gt-mail" class="mr-1 w-4" /><g-text class="flex-1">{{ email }}</g-text>
</GLink>
<GLink class="flex items-stretch" :href="`https://github.com/${github}`" target="_blank" v-if="github">
<Icon name="gt-github" class="mr-1 w-4" /><g-text class="flex-1">@{{ github }}</g-text>
</GLink>
<GLink class="flex items-stretch" :href="blog" target="_blank" v-if="blog">
<Icon name="gt-connect" class="mr-1 w-4" /><g-text class="flex-1">{{ blog }}</g-text>
</GLink>
</div>
</section>
</div>
</d-skeleton>
</div>
</template>
<script setup lang="ts">
import GText from '@/components/GText/index.vue';
interface User {
name: string;
namespace: string;
avatarUrl: string;
description: string;
fansCount: number;
followCount: number;
tenant?: string;
location?: string;
email?: string;
github?: string;
blog?: string;
width?: number;
isSelf?: boolean;
isPrivate?: boolean;
profileLoading?: boolean;
}
withDefaults(defineProps<User>(), {
fansCount: 0,
followCount: 0,
width: 260,
isSelf: true,
isPrivate: true,
profileLoading: true
});
</script>
<style lang="scss" scoped>
@import 'devui-theme/styles-var/devui-var.scss';
.g-user-info-card {
display: flex;
flex-direction: column;
background-color: transparent;
:deep(.devui-avatar) {
line-height: normal;
img {
// border: 4px solid $devui-global-bg;
border-radius: 50%;
object-fit: cover;
}
}
.username {
font-size: 22px;
font-weight: 500;
line-height: 32px;
color: var(--color-G900);
}
.namespace {
padding: 4px 0;
font-size: 14px;
line-height: 20px;
color: var(--color-CG600);
margin-bottom: 4px;
}
.description {
font-size: 14px;
color: var(--color-G900);
line-height: 20px;
margin-bottom: 4px;
}
.count-info {
display: flex;
justify-content: flex-start;
gap: 16px;
}
.user-info-edit {
width: 180px;
background-color: #ffffff;
margin: 8px 0 24px;
display: flex;
border-radius: var(--border-radius, 4px);
border: 1px solid var(--color-G300);
padding: 8px;
justify-content: center;
align-items: center;
font-size: 14px;
color: var(--black-60, #606060);
i {
margin-right: 8px;
}
&:hover {
color: var(--color-link);
:deep(.icon) {
color: var(--color-link) !important;
}
}
}
.info-list {
width: 100%;
margin: 24px 0;
display: flex;
flex-direction: column;
align-items: flex-start;
font-size: 14px;
color: var(--color-G900);
gap: 12px;
> div {
line-height: 1.15;
}
> a {
line-height: 1;
}
span {
line-height: 1;
}
:deep(.icon) {
vertical-align: middle;
}
}
}
</style>