搜索结果列表页面开发
This commit is contained in:
25
src/components/UserItem/README.md
Normal file
25
src/components/UserItem/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|-------------|-------------------|----------------|-------------------------------- |-------|
|
||||
| data | 用户信息数据 | FollowUserData | — | {} |
|
||||
| loading? | 该数据是否在处理中 | boolean | — | false |
|
||||
| showButton? | 是否显示操作按钮 | boolean | — | true |
|
||||
| isFirst? | 是否为第一条数据(用于控制样式) | boolean | — | false |
|
||||
| isLast? | 是否为最后一条数据(用于控制样式) | boolean | — | false |
|
||||
|
||||
### Emits
|
||||
|
||||
| 方法 | 说明 | 返回值 |
|
||||
|-----------|---------|---------------|
|
||||
| starred | 关注/取消关注 | data: boolean |
|
||||
|
||||
### Slots
|
||||
|
||||
| 名称 | 说明 |
|
||||
|-------------|--------------|
|
||||
| avatar | 组件头像区域插槽 |
|
||||
| title | 组件标题区域插槽 |
|
||||
| description | 组件描述区域插槽 |
|
||||
| others | 组件底部其他信息区域插槽 |
|
||||
| action | 组件操作区域插槽 |
|
||||
181
src/components/UserItem/index.vue
Normal file
181
src/components/UserItem/index.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user