|
|
@@ -1,55 +1,98 @@
|
|
|
<template>
|
|
|
<div class="page-container">
|
|
|
- <!-- 操作按钮 -->
|
|
|
- <div class="table-actions">
|
|
|
- <el-button type="primary" :icon="Plus" data-id="btn-add-machine" @click="handleAdd">新增机器</el-button>
|
|
|
- <el-button plain :icon="Refresh" data-id="btn-refresh" @click="getList">刷新列表</el-button>
|
|
|
+ <!-- 搜索表单 -->
|
|
|
+ <div class="search-form">
|
|
|
+ <el-form :model="searchForm" inline data-id="search-form">
|
|
|
+ <el-form-item label="机器ID">
|
|
|
+ <el-input
|
|
|
+ v-model="searchForm.machineId"
|
|
|
+ placeholder="请输入机器ID"
|
|
|
+ clearable
|
|
|
+ data-id="search-machine-id"
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="名称">
|
|
|
+ <el-input
|
|
|
+ v-model="searchForm.name"
|
|
|
+ placeholder="请输入名称"
|
|
|
+ clearable
|
|
|
+ data-id="search-name"
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="启用状态">
|
|
|
+ <el-select v-model="searchForm.enabled" placeholder="全部" clearable data-id="search-enabled">
|
|
|
+ <el-option label="全部" value="" />
|
|
|
+ <el-option label="已启用" :value="true" />
|
|
|
+ <el-option label="已禁用" :value="false" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="创建时间">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="searchForm.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ data-id="search-date-range"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" :icon="Search" data-id="btn-search" @click="handleSearch">查询</el-button>
|
|
|
+ <el-button :icon="RefreshRight" data-id="btn-reset" @click="handleReset">重置</el-button>
|
|
|
+ <el-button type="primary" :icon="Plus" data-id="btn-add-machine" @click="handleAdd">新增</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
</div>
|
|
|
|
|
|
<!-- 数据表格 -->
|
|
|
- <el-table v-loading="loading" :data="paginatedList" border data-id="machine-table">
|
|
|
- <el-table-column type="index" label="序号" width="60" align="center" />
|
|
|
- <el-table-column prop="machineId" label="机器ID" min-width="120" show-overflow-tooltip />
|
|
|
- <el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip>
|
|
|
- <template #default="{ row }">
|
|
|
- <el-link type="primary" :data-id="`link-edit-${row.machineId}`" @click="handleEdit(row)">
|
|
|
- {{ row.name }}
|
|
|
- </el-link>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="location" label="位置" min-width="120" show-overflow-tooltip />
|
|
|
- <el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
|
|
|
- <el-table-column prop="cameraCount" label="摄像头数" width="100" align="center">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-tag type="info">{{ row.cameraCount || 0 }}</el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="enabled" label="启用" width="80" align="center">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-tag :type="row.enabled ? 'success' : 'info'">
|
|
|
- {{ row.enabled ? '是' : '否' }}
|
|
|
- </el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- <el-table-column prop="createdAt" label="创建时间" width="170" align="center" />
|
|
|
- <el-table-column label="操作" width="150" align="center" fixed="right">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-button type="primary" link :icon="Edit" :data-id="`btn-edit-${row.machineId}`" @click="handleEdit(row)">
|
|
|
- 编辑
|
|
|
- </el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- link
|
|
|
- :icon="Delete"
|
|
|
- :disabled="deleteLoading"
|
|
|
- :data-id="`btn-delete-${row.machineId}`"
|
|
|
- @click="handleDelete(row)"
|
|
|
- >
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
+ <div class="table-wrapper">
|
|
|
+ <el-table v-loading="loading" :data="paginatedList" stripe data-id="machine-table" height="100%">
|
|
|
+ <el-table-column type="index" label="序号" width="60" align="center" />
|
|
|
+ <el-table-column prop="machineId" label="机器ID" min-width="120" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="name" label="名称" min-width="120" show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-link type="primary" :data-id="`link-edit-${row.machineId}`" @click="handleEdit(row)">
|
|
|
+ {{ row.name }}
|
|
|
+ </el-link>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="location" label="位置" min-width="120" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
|
|
|
+ <el-table-column prop="cameraCount" label="摄像头数" width="100" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag type="info">{{ row.cameraCount || 0 }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="enabled" label="启用" width="80" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag :type="row.enabled ? 'success' : 'info'">
|
|
|
+ {{ row.enabled ? '是' : '否' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="createdAt" label="创建时间" width="170" align="center" />
|
|
|
+ <el-table-column label="操作" width="150" align="center" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link :icon="Edit" :data-id="`btn-edit-${row.machineId}`" @click="handleEdit(row)">
|
|
|
+ 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ link
|
|
|
+ :icon="Delete"
|
|
|
+ :disabled="deleteLoading"
|
|
|
+ :data-id="`btn-delete-${row.machineId}`"
|
|
|
+ @click="handleDelete(row)"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
|
|
|
<!-- 分页 -->
|
|
|
<div class="pagination-container">
|
|
|
@@ -101,7 +144,7 @@
|
|
|
<script setup lang="ts">
|
|
|
import { ref, reactive, onMounted, computed } from 'vue'
|
|
|
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
|
|
|
-import { Refresh, Plus, Edit, Delete } from '@element-plus/icons-vue'
|
|
|
+import { Plus, Edit, Delete, Search, RefreshRight } from '@element-plus/icons-vue'
|
|
|
import { listMachines, addMachine, updateMachine, deleteMachine } from '@/api/machine'
|
|
|
import type { MachineDTO, MachineAddRequest, MachineUpdateRequest } from '@/types'
|
|
|
|
|
|
@@ -112,16 +155,57 @@ const machineList = ref<MachineDTO[]>([])
|
|
|
const dialogVisible = ref(false)
|
|
|
const formRef = ref<FormInstance>()
|
|
|
|
|
|
+// 搜索表单
|
|
|
+const searchForm = reactive<{
|
|
|
+ machineId: string
|
|
|
+ name: string
|
|
|
+ enabled: boolean | ''
|
|
|
+ dateRange: [string, string] | null
|
|
|
+}>({
|
|
|
+ machineId: '',
|
|
|
+ name: '',
|
|
|
+ enabled: '',
|
|
|
+ dateRange: null
|
|
|
+})
|
|
|
+
|
|
|
// 分页相关
|
|
|
const currentPage = ref(1)
|
|
|
-const pageSize = ref(10)
|
|
|
-const total = computed(() => machineList.value.length)
|
|
|
+const pageSize = ref(30)
|
|
|
+
|
|
|
+// 过滤后的数据
|
|
|
+const filteredList = computed(() => {
|
|
|
+ return machineList.value.filter((item) => {
|
|
|
+ // 机器ID过滤
|
|
|
+ if (searchForm.machineId && !item.machineId.toLowerCase().includes(searchForm.machineId.toLowerCase())) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // 名称过滤
|
|
|
+ if (searchForm.name && !item.name.toLowerCase().includes(searchForm.name.toLowerCase())) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // 启用状态过滤
|
|
|
+ if (searchForm.enabled !== '' && item.enabled !== searchForm.enabled) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // 时间范围过滤
|
|
|
+ if (searchForm.dateRange && searchForm.dateRange.length === 2) {
|
|
|
+ const itemDate = item.createdAt ? item.createdAt.split('T')[0] : ''
|
|
|
+ const [startDate, endDate] = searchForm.dateRange
|
|
|
+ if (itemDate < startDate || itemDate > endDate) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+const total = computed(() => filteredList.value.length)
|
|
|
|
|
|
// 分页后的数据
|
|
|
const paginatedList = computed(() => {
|
|
|
const start = (currentPage.value - 1) * pageSize.value
|
|
|
const end = start + pageSize.value
|
|
|
- return machineList.value.slice(start, end)
|
|
|
+ return filteredList.value.slice(start, end)
|
|
|
})
|
|
|
|
|
|
const form = reactive<{
|
|
|
@@ -159,6 +243,18 @@ async function getList() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function handleSearch() {
|
|
|
+ currentPage.value = 1 // 搜索时重置到第一页
|
|
|
+}
|
|
|
+
|
|
|
+function handleReset() {
|
|
|
+ searchForm.machineId = ''
|
|
|
+ searchForm.name = ''
|
|
|
+ searchForm.enabled = ''
|
|
|
+ searchForm.dateRange = null
|
|
|
+ currentPage.value = 1
|
|
|
+}
|
|
|
+
|
|
|
function handleAdd() {
|
|
|
Object.assign(form, {
|
|
|
id: undefined,
|
|
|
@@ -263,16 +359,117 @@ onMounted(() => {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.page-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%;
|
|
|
padding: 20px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
|
|
|
-.table-actions {
|
|
|
- margin-bottom: 15px;
|
|
|
+.search-form {
|
|
|
+ flex-shrink: 0;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ padding: 16px;
|
|
|
+ background: #f5f7fa;
|
|
|
+
|
|
|
+ :deep(.el-form-item) {
|
|
|
+ margin-bottom: 0;
|
|
|
+ margin-right: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-input),
|
|
|
+ :deep(.el-select) {
|
|
|
+ width: 160px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-date-editor--daterange) {
|
|
|
+ width: 280px;
|
|
|
+
|
|
|
+ .el-range-input {
|
|
|
+ width: 90px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-range-separator {
|
|
|
+ width: 30px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Indigo 主题按钮
|
|
|
+ :deep(.el-button--primary) {
|
|
|
+ background-color: #4f46e5;
|
|
|
+ border-color: #4f46e5;
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ background-color: #6366f1;
|
|
|
+ border-color: #6366f1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.table-wrapper {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 0;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.pagination-container {
|
|
|
+ flex-shrink: 0;
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
- margin-top: 16px;
|
|
|
+ padding-top: 16px;
|
|
|
+
|
|
|
+ // Indigo 主题分页
|
|
|
+ :deep(.el-pagination) {
|
|
|
+ .el-pager li.is-active {
|
|
|
+ background-color: #4f46e5;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-pager li:hover {
|
|
|
+ color: #4f46e5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-prev:hover,
|
|
|
+ .btn-next:hover {
|
|
|
+ color: #4f46e5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 表格样式
|
|
|
+:deep(.el-table) {
|
|
|
+ // 斑马纹对比度
|
|
|
+ --el-table-row-hover-bg-color: #f0f0ff;
|
|
|
+
|
|
|
+ .el-table__row--striped td.el-table__cell {
|
|
|
+ background-color: #f8f9fc;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 表头样式
|
|
|
+ .el-table__header th {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 链接颜色
|
|
|
+ .el-link--primary {
|
|
|
+ color: #4f46e5;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #6366f1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 主要按钮颜色
|
|
|
+ .el-button--primary.is-link {
|
|
|
+ color: #4f46e5;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #6366f1;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|