一、实现效果
左边是一个树形结构,展示门店的层次,并且可以进行滚动,右边是具体门店员工信息的展示
二、实现思路
1.静态结构
整体布局
采用 el-row 和 el-col 组件来构建页面布局,这是基于 Element Plus 提供的栅格系统。el-row 作为行容器,el-col 用于划分列,这里将页面分为左(占 span="4" )、右(占 span="20" )两部分,实现左右分栏效果。
左侧门店列表部分
- 滚动容器:使用
el-scrollbar组件并设置高度为80vh,目的是当内部内容(门店列表)超出该高度时出现滚动条,方便展示更多的信息。 - 表格展示:
el-table用于呈现门店数据,是展示的核心组件。v-loading="isLoading"实现表格加载状态的显示与隐藏,当数据加载时显示加载动画,加载完成后隐藏,增强用户体验。:cell-style="cellStyle"用于设置表格单元格的样式,通过定义cellStyle对象来指定如字体加粗、鼠标指针样式等样式属性,提升视觉效果和交互感。:data="shops"将静态的门店数据数组shops绑定到表格,使表格能展示门店信息。:tree-props="tableTreeProps"配合树形数据结构,指定数据中表示子节点的字段(这里是childs),让表格以树形结构展示门店层级关系。border属性为表格添加边框,使表格结构更清晰。default-expand-all让表格默认展开所有层级的树形结构,方便用户一开始就能看到所有门店层级。highlight-current-row高亮当前选中的行,便于用户明确当前选择的门店。row-key="selfid"为表格的每一行指定唯一标识,方便 Vue 进行虚拟 DOM 渲染和管理。size="large"设置表格尺寸为较大规格,使内容展示更清晰。@current-change="handleCurrentChange"监听表格当前行变化事件,当用户点击不同门店行时,触发该事件并执行handleCurrentChange方法,用于更新右侧展示的人员信息等操作。el-table-column定义表格列,这里定义了展示 “门店” 名称的列,通过prop="shop_name"绑定到数据中的对应字段。
右侧门店人员信息部分
- 条件渲染:使用
v-if="currentShopId!== undefined"进行条件判断,当有门店被选中(即currentShopId有值 )时,展示右侧区域内容,否则显示el-empty组件提示用户 “请选择门店” 。 - 添加人员按钮:当用户角色为 HR(通过
v-if="isHr"判断 )时,展示 “添加人员” 按钮,@click="handleAddClick"绑定点击事件,点击后执行handleAddClick方法,一般用于打开添加人员的对话框或页面等操作。 - 人员表格展示:
- 同样使用
el-table展示门店人员信息。v-loading="isLoading"处理表格加载状态。:data="currentShopUsers"将当前选中门店对应的人员数据数组currentShopUsers绑定到表格。 - 定义了 “用户名”(
prop="username")、“手机”(prop="mobile")列展示人员基本信息。 - 当用户角色为 HR 时,展示 “操作” 列,其中通过
el-popconfirm组件实现删除确认功能,点击 “删除” 按钮弹出确认框,确认后执行handleDeleteConfirm方法来处理删除逻辑。
- 同样使用
2.代码功能部分
为了方便起见,这里使用静态数据来展示
function handleCurrentChange({ selfid }) {
currentShopId.value = selfid;
currentShopUsers.value = staffData[selfid] || [];
}
handleCurrentChange 函数:当左侧门店表格中当前行发生变化时(即用户点击不同门店行 ),该函数被调用。它接收包含门店 selfid 的参数,将 currentShopId 更新为当前点击门的 selfid,然后根据这个 selfid 从 staffData 中获取对应的工作人员数组,赋值给 currentShopUsers,从而实现右侧展示区域根据选中门店更新工作人员信息的功能。
三、完整代码
<template>
<el-row>
<el-col :span="4">
<el-scrollbar height="80vh">
<el-table
v-loading="isLoading"
:cell-style="cellStyle"
:data="shops"
:tree-props="tableTreeProps"
border
default-expand-all
highlight-current-row
row-key="selfid"
size="large"
@current-change="handleCurrentChange"
>
<el-table-column label="门店" prop="shop_name" />
</el-table>
</el-scrollbar>
</el-col>
<el-col :span="20">
<div v-if="currentShopId!== undefined">
<div class="button">
<el-button v-if="isHr" type="primary" @click="handleAddClick">添加人员</el-button>
</div>
<div class="table">
<el-table v-loading="isLoading" :data="currentShopUsers" border>
<el-table-column label="用户名" prop="username" />
<el-table-column label="手机" prop="mobile" />
<el-table-column v-if="isHr" label="操作" width="140">
<template #default="{ row }">
<el-popconfirm
title="是否确定删除?"
@confirm="handleDeleteConfirm(currentShopId, row.userid)"
>
<template #reference>
<el-button link type="danger">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-empty v-else description="请选择门店" />
</el-col>
</el-row>
</template>
<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
// 静态门店数据
const shops = ref([
{
level: 1,
shop_name: '示例总店',
childs: [
{
level: 2,
shop_name: '示例分店1',
selfid: 1,
childs: [
{
level: 3,
shop_name: '示例子分店1',
selfid: 3
},
{
level: 3,
shop_name: '示例子分店2',
selfid: 4
},
{
level: 3,
shop_name: '示例子分店3',
selfid: 5
},
{
level: 3,
shop_name: '示例子分店4',
selfid: 6
},
{
level: 3,
shop_name: '示例子分店5',
selfid: 7
}
]
},
{
level: 2,
shop_name: '示例分店2',
selfid: 2,
childs: [
{
level: 3,
shop_name: '示例子分店6',
selfid: 8
},
{
level: 3,
shop_name: '示例子分店7',
selfid: 9
},
{
level: 3,
shop_name: '示例子分店8',
selfid: 10
}
]
},
{
level: 2,
shop_name: '示例分店3',
selfid: 11,
childs: [
{
level: 3,
shop_name: '示例子分店9',
selfid: 12
},
{
level: 3,
shop_name: '示例子分店10',
selfid: 13
}
]
},
{
level: 2,
shop_name: '示例分店4',
selfid: 14
},
{
level: 2,
shop_name: '示例分店5',
selfid: 15
}
],
selfid: 0
}
]);
// 静态工作人员数据
const staffData = {
0: [
{ username: '总店员工1', mobile: '13800000001', userid: '1' },
{ username: '总店员工2', mobile: '13800000002', userid: '2' },
{ username: '总店员工3', mobile: '13800000003', userid: '3' }
],
1: [
{ username: '分店1员工1', mobile: '13800000004', userid: '4' },
{ username: '分店1员工2', mobile: '13800000005', userid: '5' },
{ username: '分店1员工3', mobile: '13800000006', userid: '6' },
{ username: '分店1员工4', mobile: '13800000007', userid: '7' },
{ username: '分店1员工5', mobile: '13800000008', userid: '8' }
],
2: [
{ username: '分店2员工1', mobile: '13800000009', userid: '9' },
{ username: '分店2员工2', mobile: '13800000010', userid: '10' },
{ username: '分店2员工3', mobile: '13800000011', userid: '11' },
{ username: '分店2员工4', mobile: '13800000012', userid: '12' }
],
3: [
{ username: '子分店1员工1', mobile: '13800000013', userid: '13' },
{ username: '子分店1员工2', mobile: '13800000014', userid: '14' },
{ username: '子分店1员工3', mobile: '13800000015', userid: '15' }
],
4: [
{ username: '子分店2员工1', mobile: '13800000016', userid: '16' },
{ username: '子分店2员工2', mobile: '13800000017', userid: '17' }
],
5: [
{ username: '子分店3员工1', mobile: '13800000018', userid: '18' },
{ username: '子分店3员工2', mobile: '13800000019', userid: '19' }
],
6: [
{ username: '子分店4员工1', mobile: '13800000020', userid: '20' },
{ username: '子分店4员工2', mobile: '13800000021', userid: '21' }
],
7: [
{ username: '子分店5员工1', mobile: '13800000022', userid: '22' },
{ username: '子分店5员工2', mobile: '13800000023', userid: '23' }
],
8: [
{ username: '子分店6员工1', mobile: '13800000024', userid: '24' },
{ username: '子分店6员工2', mobile: '13800000025', userid: '25' }
],
9: [
{ username: '子分店7员工1', mobile: '13800000026', userid: '26' },
{ username: '子分店7员工2', mobile: '13800000027', userid: '27' }
],
10: [
{ username: '子分店8员工1', mobile: '13800000028', userid: '28' },
{ username: '子分店8员工2', mobile: '13800000029', userid: '29' }
],
11: [
{ username: '子分店9员工1', mobile: '13800000030', userid: '30' },
{ username: '子分店9员工2', mobile: '13800000031', userid: '31' }
],
12: [
{ username: '子分店10员工1', mobile: '13800000032', userid: '32' },
{ username: '子分店10员工2', mobile: '13800000033', userid: '33' }
],
14: [
{ username: '分店4员工1', mobile: '13800000034', userid: '34' },
{ username: '分店4员工2', mobile: '13800000035', userid: '35' }
],
15: [
{ username: '分店5员工1', mobile: '13800000036', userid: '36' },
{ username: '分店5员工2', mobile: '13800000037', userid: '37' }
]
};
const isLoading = ref(false);
const tableTreeProps = {
children: 'childs'
};
const cellStyle = {
fontWeight: 'bold',
cursor: 'pointer'
};
const isHr = ref(true);
const currentShopId = ref();
const currentShopUsers = ref([]);
function handleCurrentChange({ selfid }) {
currentShopId.value = selfid;
currentShopUsers.value = staffData[selfid] || [];
}
function handleAddClick() {
// 这里可以添加添加人员的逻辑
ElMessage.info('添加人员功能待实现');
}
async function handleDeleteConfirm(shopId, shopUserId) {
try {
// 这里可以添加删除人员的逻辑
const index = currentShopUsers.value.findIndex(item => item.userid === shopUserId);
if (index!== -1) {
currentShopUsers.value.splice(index, 1);
ElMessage.success('删除成功');
}
} catch (error) {
ElMessage.error('删除失败');
console.log(error);
}
}
</script>
<style scoped>
.button,
.table {
margin-left: 20px;
}
.button {
margin-bottom: 10px;
}
</style>



3178

被折叠的 条评论
为什么被折叠?



