182 lines
4.6 KiB
Vue
182 lines
4.6 KiB
Vue
<template>
|
|
<div class="g-user-item" :class="{ 'is-last': isLast, 'is-first': isFirst }">
|
|
<div class="g-user-item-avatar flex items-center">
|
|
<slot name="avatar">
|
|
<a :href="`/${data.username}`" target="_blank">
|
|
<GAvatar
|
|
:src="data.avatar"
|
|
:name="data.nickname"
|
|
:is_round="data.round"
|
|
/>
|
|
</a>
|
|
</slot>
|
|
</div>
|
|
<div class="g-user-item-info">
|
|
<div class="g-user-item-title">
|
|
<slot name="title" :data="data">
|
|
<a :href="`/${data.username}`" target="_blank">
|
|
<span class="g-user-item-name" v-html="highlightWords(keywords,data.nickname)"></span>
|
|
</a>
|
|
<span class="g-user-item-username" v-html="highlightWords(keywords,`@${data.username}`)"></span>
|
|
</slot>
|
|
</div>
|
|
<div class="g-user-item-description">
|
|
<slot name="description" :data="data">
|
|
<g-text :config="{ ellipse: true, line: 2, tooltip: true }">
|
|
{{ data.description || '-' }}
|
|
</g-text>
|
|
</slot>
|
|
</div>
|
|
<div class="g-user-item-others">
|
|
<slot name="others" :data="data">
|
|
<div v-if="data.org" class="g-user-item-icon-text">
|
|
<Icon name="gt-organizations" size="16px" />
|
|
<a :href="data.website" target="_blank">
|
|
<span class="g-user-item-text">@<g-text style="max-width: 200px">{{ data.org }}</g-text></span>
|
|
</a>
|
|
</div>
|
|
<div class="g-user-item-icon-text" v-if="data.location">
|
|
<Icon name="gt-location" size="16px" color="#9FA7B3" />
|
|
<span class="g-user-item-text"><g-text style="max-width: 200px">{{ data.location || '未知' }}</g-text></span>
|
|
</div>
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
<div v-if="showButton" class="g-user-item-actions">
|
|
<slot name="action">
|
|
<d-button
|
|
v-if="data.hasStarred"
|
|
color="secondary"
|
|
:loading="loading"
|
|
class="g-user-item-action"
|
|
@click="emits('starred', false)"
|
|
>
|
|
取消关注
|
|
</d-button>
|
|
<d-button v-else :loading="loading" color="secondary" class="g-user-item-action" @click="emits('starred', true)">关注</d-button>
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
export default {
|
|
name: 'user-item'
|
|
};
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import { highlightWords } from '@/utils';
|
|
type FollowUserData = {
|
|
id: string;
|
|
avatar?: string;
|
|
nickname?: string;
|
|
username: string;
|
|
description?: string;
|
|
location?: string;
|
|
org?: string;
|
|
round?: boolean;
|
|
loading?: boolean;
|
|
hasStarred?: boolean;
|
|
website?: string;
|
|
}
|
|
|
|
withDefaults(defineProps<{
|
|
data: FollowUserData;
|
|
loading?: boolean;
|
|
showButton?: boolean;
|
|
isFirst?: boolean;
|
|
isLast?: boolean;
|
|
keywords?: string
|
|
}>(), {
|
|
data: () => ({
|
|
id: '',
|
|
location: '-',
|
|
round: false,
|
|
nickname: '',
|
|
username: '',
|
|
hasStarred: false
|
|
}),
|
|
loading: false,
|
|
showButton: true,
|
|
isFirst: false,
|
|
isLast: false,
|
|
keywords: ''
|
|
});
|
|
|
|
const emits = defineEmits<{(e: 'starred', data: boolean): void
|
|
}>();
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
$g-user-item-color: var(--color-G900);
|
|
$g-user-item-color-second: var(--color-G700);
|
|
$g-user-item-color-third: #606060;
|
|
$g-user-item-border-color: var(--color-G200);
|
|
$g-user-item-border-radius: 4px;
|
|
.g-user-item {
|
|
display: flex;
|
|
border-bottom: 1px solid $g-user-item-border-color;
|
|
padding: 16px 20px;
|
|
// border-bottom: none;
|
|
&.is-first {
|
|
border-top-left-radius: $g-user-item-border-radius;
|
|
border-top-right-radius: $g-user-item-border-radius;
|
|
}
|
|
&.is-last {
|
|
border-bottom-left-radius: $g-user-item-border-radius;
|
|
border-bottom-right-radius: $g-user-item-border-radius;
|
|
border-bottom: none;
|
|
}
|
|
&-info {
|
|
padding: 0 24px;
|
|
flex: 1;
|
|
}
|
|
&-title {
|
|
margin-bottom: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
line-height: 1;
|
|
}
|
|
&-name {
|
|
color: $g-user-item-color;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
line-height: 20px;
|
|
margin-right: 8px;
|
|
}
|
|
&-username {
|
|
color: $g-user-item-color-second;
|
|
font-size: 14px;
|
|
line-height: 20px;
|
|
}
|
|
&-description {
|
|
color: $g-user-item-color-second;
|
|
font-size: 14px;
|
|
margin-bottom: 8px;
|
|
line-height: 20px;
|
|
}
|
|
&-others {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
&-icon-text {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-right: 24px;
|
|
line-height: 1;
|
|
}
|
|
&-text {
|
|
margin-left: 8px;
|
|
color: $g-user-item-color-second;
|
|
font-size: 14px;
|
|
line-height: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
&-action {
|
|
padding: 6px 12px;
|
|
}
|
|
}
|
|
</style>
|