# MatchUserItem 用户项
用户项组件,显示用户信息和操作按钮。支持灵活的按钮配置、自定义操作,适用于队伍管理、好友申请、成员审核等场景。
# 特性
- 👤 用户信息展示 - 支持头像、昵称、标签、描述等信息展示
- 🏷️ 多标签支持 - 支持显示多个标签,自动换行
- 🎯 灵活配置 - 通过按钮配置数组自由定义操作按钮,不固化业务状态
- 🎨 主题定制 - 丰富的CSS变量支持主题定制,支持按钮类型、尺寸、朴素模式
- 🔧 插槽支持 - 支持为每个按钮自定义插槽
- ⚡ 轻量高效 - 优化的代码结构,性能出色
# 适用场景
- 队伍成员管理
- 好友申请审核
- 用户列表展示
- 成员邀请功能
- 任何需要用户信息+操作按钮的场景
# 引入
import PressMatchUserItem from 'press-next/press-match-user-item/press-match-user-item';
# 代码演示
# 基础用法
<template>
<PressMatchUserItem
:user-info="userInfo"
:buttons="buttons"
@button-click="handleButtonClick"
@image-error="handleImageError"
/>
</template>
<script setup lang="ts">
import PressMatchUserItem from 'press-next/press-match-user-item/press-match-user-item.vue';
// 用户信息
const userInfo = {
avatar: 'https://img.yzcdn.cn/vant/cat.jpeg',
name: '张三',
tags: [
{ icon: 'https://example.com/icon1.png', name: '王者荣耀' },
{ icon: 'https://example.com/icon2.png', name: '和平精英' }
],
description: '擅长打野位置,段位王者',
id: '001'
};
// 按钮配置
const buttons = [
{
key: 'ignore',
text: '忽略',
type: 'default',
plain: false,
size: 'normal',
},
{
key: 'pass',
text: '通过',
type: 'primary',
plain: false,
size: 'normal',
},
];
// 统一处理按钮点击
const handleButtonClick = (button, userInfo) => {
console.log('按钮点击:', button.key, '用户:', userInfo);
// 根据按钮key执行不同逻辑
if (button.key === 'ignore') {
console.log('忽略用户');
} else if (button.key === 'pass') {
console.log('通过用户');
}
};
const handleImageError = (userInfo) => {
console.log('图片加载失败:', userInfo);
};
</script>
# 不同场景的按钮配置
<template>
<div class="user-list">
<!-- 待审核场景 -->
<PressMatchUserItem
:user-info="pendingUser"
:buttons="pendingButtons"
@button-click="handleButtonClick"
/>
<!-- 已通过场景 -->
<PressMatchUserItem
:user-info="passedUser"
:buttons="passedButtons"
@button-click="handleButtonClick"
/>
<!-- 队伍管理场景 -->
<PressMatchUserItem
:user-info="manageUser"
:buttons="manageButtons"
@button-click="handleButtonClick"
/>
</div>
</template>
<script setup lang="ts">
// 待审核场景按钮
const pendingButtons = [
{ key: 'ignore', text: '忽略', type: 'default' },
{ key: 'pass', text: '通过', type: 'primary' }
];
// 已通过场景按钮
const passedButtons = [
{ key: 'passed', text: '已通过', type: 'default', disabled: true }
];
// 队伍管理场景按钮
const manageButtons = [
{ key: 'transfer', text: '移交队长', type: 'default' },
{ key: 'kick', text: '踢出队伍', type: 'danger' }
];
const handleButtonClick = (button, userInfo) => {
console.log(`执行操作: ${button.key}, 用户: ${userInfo.name}`);
};
</script>
# 使用插槽自定义按钮
<template>
<PressMatchUserItem
:user-info="userInfo"
:buttons="buttons"
@button-click="handleButtonClick"
>
<!-- 自定义通过按钮 -->
<template #pass-btn>
<button class="custom-btn" @click="handleCustomPass">
✓ 批准加入
</button>
</template>
<!-- 自定义忽略按钮 -->
<template #ignore-btn>
<button class="custom-btn-secondary" @click="handleCustomIgnore">
✗ 拒绝
</button>
</template>
</PressMatchUserItem>
</template>
<script setup lang="ts">
const handleCustomPass = () => {
console.log('自定义批准逻辑');
};
const handleCustomIgnore = () => {
console.log('自定义拒绝逻辑');
};
</script>
<style scoped>
.custom-btn {
padding: 8px 16px;
background: #52c41a;
color: white;
border: none;
border-radius: 4px;
}
.custom-btn-secondary {
padding: 8px 16px;
background: #f5f5f5;
color: #666;
border: 1px solid #d9d9d9;
border-radius: 4px;
}
</style>
# 自定义主题
<template>
<PressMatchUserItem
custom-class="my-custom-theme"
:user-info="userInfo"
:buttons="buttons"
/>
</template>
<style>
.my-custom-theme {
/* 卡片样式 */
--pmui-user-item-bg: #f5f5f5;
--pmui-user-item-padding: 0.32rem;
/* 头像样式 */
--pmui-avatar-wrapper-size: 1rem;
/* 标签样式 */
--pmui-user-tag-bg: rgba(255, 107, 0, 0.1);
--pmui-tag-label-color: #ff6b00;
/* 按钮样式 */
--pmui-btn-radius: 0.4rem;
}
</style>
# API
# Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| user-info | 用户信息 | UserInfo | - |
| buttons | 按钮配置列表 | ButtonConfig[] | [] |
| custom-class | 自定义样式类 | string | '' |
# UserInfo 数据结构
// 标签接口
interface Tag {
icon?: string; // 标签图标(可选)
name: string; // 标签名称
}
// 用户信息接口
interface UserInfo {
avatar?: string; // 用户头像(可选)
name: string; // 用户名称
tags?: Tag[]; // 标签列表(可选)
description?: string; // 用户描述(可选)
id?: string; // 用户ID(可选)
}
# ButtonConfig 数据结构
interface ButtonConfig {
key: string; // 按钮唯一标识,用于插槽名称和事件识别
text: string; // 按钮文本
type?: ButtonType; // 按钮类型
plain?: boolean; // 是否朴素按钮
size?: ButtonSize; // 按钮尺寸
openType?: string; // 微信小程序开放能力
disabled?: boolean; // 是否禁用
}
type ButtonType = 'primary' | 'default' | 'info' | 'warning' | 'danger';
type ButtonSize = 'normal' | 'large' | 'small' | 'mini';
# Slots
| 名称 | 说明 |
|---|---|
${button.key}-btn | 自定义按钮,key为按钮配置中的key值 |
插槽命名规则:按钮的 key 值 + -btn 后缀
示例:
- 按钮 key 为
'pass'→ 插槽名为'pass-btn' - 按钮 key 为
'ignore'→ 插槽名为'ignore-btn'
# Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| button-click | 按钮点击 | (button: ButtonConfig, userInfo: UserInfo) |
| image-error | 头像图片加载失败 | (userInfo: UserInfo) |
# 注意事项
# 使用建议
- 按钮配置:通过
buttons数组灵活配置按钮,每个按钮必须有唯一的key值 - 标签:
tags为数组类型,支持显示多个标签,标签过多时会自动换行。标签的icon字段为可选,不传则只显示文字 - 头像:
avatar字段为可选,不传则不显示头像区域 - 事件处理:使用统一的
button-click事件,根据button.key区分不同操作 - 描述信息:
description字段可选,用于显示用户的额外信息
# 设计理念
本组件采用配置驱动的设计理念:
- 不固化业务状态:没有
status属性,不预设"待审核"、"已通过"等状态 - 配置什么展示什么:通过
buttons数组自由定义要显示的按钮 - 灵活扩展:可以随时添加、删除、修改按钮配置,无需修改组件代码
- 统一事件处理:所有按钮点击都触发
button-click事件,简化事件管理
# 性能优化
- 使用
v-memo指令优化列表渲染 - 大量用户时考虑虚拟滚动
- 头像图片建议使用 CDN 加速
# 兼容性
- 支持 Vue 3.0+
- 兼容现代浏览器(Chrome 60+, Firefox 60+, Safari 12+)
- 支持微信小程序、支付宝小程序等平台
# 主题定制
# 样式变量
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。
# 间距系统 (Spacing)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-user-item-padding | $spacing-md | 用户项内边距 |
| --pmui-avatar-wrapper-margin | 0 $spacing-lg 0 0 | 头像容器外边距 |
| --pmui-user-tag-margin-top | 0.06rem | 标签容器上边距 |
| --pmui-user-tag-gap | 0.16rem | 标签之间间距 |
| --pmui-user-tag-padding | 0.04rem 0.16rem | 单个标签内边距 |
| --pmui-tag-icon-margin-right | 0.04rem | 标签图标右边距 |
| --pmui-operation-gap | 0.14rem | 操作按钮间距 |
| --pmui-desc-margin-top | 0.24rem | 描述上边距 |
| --pmui-desc-padding | 0.16rem 0.24rem | 描述内边距 |
# 块状系统 (Box Model)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-avatar-wrapper-size | 0.8rem | 头像容器尺寸 |
| --pmui-avatar-image-size | 100% | 头像图片尺寸 |
| --pmui-content-flex | 1 | 内容区域flex |
| --pmui-content-info-width | 100% | 内容信息宽度 |
| --pmui-user-name-max-width | 2.4rem | 用户名最大宽度 |
| --pmui-tag-icon-size | 0.28rem | 标签图标尺寸 |
| --pmui-tag-label-max-width | 2rem | 标签文字最大宽度 |
| --pmui-btn-width | 1.28rem | 按钮宽度 |
| --pmui-btn-min-width | 1.2rem | 按钮最小宽度 |
| --pmui-btn-height | 0.5rem | 按钮高度 |
| --pmui-desc-width | 100% | 描述宽度 |
# 颜色系统 (Colors)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-user-item-bg | $color-surface-default | 用户项背景色 |
| --pmui-user-tag-bg | $color-divider-light | 标签背景色 |
| --pmui-desc-bg | $color-surface-secondary | 描述背景色 |
| --pmui-user-name-color | $color-text-primary | 用户名颜色 |
| --pmui-tag-label-color | $color-text-secondary | 标签文字颜色 |
| --pmui-desc-color | $color-text-invert-dark | 描述文字颜色 |
# 字体系统 (Typography)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-user-name-font-size | $font-size-md | 用户名字体大小 |
| --pmui-user-name-font-weight | $font-weight-bold | 用户名字体粗细 |
| --pmui-user-name-line-height | 1.5 | 用户名行高 |
| --pmui-tag-label-font-size | $font-size-xs | 标签文字大小 |
| --pmui-tag-label-font-weight | $font-weight-regular | 标签文字粗细 |
| --pmui-tag-label-line-height | 1.5 | 标签文字行高 |
| --pmui-btn-font-size | $font-size-sm | 按钮字体大小 |
| --pmui-btn-font-weight | $font-weight-bold | 按钮字体粗细 |
| --pmui-btn-line-height | 1.5 | 按钮行高 |
| --pmui-desc-font-size | $font-size-xs | 描述字体大小 |
| --pmui-desc-font-weight | $font-weight-regular | 描述字体粗细 |
| --pmui-desc-line-height | 1.5 | 描述行高 |
# 圆角系统 (Border Radius)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-avatar-image-radius | 50% | 头像圆角 |
| --pmui-btn-radius | $border-radius-999 | 按钮圆角 |
# 边框系统 (Border)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-user-item-border-bottom | 1px solid $color-divider-light | 用户项底部边框 |
# 其他属性 (Others)
| 名称 | 默认值 | 描述 |
|---|---|---|
| --pmui-user-item-position | relative | 用户项定位方式 |
| --pmui-avatar-wrapper-position | relative | 头像容器定位方式 |
| --pmui-avatar-image-fit | cover | 头像图片填充方式 |