目录
前言
在企业级应用开发中,用户选择是一个非常常见的需求。无论是发送消息、分配任务,还是设置权限,我们都需要一个功能完善、体验良好的用户选择组件。本文将带你一步步实现一个基于若依 Ruoyi-Vue-Pro Vue3 的用户选择组件。
实现效果
思路
1. 需求分析
首先,我们需要明确组件的核心需求:
- 支持单选和多选模式
- 展示组织架构树
- 实现用户搜索
- 管理已选用户
- 支持数据回显
- 提供灵活的配置项
2. 设计思路
我们将组件分为三个主要部分:
1.组织架构树
- 树形展示部门结构
- 支持部门搜索
- 点击部门筛选用户
2.用户列表
- 展示用户信息
- 支持用户搜索
- 触底分页加载更多
- 实现单选/多选功能
3.已选用户区
- 显示已选用户
- 支持单个/批量取消选择
- 展示选择数量
实现
1. 创建子组件 components/PeopleSelect/index.vue
<template>
<div>
<el-dialog
:title="'用户选择' + (type == 'multiple' ? '(多选)' : '(单选)')"
v-model="dialogVisible"
:width="width || '1050px'"
:height="height || '650px'"
:before-close="handleClose"
append-to-body
>
<div class="selectBox">
<div class="search-area" v-show="showSearch">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="0">
<el-row :gutter="16">
<el-col :span="8">
<el-form-item prop="nickname">
<el-input
v-model="queryParams.nickname"
placeholder="请输入用户姓名"
clearable
size="default"
:prefix-icon="User"
@keyup.enter="handleQuery"
@clear="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
size="default"
:prefix-icon="Phone"
@keyup.enter="handleQuery"
@clear="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button-group>
<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
</el-button-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="topBox">
<div class="leftBox">
<div class="contentBox">
<div class="step-header">
<div class="step-number">1</div>
<div class="step-title">选择部门</div>
</div>
<div class="step-content">
<div class="search-input">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
:prefix-icon="Search"
/>
</div>
<div class="treeBox">
<el-tree
ref="treeRef"
:data="deptOptions"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
/>
</div>
</div>
</div>
</div>
<div class="leftBox">
<div class="contentBox">
<div class="step-header">
<div class="step-number">2</div>
<div class="step-title">选择用户</div>
<div class="step-actions" v-if="type == 'multiple'">
<el-button type="text" size="small" @click="handleCheckedNodeAll(true)">全选</el-button>
<el-button type="text" size="small" @click="handleCheckedNodeAll(false)">取消全选</el-button>
</div>
</div>
<div class="peopleBox">
<div class="peopleList" @scroll="handleScroll">
<el-checkbox-group ref="peopleCheckBoxes" v-model="checkedUsers" @change="handleCheckedUsersChange" :max="type == 'single' ? 1 : 2147483647">
<el-checkbox
v-for="item in list"
:label="item.username"
:key="item.id"
class="peopleCard"
>
<div class="peopleCardContent">
<div class="avatarBox">
<el-avatar
:size="30"
:src="item.avatar"
:fallback="() => item.nickname?.substring(0,1) || item.username?.substring(0,1) || 'U'"
/>
</div>
<div class="peopleInfoBox">
<div class="peopleName">{
{
item.nickname }}</div>
<div class="peopleDetail">
<el-icon v-if="item.sex === 1" color="#409EFF"><Male /></el-icon>
<el-icon v-else-if="item.sex === 2" color="#F56C6C"><Female /></el-icon>
<el-icon v-else color="#909399"><User /></el-icon>
<span class="deptName">{
{
item.deptName }}</span>
</div>
</div>
</div>
</el-checkbox>
</el-checkbox-group>
<!-- 加载更多提示 -->
<div v-if="loading" class="loading-more">
<el-icon class="is-loading"><Loading /></el-icon>
<span>加载中...</span>
</div>
<div v-if="noMore" class="no-more">
没有更多数据了
</div>
</div>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</div>
</div>
<!-- this.checkedUsers -->
<div class="leftBox">
<div class="contentBox">
<div class="step-header">
<div class="step-number">3</div>
<div class="step-title">
已选择用户
<span class="selected-count">({
{
selectedUserList.length }}人)</span>
</div>
<div class="step-actions">
<el-button
v-if="type == 'multiple'"
type="text"
size="small"
@click="clearAll"
>
清空
</el-button>
</div>
</div>
<div class="peopleBox">
<div class="peopleList">
<div
v-for="item in selectedUserList"
:key="item.id"
class="peopleCard"