<template>
|
<div class="app-container">
|
<el-form :model="filters" :inline="true">
|
<el-form-item label="门禁名称">
|
<el-input
|
v-model="filters.name"
|
style="width: 240px"
|
placeholder="请输入门禁名称"
|
clearable
|
:prefix-icon="Search"
|
@change="getTableData"
|
/>
|
</el-form-item>
|
<el-form-item label="门禁状态">
|
<el-select
|
v-model="filters.status"
|
style="width: 240px"
|
placeholder="请选择门禁状态"
|
clearable
|
@change="getTableData"
|
>
|
<el-option label="正常" value="1"></el-option>
|
<el-option label="异常" value="0"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="区域">
|
<el-input
|
v-model="filters.area"
|
style="width: 240px"
|
placeholder="请输入区域"
|
clearable
|
:prefix-icon="Search"
|
@change="getTableData"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="getTableData">搜索</el-button>
|
<el-button @click="resetFilters">重置</el-button>
|
</el-form-item>
|
</el-form>
|
<div class="table_list">
|
<div class="actions">
|
<div></div>
|
<div>
|
<el-button type="primary" @click="add" icon="Plus"> 新增 </el-button>
|
<el-button type="danger" icon="Delete" :disabled="multipleList.length <= 0" @click="batchDelete">批量删除</el-button>
|
</div>
|
</div>
|
<PIMTable
|
rowKey="id"
|
isSelection
|
:column="columns"
|
:tableData="dataList"
|
:page="{
|
current: pagination.currentPage,
|
size: pagination.pageSize,
|
total: pagination.total,
|
}"
|
@selection-change="handleSelectionChange"
|
@pagination="changePage"
|
>
|
</PIMTable>
|
</div>
|
<!-- 新增编辑弹窗 -->
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
|
<el-form :model="formData" label-width="100px">
|
<el-form-item label="门禁名称" required>
|
<el-input v-model="formData.name" placeholder="请输入门禁名称"></el-input>
|
</el-form-item>
|
<el-form-item label="区域" required>
|
<el-input v-model="formData.area" placeholder="请输入区域"></el-input>
|
</el-form-item>
|
<el-form-item label="位置" required>
|
<el-input v-model="formData.location" placeholder="请输入具体位置"></el-input>
|
</el-form-item>
|
<el-form-item label="状态" required>
|
<el-select v-model="formData.status" placeholder="请选择状态">
|
<el-option label="正常" value="1"></el-option>
|
<el-option label="异常" value="0"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="描述">
|
<el-input v-model="formData.description" type="textarea" rows="3" placeholder="请输入描述信息"></el-input>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="dialogVisible = false">取消</el-button>
|
<el-button type="primary" @click="saveData">确定</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed, onMounted } from 'vue';
|
import { Search, Plus, Delete } from '@element-plus/icons-vue';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
import dayjs from 'dayjs';
|
|
// 定义假数据
|
const mockData = [
|
{ id: 1, name: '东门门禁', area: '生产区', location: '东门入口', status: '1', lastUpdate: '2025-12-30 08:30:00', description: '主要用于员工上下班通行' },
|
{ id: 2, name: '西门门禁', area: '仓储区', location: '西门入口', status: '1', lastUpdate: '2025-12-30 09:15:00', description: '主要用于物流车辆通行' },
|
{ id: 3, name: '南门门禁', area: '办公区', location: '南门入口', status: '0', lastUpdate: '2025-12-30 10:20:00', description: '主要用于访客通行,当前故障' },
|
{ id: 4, name: '北门门禁', area: '生产区', location: '北门入口', status: '1', lastUpdate: '2025-12-30 11:45:00', description: '主要用于原材料运输车辆通行' },
|
{ id: 5, name: '中控室门禁', area: '中控区', location: '中控室门口', status: '1', lastUpdate: '2025-12-30 13:20:00', description: '仅限授权人员进入' },
|
];
|
|
// 响应式数据
|
const filters = reactive({
|
name: '',
|
status: '',
|
area: ''
|
});
|
|
const dataList = ref([]);
|
const pagination = reactive({
|
currentPage: 1,
|
pageSize: 10,
|
total: 0
|
});
|
|
const multipleList = ref([]);
|
const dialogVisible = ref(false);
|
const dialogTitle = ref('新增门禁');
|
const formData = reactive({
|
id: '',
|
name: '',
|
area: '',
|
location: '',
|
status: '1',
|
description: ''
|
});
|
|
// 表格列配置
|
const columns = [
|
{
|
label: '门禁名称',
|
align: 'center',
|
prop: 'name',
|
},
|
{
|
label: '区域',
|
align: 'center',
|
prop: 'area',
|
},
|
{
|
label: '位置',
|
align: 'center',
|
prop: 'location',
|
},
|
{
|
label: '状态',
|
align: 'center',
|
prop: 'status',
|
formatter: (row) => {
|
return row.status === '1' ? '<el-tag type="success">正常</el-tag>' : '<el-tag type="danger">异常</el-tag>';
|
}
|
},
|
{
|
label: '最后更新',
|
align: 'center',
|
prop: 'lastUpdate',
|
},
|
{
|
label: '描述',
|
align: 'center',
|
prop: 'description',
|
},
|
{
|
dataType: 'action',
|
label: '操作',
|
align: 'center',
|
fixed: 'right',
|
width: 140,
|
operation: [
|
{
|
name: '编辑',
|
type: 'text',
|
clickFun: (row) => {
|
edit(row);
|
},
|
},
|
{
|
name: '删除',
|
type: 'text',
|
clickFun: (row) => {
|
deleteRow(row.id);
|
},
|
},
|
],
|
},
|
];
|
|
// 过滤后的数据
|
const filteredData = computed(() => {
|
return mockData.filter(item => {
|
const nameMatch = !filters.name || item.name.includes(filters.name);
|
const statusMatch = !filters.status || item.status === filters.status;
|
const areaMatch = !filters.area || item.area.includes(filters.area);
|
return nameMatch && statusMatch && areaMatch;
|
});
|
});
|
|
// 获取表格数据
|
const getTableData = () => {
|
pagination.total = filteredData.value.length;
|
const start = (pagination.currentPage - 1) * pagination.pageSize;
|
const end = start + pagination.pageSize;
|
dataList.value = filteredData.value.slice(start, end);
|
};
|
|
// 重置过滤器
|
const resetFilters = () => {
|
filters.name = '';
|
filters.status = '';
|
filters.area = '';
|
pagination.currentPage = 1;
|
getTableData();
|
};
|
|
// 分页变化
|
const changePage = ({ page, limit }) => {
|
pagination.currentPage = page;
|
pagination.pageSize = limit;
|
getTableData();
|
};
|
|
// 多选处理
|
const handleSelectionChange = (selectionList) => {
|
multipleList.value = selectionList;
|
};
|
|
// 新增
|
const add = () => {
|
dialogTitle.value = '新增门禁';
|
formData.id = '';
|
formData.name = '';
|
formData.area = '';
|
formData.location = '';
|
formData.status = '1';
|
formData.description = '';
|
dialogVisible.value = true;
|
};
|
|
// 编辑
|
const edit = (row) => {
|
dialogTitle.value = '编辑门禁';
|
formData.id = row.id;
|
formData.name = row.name;
|
formData.area = row.area;
|
formData.location = row.location;
|
formData.status = row.status;
|
formData.description = row.description;
|
dialogVisible.value = true;
|
};
|
|
// 保存数据
|
const saveData = () => {
|
if (!formData.name || !formData.area || !formData.location) {
|
ElMessage.warning('请填写必填字段');
|
return;
|
}
|
|
const currentTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
if (formData.id) {
|
// 编辑
|
const index = mockData.findIndex(item => item.id === formData.id);
|
if (index !== -1) {
|
mockData[index] = {
|
...formData,
|
lastUpdate: currentTime
|
};
|
ElMessage.success('编辑成功');
|
}
|
} else {
|
// 新增
|
const newId = Math.max(...mockData.map(item => item.id), 0) + 1;
|
mockData.unshift({
|
...formData,
|
id: newId,
|
lastUpdate: currentTime
|
});
|
ElMessage.success('新增成功');
|
}
|
dialogVisible.value = false;
|
getTableData();
|
};
|
|
// 删除
|
const deleteRow = (id) => {
|
ElMessageBox.confirm('此操作将永久删除该门禁记录, 是否继续?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
}).then(() => {
|
const index = mockData.findIndex(item => item.id === id);
|
if (index !== -1) {
|
mockData.splice(index, 1);
|
ElMessage.success('删除成功');
|
getTableData();
|
}
|
}).catch(() => {});
|
};
|
|
// 批量删除
|
const batchDelete = () => {
|
if (multipleList.value.length === 0) {
|
ElMessage.warning('请选择要删除的数据');
|
return;
|
}
|
|
ElMessageBox.confirm('此操作将永久删除所选门禁记录, 是否继续?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
}).then(() => {
|
const ids = multipleList.value.map(item => item.id);
|
mockData.forEach((item, index) => {
|
if (ids.includes(item.id)) {
|
mockData.splice(index, 1);
|
}
|
});
|
ElMessage.success('删除成功');
|
getTableData();
|
multipleList.value = [];
|
}).catch(() => {});
|
};
|
|
// 初始化数据
|
onMounted(() => {
|
getTableData();
|
});
|
</script>
|
|
<style lang="scss" scoped>
|
.table_list {
|
margin-top: unset;
|
}
|
.actions {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
</style>
|