<template>
|
<div class="group-list-panel">
|
<div class="panel-header">
|
<div class="header-title">
|
<h3>设备组列表</h3>
|
<p>选择一个设备组进行编排测试</p>
|
</div>
|
<div class="actions">
|
<el-input
|
v-model="filters.keyword"
|
placeholder="搜索设备组名称/编码"
|
clearable
|
@clear="fetchGroups"
|
@keyup.enter="fetchGroups"
|
class="search-input"
|
>
|
<template #prefix>
|
<el-icon><Search /></el-icon>
|
</template>
|
</el-input>
|
<el-button :loading="loading" @click="fetchGroups">
|
<el-icon><Refresh /></el-icon>
|
</el-button>
|
</div>
|
</div>
|
|
<el-table
|
v-loading="loading"
|
:data="groups"
|
height="320"
|
stripe
|
class="group-table"
|
@row-click="handleRowClick"
|
>
|
<el-table-column prop="groupName" label="设备组" min-width="160" />
|
<el-table-column prop="groupCode" label="编码" min-width="120" />
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="{ row }">
|
<el-tag :type="formatStatus(row.status).type">{{ formatStatus(row.status).label }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="deviceCount" label="设备数量" width="100" />
|
<el-table-column label="最后更新时间" min-width="160">
|
<template #default="{ row }">
|
{{ row.updatedTime || row.createTime || '-' }}
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</template>
|
|
<script setup>
|
import { onMounted, reactive, ref } from 'vue'
|
import { Refresh, Search } from '@element-plus/icons-vue'
|
import { deviceGroupApi } from '@/api/device/deviceManagement'
|
|
const emit = defineEmits(['select'])
|
|
const loading = ref(false)
|
const groups = ref([])
|
const filters = reactive({
|
keyword: ''
|
})
|
|
const fetchGroups = async () => {
|
try {
|
loading.value = true
|
const payload = {
|
page: 1,
|
size: 20,
|
keyword: filters.keyword
|
}
|
const { data } = await deviceGroupApi.getList(payload)
|
const records = data?.records || data?.data || data || []
|
groups.value = Array.isArray(records) ? records : []
|
} finally {
|
loading.value = false
|
}
|
}
|
|
const handleRowClick = (row) => {
|
emit('select', row)
|
}
|
|
const formatStatus = (status) => {
|
const value = typeof status === 'number' ? status : String(status || '').toUpperCase()
|
if (value === 1 || value === '启用' || value === 'ENABLED') {
|
return { label: '启用', type: 'success' }
|
}
|
if (value === 0 || value === '停用' || value === 'DISABLED') {
|
return { label: '停用', type: 'info' }
|
}
|
if (value === 2 || value === '维护中' || value === 'MAINTENANCE') {
|
return { label: '维护', type: 'warning' }
|
}
|
return { label: status || '未知', type: 'default' }
|
}
|
|
onMounted(fetchGroups)
|
</script>
|
|
<style scoped>
|
.group-list-panel {
|
background: #fff;
|
border-radius: 12px;
|
padding: 20px;
|
box-shadow: 0 8px 32px rgba(15, 18, 63, 0.08);
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
}
|
|
.panel-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
gap: 16px;
|
flex-wrap: wrap;
|
}
|
|
.header-title {
|
flex: 0 0 auto;
|
min-width: 0;
|
}
|
|
.panel-header h3 {
|
margin: 0;
|
font-size: 18px;
|
white-space: nowrap;
|
}
|
|
.panel-header p {
|
margin: 2px 0 0;
|
color: #909399;
|
font-size: 13px;
|
white-space: nowrap;
|
word-break: keep-all;
|
}
|
|
.actions {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
flex-shrink: 0;
|
}
|
|
.search-input {
|
width: 240px;
|
min-width: 200px;
|
}
|
|
/* 小屏幕时,操作区域换行 */
|
@media (max-width: 768px) {
|
.panel-header {
|
flex-direction: column;
|
align-items: stretch;
|
}
|
|
.actions {
|
width: 100%;
|
justify-content: flex-end;
|
}
|
|
.search-input {
|
flex: 1;
|
min-width: 0;
|
}
|
}
|
|
.group-table {
|
flex: 1;
|
}
|
</style>
|