Vue3 + Element Plus 人员列表搜索功能实现
设计思路
使用Element Plus的el-table组件展示人员数据
在姓名表头添加搜索图标按钮
点击按钮弹出搜索对话框
在对话框中输入姓名进行搜索
实现搜索功能并高亮匹配项
下面是完整的实现代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>人员管理系统 - Vue3 + Element Plus</title><!-- 引入Element Plus样式 --><link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css"><!-- 引入Element Plus图标 --><link rel="stylesheet" href="https://unpkg.com/@element-plus/icons-vue/dist/index.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);min-height: 100vh;padding: 20px;color: #333;}.container {max-width: 1200px;margin: 0 auto;padding: 20px;}header {text-align: center;margin-bottom: 30px;padding: 20px;background: linear-gradient(90deg, #1e3c72 0%, #2a5298 100%);border-radius: 12px;color: white;box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);}h1 {font-size: 2.5rem;margin-bottom: 10px;}.subtitle {font-size: 1.1rem;opacity: 0.9;}.card {background: white;border-radius: 12px;box-shadow: 0 6px 30px rgba(0, 0, 0, 0.1);padding: 25px;margin-bottom: 30px;transition: transform 0.3s ease, box-shadow 0.3s ease;}.card:hover {transform: translateY(-5px);box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);}.search-container {display: flex;justify-content: flex-end;margin-bottom: 20px;}.search-btn {display: flex;align-items: center;background: linear-gradient(90deg, #1e3c72 0%, #2a5298 100%);color: white;border: none;padding: 10px 20px;border-radius: 8px;cursor: pointer;transition: all 0.3s ease;box-shadow: 0 4px 15px rgba(30, 60, 114, 0.3);}.search-btn:hover {transform: translateY(-2px);box-shadow: 0 6px 20px rgba(30, 60, 114, 0.4);}.search-btn i {margin-right: 8px;font-size: 18px;}.highlight {background-color: #ffeb3b;font-weight: bold;padding: 0 2px;border-radius: 3px;}.stats {display: flex;justify-content: space-between;margin-top: 20px;background: #f8f9fc;padding: 15px;border-radius: 8px;font-size: 0.95rem;}.stat-item {text-align: center;padding: 0 15px;}.stat-value {font-size: 1.4rem;font-weight: bold;color: #1e3c72;}.stat-label {color: #6c757d;font-size: 0.9rem;}.footer {text-align: center;margin-top: 30px;color: #6c757d;font-size: 0.9rem;}@media (max-width: 768px) {.stats {flex-direction: column;}.stat-item {margin-bottom: 15px;}}</style>
</head>
<body><div id="app"><div class="container"><header><h1>人员管理系统</h1><p class="subtitle">使用 Vue3 和 Element Plus 构建</p></header><main><div class="card"><div class="search-container"><button class="search-btn" @click="openSearchDialog"><i class="el-icon-search"></i> 搜索人员</button></div><el-table :data="filteredPersonnel" style="width: 100%" border stripe><el-table-column prop="id" label="ID" width="80" sortable></el-table-column><el-table-column label="姓名" sortable><template #header><span>姓名</span><el-button type="text" @click="openSearchDialog"><i class="el-icon-search" style="margin-left: 8px; font-size: 16px;"></i></el-button></template><template #default="scope"><span v-html="highlightSearchTerm(scope.row.name)"></span></template></el-table-column><el-table-column prop="position" label="职位" width="180"></el-table-column><el-table-column prop="department" label="部门" width="150"></el-table-column><el-table-column prop="email" label="邮箱" width="220"></el-table-column><el-table-column prop="phone" label="电话" width="150"></el-table-column><el-table-column label="状态" width="120"><template #default="scope"><el-tag :type="scope.row.status === '在职' ? 'success' : 'danger'">{{ scope.row.status }}</el-tag></template></el-table-column></el-table><div class="stats"><div class="stat-item"><div class="stat-value">{{ totalPersonnel }}</div><div class="stat-label">总人数</div></div><div class="stat-item"><div class="stat-value">{{ activePersonnel }}</div><div class="stat-label">在职人员</div></div><div class="stat-item"><div class="stat-value">{{ filteredCount }}</div><div class="stat-label">搜索结果</div></div></div></div></main><!-- 搜索对话框 --><el-dialog v-model="searchDialogVisible" title="搜索人员" width="500px"><el-inputv-model="searchTerm"placeholder="请输入人员姓名"clearable@keyup.enter="applySearch"><template #prefix><i class="el-icon-search"></i></template></el-input><div style="margin-top: 20px;"><el-button type="primary" @click="applySearch" style="width: 100%;"><i class="el-icon-search"></i> 搜索</el-button><el-button @click="clearSearch" style="width: 100%; margin-top: 10px;"><i class="el-icon-refresh"></i> 重置搜索</el-button></div><template #footer><div style="text-align: center; margin-top: 10px;"><el-button type="text" @click="searchDialogVisible = false">关闭</el-button></div></template></el-dialog><footer class="footer"><p>© 2023 人员管理系统 | 使用 Vue3 和 Element Plus 构建</p></footer></div></div><!-- 引入Vue 3 --><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><!-- 引入Element Plus --><script src="https://unpkg.com/element-plus/dist/index.full.js"></script><!-- 引入Element Plus图标 --><script src="https://unpkg.com/@element-plus/icons-vue"></script><script>const { createApp, ref, computed } = Vue;const app = createApp({setup() {// 搜索对话框可见性const searchDialogVisible = ref(false);// 搜索关键词const searchTerm = ref('');// 打开搜索对话框const openSearchDialog = () => {searchDialogVisible.value = true;};// 应用搜索const applySearch = () => {searchDialogVisible.value = false;};// 清除搜索const clearSearch = () => {searchTerm.value = '';applySearch();};// 模拟人员数据const personnelData = ref([{ id: 1, name: '张明', position: '前端工程师', department: '技术部', email: 'zhangming@example.com', phone: '13800138001', status: '在职' },{ id: 2, name: '李华', position: '后端工程师', department: '技术部', email: 'lihua@example.com', phone: '13800138002', status: '在职' },{ id: 3, name: '王芳', position: 'UI设计师', department: '设计部', email: 'wangfang@example.com', phone: '13800138003', status: '在职' },{ id: 4, name: '刘伟', position: '产品经理', department: '产品部', email: 'liuwei@example.com', phone: '13800138004', status: '在职' },{ id: 5, name: '陈静', position: '测试工程师', department: '质量保障部', email: 'chenjing@example.com', phone: '13800138005', status: '在职' },{ id: 6, name: '赵阳', position: '运维工程师', department: '技术部', email: 'zhaoyang@example.com', phone: '13800138006', status: '离职' },{ id: 7, name: '钱浩', position: '项目经理', department: '项目管理部', email: 'qianhao@example.com', phone: '13800138007', status: '在职' },{ id: 8, name: '孙琳', position: '数据分析师', department: '数据分析部', email: 'sunlin@example.com', phone: '13800138008', status: '在职' },{ id: 9, name: '周涛', position: '移动开发工程师', department: '技术部', email: 'zhoutao@example.com', phone: '13800138009', status: '在职' },{ id: 10, name: '吴敏', position: 'HR专员', department: '人力资源部', email: 'wumin@example.com', phone: '13800138010', status: '在职' }]);// 过滤后的人员数据const filteredPersonnel = computed(() => {if (!searchTerm.value) {return personnelData.value;}const term = searchTerm.value.toLowerCase();return personnelData.value.filter(person => person.name.toLowerCase().includes(term));});// 高亮搜索关键词const highlightSearchTerm = (name) => {if (!searchTerm.value) return name;const term = searchTerm.value;const regex = new RegExp(term, 'gi');return name.replace(regex, match => `<span class="highlight">${match}</span>`);};// 统计信息const totalPersonnel = computed(() => personnelData.value.length);const activePersonnel = computed(() => personnelData.value.filter(p => p.status === '在职').length);const filteredCount = computed(() => filteredPersonnel.value.length);return {searchDialogVisible,searchTerm,openSearchDialog,applySearch,clearSearch,filteredPersonnel,highlightSearchTerm,totalPersonnel,activePersonnel,filteredCount};}});// 注册Element Plusapp.use(ElementPlus);// 注册图标组件const ElIcon = ElementPlus.ElIcon;app.component('el-icon', ElIcon);app.mount('#app');</script>
</body>
</html>