Phase1_Day4_DeviceManager_page

This commit is contained in:
2026-05-16 23:44:53 +08:00
parent 0ea2882627
commit 7e77cc7db2
4 changed files with 166 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import request from '@/uitils/request'
export function getRegionTree(params) {
return request({ url: '/api/DeviceManager/GetRegionTree', method: 'get', params })
}
export function getDevicesByPoint(params) {
return request({ url: '/api/DeviceManager/GetDevicesByPoint', method: 'get', params })
}
export function updateDevice(id, data) {
return request({ url: `/api/DeviceManager/${id}`, method: 'put', data })
}

View File

@@ -0,0 +1,49 @@
<template>
<div class="device-table">
<div class="toolbar" v-if="selectedPoint">
<span>点位: <strong>{{ selectedPoint.name }}</strong></span>
<el-button size="small" type="primary" @click="loadDevices">刷新</el-button>
</div>
<el-table :data="devices" row-key="deviceId" v-loading="loading" stripe max-height="calc(100vh - 240px)">
<el-table-column prop="deviceName" label="名称" min-width="150" />
<el-table-column prop="deviceCategory" label="种类" width="120" />
<el-table-column prop="deviceGroup" label="分组" width="100" />
<el-table-column label="状态" width="80">
<template #default="{ row }">
<el-tag :type="row.isOnline==='在线'?'success':'danger'" size="small">{{ row.isOnline }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="adapterCode" label="来源" width="120" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button size="small" text @click="$emit('edit', row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { getDevicesByPoint } from '../api/deviceManager'
const props = defineProps({ selectedPoint: Object })
defineEmits(['edit'])
const devices = ref([])
const loading = ref(false)
const loadDevices = async () => {
if (!props.selectedPoint?.id) return
loading.value = true
try {
const res = await getDevicesByPoint({ pointId: props.selectedPoint.id, page: 1, size: 100 })
devices.value = res.items || []
} finally { loading.value = false }
}
watch(() => props.selectedPoint, loadDevices, { immediate: true })
</script>
<style scoped>
.device-table { padding: 8px; }
.toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
</style>

View File

@@ -0,0 +1,61 @@
<template>
<div class="region-tree">
<el-input v-model="filterText" placeholder="搜索区域/点位" size="small" clearable />
<el-tree
ref="treeRef"
:data="treeData"
:props="{ children: 'children', label: 'label' }"
:filter-node-method="filterNode"
node-key="id"
highlight-current
:expand-on-click-node="true"
@node-click="handleNodeClick"
style="margin-top:8px; max-height:calc(100vh - 200px); overflow-y:auto"
>
<template #default="{ data }">
<span class="tree-node">
<el-icon v-if="data.type==='region'"><Folder /></el-icon>
<el-icon v-else><Location /></el-icon>
<span>{{ data.label }}</span>
<el-tag size="small" type="info" style="margin-left:6px">{{ data.deviceCount || 0 }}</el-tag>
</span>
</template>
</el-tree>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
import { getRegionTree } from '../api/deviceManager'
const emit = defineEmits(['select-point'])
const treeRef = ref(null)
const treeData = ref([])
const filterText = ref('')
const loadTree = async () => {
const res = await getRegionTree()
treeData.value = res || []
}
loadTree()
const filterNode = (value, data) => {
if (!value) return true
return data.label.includes(value)
}
watch(filterText, (val) => {
treeRef.value?.filter(val)
})
const handleNodeClick = (data) => {
if (data.type === 'point') {
const id = parseInt(data.id.replace('p_', ''))
emit('select-point', { id, name: data.label })
}
}
</script>
<style scoped>
.region-tree { padding: 8px; }
.tree-node { display: flex; align-items: center; gap: 4px; }
</style>

View File

@@ -0,0 +1,43 @@
<template>
<div class="device-manager-page">
<div class="left-panel">
<RegionTree @select-point="onSelectPoint" />
</div>
<div class="right-panel">
<DeviceTable :selectedPoint="selectedPoint" @edit="onEdit" />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import RegionTree from './components/RegionTree.vue'
import DeviceTable from './components/DeviceTable.vue'
const selectedPoint = ref(null)
const onSelectPoint = (point) => {
selectedPoint.value = point
}
const onEdit = (device) => {
// TODO: open edit dialog (Day 5)
console.log('edit', device)
}
</script>
<style scoped>
.device-manager-page {
display: flex;
height: calc(100vh - 80px);
}
.left-panel {
width: 280px;
border-right: 1px solid #e4e7ed;
overflow-y: auto;
}
.right-panel {
flex: 1;
overflow-y: auto;
}
</style>