135 lines
2.6 KiB
Vue
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>
|