Phase1_Day4_DeviceManager_page
This commit is contained in:
@@ -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 })
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
43
web.vite/src/views/warehouse/DeviceManager/index.vue
Normal file
43
web.vite/src/views/warehouse/DeviceManager/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user