Files
timi-tdesign-pc/src/components/user-profile/index.vue
T
2026-08-28 15:19:08 +08:00

135 lines
2.6 KiB
Vue

<template>
<div class="tui-user-profile">
<template v-if="user">
<img
:class="getImageClass(user.profile.wrapperType)"
:src="wrapperUrl"
width="320"
alt="背景"
/>
<img
class="avatar"
:class="getImageClass(user.profile.avatarType)"
width="64"
height="64"
:src="avatarUrl"
alt="头像"
/>
<div class="info">
<div class="name">
<h3 class="value pink" v-text="user.name"></h3>
<user-level :value="toUserLevel(user.profile.exp).value" />
</div>
<template v-if="user.profile.sex">
<icon
v-if="user.profile.sex === 1"
class="sex boy"
name="BOY"
fill="var(--tui-blue)"
v-popup="`男生`"
/>
<icon
v-else
class="sex girl"
name="GIRL"
fill="var(--tui-pink)"
v-popup="`女生`"
/>
</template>
<p class="description" v-text="user.profile.description"></p>
</div>
</template>
</div>
</template>
<script lang="ts" setup>
import { Icon } from "timi-web";
import { toUserLevel } from "../user-level";
import { ImageType } from "./types";
import type {
ImageTypeKey,
UserImageResolver,
UserView
} from "./types";
defineOptions({
name: "UserProfile"
});
const props = withDefaults(defineProps<{
user?: UserView;
resolveAvatarUrl?: UserImageResolver;
resolveWrapperUrl?: UserImageResolver;
}>(), {
});
const { user } = toRefs(props);
const wrapperUrl = ref("");
const avatarUrl = ref("");
async function updateImageUrls(value?: UserView) {
const profile = value?.profile;
wrapperUrl.value = profile?.wrapperUrl || "";
avatarUrl.value = profile?.avatarUrl || "";
if (!profile) {
return;
}
if (props.resolveWrapperUrl) {
wrapperUrl.value = await props.resolveWrapperUrl(profile) || wrapperUrl.value;
}
if (props.resolveAvatarUrl) {
avatarUrl.value = await props.resolveAvatarUrl(profile) || avatarUrl.value;
}
}
watch(() => props.user, async value => await updateImageUrls(value), {
deep: true,
immediate: true
});
function getImageClass(type?: string) {
return type && type in ImageType ? ImageType[type as ImageTypeKey] : "";
}
</script>
<style lang="less" scoped>
.tui-user-profile {
width: 320px;
position: relative;
.avatar {
margin: -32px 0 0 16px;
border: 1px solid #CDDEF0;
position: absolute;
}
.info {
margin-top: 4px;
.name {
margin: 0 6px;
display: flex;
align-items: center;
line-height: 22px;
padding-left: 84px;
.value {
margin: 0 .5rem 0 0;
}
}
.sex {
width: 22px;
height: 22px;
}
.description {
padding: 0 16px;
margin-top: 20px;
}
}
}
</style>