412 lines
9.3 KiB
Vue
412 lines
9.3 KiB
Vue
<template>
|
|
<div class="drone-management">
|
|
<div class="header">
|
|
<h2>无人机管理</h2>
|
|
<div class="operation-buttons">
|
|
<el-button type="primary" @click="handleAdd">
|
|
<el-icon>
|
|
<Plus />
|
|
</el-icon>
|
|
添加无人机
|
|
</el-button>
|
|
<el-button type="danger" :disabled="!selectedIds.length" @click="handleBatchDelete">
|
|
<el-icon>
|
|
<Delete />
|
|
</el-icon>
|
|
批量删除
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="filter-container">
|
|
<el-input
|
|
v-model="listQuery.keyword"
|
|
placeholder="搜索无人机名称/型号"
|
|
style="width: 300px"
|
|
clearable
|
|
@keyup.enter="handleFilter"
|
|
>
|
|
<template #append>
|
|
<el-button :icon="Search" @click="handleFilter" />
|
|
</template>
|
|
</el-input>
|
|
<el-select
|
|
v-model="listQuery.status"
|
|
placeholder="状态筛选"
|
|
clearable
|
|
style="width: 120px; margin-left: 10px"
|
|
>
|
|
<el-option label="在线" value="online" />
|
|
<el-option label="离线" value="offline" />
|
|
<el-option label="维修中" value="maintenance" />
|
|
</el-select>
|
|
</div>
|
|
|
|
<el-table
|
|
v-loading="listLoading"
|
|
:data="droneList"
|
|
border
|
|
fit
|
|
highlight-current-row
|
|
style="width: 100%"
|
|
@selection-change="handleSelectionChange"
|
|
>
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
<el-table-column prop="id" label="ID" width="80" align="center" />
|
|
<el-table-column prop="name" label="无人机名称" min-width="120" />
|
|
<el-table-column prop="model" label="型号" width="150" />
|
|
<el-table-column prop="sn" label="序列号" width="180" />
|
|
<el-table-column label="状态" width="100" align="center">
|
|
<template #default="{ row }">
|
|
<el-tag :type="statusType[row.status]">
|
|
{{ statusMap[row.status] }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="battery" label="电量" width="100" align="center">
|
|
<template #default="{ row }">
|
|
<el-progress
|
|
:percentage="row.battery"
|
|
:color="batteryColor(row.battery)"
|
|
:show-text="false"
|
|
:stroke-width="18"
|
|
/>
|
|
{{ row.battery }}%
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="lastConnectTime" label="最后连接时间" width="180" />
|
|
<el-table-column label="操作" width="180" align="center" fixed="right">
|
|
<template #default="{ row }">
|
|
<el-button size="small" @click="handleEdit(row)">
|
|
<el-icon>
|
|
<Edit />
|
|
</el-icon>
|
|
</el-button>
|
|
<el-button size="small" type="danger" @click="handleDelete(row)">
|
|
<el-icon>
|
|
<Delete />
|
|
</el-icon>
|
|
</el-button>
|
|
<el-button size="small" type="warning" @click="handleControl(row)">
|
|
<el-icon>
|
|
<Connection />
|
|
</el-icon>
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="pagination-container">
|
|
<el-pagination
|
|
v-model:current-page="listQuery.page"
|
|
v-model:page-size="listQuery.limit"
|
|
:total="total"
|
|
:page-sizes="[10, 20, 30, 50]"
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handleCurrentChange"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 添加/编辑对话框 -->
|
|
<el-dialog
|
|
v-model="dialogVisible"
|
|
:title="dialogType === 'edit' ? '编辑无人机' : '添加无人机'"
|
|
width="600px"
|
|
>
|
|
<el-form
|
|
ref="droneForm"
|
|
:model="droneForm"
|
|
:rules="droneRules"
|
|
label-width="100px"
|
|
>
|
|
<el-form-item label="无人机名称" prop="name">
|
|
<el-input v-model="droneForm.name" placeholder="请输入无人机名称" />
|
|
</el-form-item>
|
|
<el-form-item label="无人机型号" prop="model">
|
|
<el-input v-model="droneForm.model" placeholder="请输入无人机型号" />
|
|
</el-form-item>
|
|
<el-form-item label="序列号" prop="sn">
|
|
<el-input v-model="droneForm.sn" placeholder="请输入序列号" />
|
|
</el-form-item>
|
|
<el-form-item label="状态" prop="status">
|
|
<el-select v-model="droneForm.status" placeholder="请选择状态">
|
|
<el-option
|
|
v-for="item in statusOptions"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="confirmDrone">确认</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, onMounted } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import { useRouter } from 'vue-router'
|
|
import {
|
|
Plus,
|
|
Delete,
|
|
Edit,
|
|
Search,
|
|
Connection
|
|
} from '@element-plus/icons-vue'
|
|
import { useRoute } from 'vue-router'
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
|
|
// 状态映射
|
|
const statusMap = {
|
|
online: '在线',
|
|
offline: '离线',
|
|
maintenance: '维修中'
|
|
}
|
|
|
|
const statusType = {
|
|
online: 'success',
|
|
offline: 'danger',
|
|
maintenance: 'warning'
|
|
}
|
|
|
|
const statusOptions = [
|
|
{ value: 'online', label: '在线' },
|
|
{ value: 'offline', label: '离线' },
|
|
{ value: 'maintenance', label: '维修中' }
|
|
]
|
|
|
|
// 电池颜色
|
|
const batteryColor = (percentage) => {
|
|
if (percentage > 70) return '#67C23A'
|
|
if (percentage > 30) return '#E6A23C'
|
|
return '#F56C6C'
|
|
}
|
|
|
|
// 列表相关
|
|
const listLoading = ref(false)
|
|
const droneList = ref([])
|
|
const total = ref(0)
|
|
const selectedIds = ref([])
|
|
|
|
const listQuery = reactive({
|
|
page: 1,
|
|
limit: 10,
|
|
keyword: '',
|
|
status: ''
|
|
})
|
|
|
|
// 表单相关
|
|
const dialogVisible = ref(false)
|
|
const dialogType = ref('add')
|
|
const droneForm = reactive({
|
|
id: '',
|
|
name: '',
|
|
model: '',
|
|
sn: '',
|
|
status: 'online',
|
|
battery: 100
|
|
})
|
|
|
|
const droneRules = reactive({
|
|
name: [{ required: true, message: '请输入无人机名称', trigger: 'blur' }],
|
|
model: [{ required: true, message: '请输入无人机型号', trigger: 'blur' }],
|
|
sn: [{ required: true, message: '请输入序列号', trigger: 'blur' }],
|
|
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
|
})
|
|
|
|
// 获取无人机列表
|
|
const fetchDrones = async () => {
|
|
listLoading.value = true
|
|
try {
|
|
// 这里替换为实际API调用
|
|
// const res = await getDroneList(listQuery)
|
|
// 模拟数据
|
|
setTimeout(() => {
|
|
droneList.value = [
|
|
{
|
|
id: 1,
|
|
name: '巡检无人机1号',
|
|
model: 'DJI Mavic 3',
|
|
sn: 'DJI123456789',
|
|
status: 'online',
|
|
battery: 85,
|
|
lastConnectTime: '2023-05-15 14:30:22'
|
|
},
|
|
{
|
|
id: 2,
|
|
name: '测绘无人机A',
|
|
model: 'DJI Phantom 4 RTK',
|
|
sn: 'DJI987654321',
|
|
status: 'offline',
|
|
battery: 25,
|
|
lastConnectTime: '2023-05-14 09:15:33'
|
|
},
|
|
{
|
|
id: 3,
|
|
name: '应急无人机',
|
|
model: 'DJI Matrice 300',
|
|
sn: 'DJI456789123',
|
|
status: 'maintenance',
|
|
battery: 0,
|
|
lastConnectTime: '2023-05-10 16:45:12'
|
|
}
|
|
].slice(
|
|
(listQuery.page - 1) * listQuery.limit,
|
|
listQuery.page * listQuery.limit
|
|
)
|
|
total.value = 3
|
|
listLoading.value = false
|
|
}, 500)
|
|
} catch (error) {
|
|
console.error(error)
|
|
listLoading.value = false
|
|
}
|
|
}
|
|
|
|
// 表格选择
|
|
const handleSelectionChange = (selection) => {
|
|
selectedIds.value = selection.map((item) => item.id)
|
|
}
|
|
|
|
// 筛选
|
|
const handleFilter = () => {
|
|
listQuery.page = 1
|
|
fetchDrones()
|
|
}
|
|
|
|
// 分页
|
|
const handleSizeChange = (val) => {
|
|
listQuery.limit = val
|
|
fetchDrones()
|
|
}
|
|
|
|
const handleCurrentChange = (val) => {
|
|
listQuery.page = val
|
|
fetchDrones()
|
|
}
|
|
|
|
// 添加无人机
|
|
const handleAdd = () => {
|
|
dialogType.value = 'add'
|
|
Object.assign(droneForm, {
|
|
id: '',
|
|
name: '',
|
|
model: '',
|
|
sn: '',
|
|
status: 'online',
|
|
battery: 100
|
|
})
|
|
dialogVisible.value = true
|
|
}
|
|
|
|
// 编辑无人机
|
|
const handleEdit = (row) => {
|
|
dialogType.value = 'edit'
|
|
Object.assign(droneForm, row)
|
|
dialogVisible.value = true
|
|
}
|
|
|
|
// 删除无人机
|
|
const handleDelete = (row) => {
|
|
ElMessageBox.confirm(`确认删除无人机 "${row.name}"?`, '警告', {
|
|
confirmButtonText: '确认',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
})
|
|
.then(async () => {
|
|
// 这里替换为实际API调用
|
|
// await deleteDrone(row.id)
|
|
ElMessage.success('删除成功')
|
|
fetchDrones()
|
|
})
|
|
.catch(() => {
|
|
})
|
|
}
|
|
|
|
// 批量删除
|
|
const handleBatchDelete = () => {
|
|
ElMessageBox.confirm(`确认删除选中的 ${selectedIds.value.length} 台无人机?`, '警告', {
|
|
confirmButtonText: '确认',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
})
|
|
.then(async () => {
|
|
// 这里替换为实际API调用
|
|
// await batchDeleteDrones(selectedIds.value)
|
|
ElMessage.success('删除成功')
|
|
selectedIds.value = []
|
|
fetchDrones()
|
|
})
|
|
.catch(() => {
|
|
})
|
|
}
|
|
|
|
// 控制无人机
|
|
const handleControl = (row) => {
|
|
ElMessage.info(`正在连接无人机 ${row.name}...`)
|
|
// 这里可以跳转到控制页面或打开控制对话框
|
|
router.push(`${row.id}`)
|
|
}
|
|
|
|
// 确认表单
|
|
const confirmDrone = () => {
|
|
// 这里替换为实际表单验证和API调用
|
|
ElMessage.success(
|
|
dialogType.value === 'add' ? '添加成功' : '更新成功'
|
|
)
|
|
dialogVisible.value = false
|
|
fetchDrones()
|
|
}
|
|
|
|
onMounted(() => {
|
|
fetchDrones()
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.drone-management {
|
|
padding: 20px;
|
|
}
|
|
|
|
.header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.filter-container {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.pagination-container {
|
|
margin-top: 20px;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.el-table {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.el-tag {
|
|
margin-right: 0;
|
|
}
|
|
|
|
.el-progress {
|
|
display: inline-block;
|
|
width: 80px;
|
|
margin-right: 10px;
|
|
vertical-align: middle;
|
|
}
|
|
</style>
|