| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- <template>
- <div class="point-container">
- <el-card class="search-card">
- <el-form :inline="true" :model="searchForm">
- <el-form-item label="测点名称">
- <el-input v-model="searchForm.pointName" placeholder="请输入测点名称" clearable />
- </el-form-item>
- <el-form-item label="测点类型">
- <el-select v-model="searchForm.pointType" placeholder="请选择" clearable style="width:160px">
- <el-option v-for="d in pointTypeDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleSearch">查询</el-button>
- <el-button @click="handleReset">重置</el-button>
- <el-button type="success" @click="handleAdd">新增测点</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- <el-card class="table-card">
- <el-table :data="tableData" border stripe v-loading="loading">
- <el-table-column prop="pointCode" label="测点编码" width="120" />
- <el-table-column prop="pointName" label="测点名称" min-width="150" />
- <el-table-column prop="pointType" label="测点类型" width="110">
- <template #default="{ row }">{{ getDictLabel(pointTypeDict, row.pointType) }}</template>
- </el-table-column>
- <el-table-column label="所属管网" width="150">
- <template #default="{ row }">{{ getNetworkName(row.networkId) }}</template>
- </el-table-column>
- <el-table-column prop="location" label="位置" min-width="180" />
- <el-table-column prop="status" label="状态" width="90">
- <template #default="{ row }">
- <el-tag :type="row.status === 'ACTIVE' ? 'success' : 'info'">{{ getDictLabel(pointStatusDict, row.status) }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="200" fixed="right">
- <template #default="{ row }">
- <el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
- <el-button type="info" size="small" @click="handleRelDevice(row)">关联设备</el-button>
- <el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- <el-pagination
- v-model:current-page="pageNum" v-model:page-size="pageSize" :total="total"
- layout="total, prev, pager, next, sizes" :page-sizes="[10, 20, 50]"
- @change="loadData" style="margin-top: 16px; justify-content: flex-end"
- />
- </el-card>
- <el-dialog title="关联监测设备" v-model="deviceDialogVisible" width="950px" destroy-on-close>
- <el-form label-width="80px">
- <el-form-item label="当前测点">
- <span>{{ currentPoint.pointName || '-' }}</span>
- </el-form-item>
- <el-form-item label="选择设备">
- <el-select
- v-model="bindForm.equipmentId"
- filterable
- clearable
- placeholder="请选择要关联的设备"
- style="width: 100%"
- >
- <el-option
- v-for="item in unboundEquipmentOptions"
- :key="item.equipmentId"
- :label="`${item.equipmentName}(${item.equipmentCode})`"
- :value="item.equipmentId"
- />
- </el-select>
- </el-form-item>
- </el-form>
- <div style="margin-bottom: 12px">
- <el-button type="primary" @click="submitBind">添加关联</el-button>
- </div>
- <el-table :data="deviceList" border stripe v-loading="deviceLoading">
- <el-table-column label="设备编码" prop="equipmentCode" min-width="140" />
- <el-table-column label="设备名称" prop="equipmentName" min-width="180" show-overflow-tooltip />
- <el-table-column label="设备型号" prop="equipmentModel" min-width="120" />
- <el-table-column label="制造商" prop="manufacturer" min-width="140" show-overflow-tooltip />
- <el-table-column label="设备位置" prop="equipmentLocation" min-width="180" show-overflow-tooltip />
- <el-table-column label="操作" align="center" width="100">
- <template #default="{ row: dev }">
- <el-button link type="danger" icon="Close" @click="handleUnbind(dev)">解绑</el-button>
- </template>
- </el-table-column>
- </el-table>
- </el-dialog>
- <el-dialog :title="dialogTitle" v-model="dialogVisible" width="550px" destroy-on-close>
- <el-form :model="formData" ref="formRef" label-width="100px">
- <el-form-item label="测点编码" prop="pointCode">
- <el-input v-model="formData.pointCode" placeholder="请输入测点编码" />
- </el-form-item>
- <el-form-item label="测点名称" prop="pointName">
- <el-input v-model="formData.pointName" placeholder="请输入测点名称" />
- </el-form-item>
- <el-form-item label="测点类型">
- <el-select v-model="formData.pointType" style="width: 100%">
- <el-option v-for="d in pointTypeDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
- </el-select>
- </el-form-item>
- <el-form-item label="所属管网">
- <el-select v-model="formData.networkId" placeholder="请选择管网" clearable style="width: 100%">
- <el-option v-for="n in networkOptions" :key="n.networkId" :label="`${n.networkName}(${n.networkCode})`" :value="n.networkId" />
- </el-select>
- </el-form-item>
- <el-form-item label="位置描述">
- <el-input v-model="formData.location" />
- </el-form-item>
- <el-form-item label="经度">
- <el-input-number v-model="formData.longitude" :precision="10" style="width: 100%" />
- </el-form-item>
- <el-form-item label="纬度">
- <el-input-number v-model="formData.latitude" :precision="10" style="width: 100%" />
- </el-form-item>
- <el-form-item label="状态">
- <el-select v-model="formData.status">
- <el-option v-for="d in pointStatusDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <el-button @click="dialogVisible = false">取消</el-button>
- <el-button type="primary" @click="handleSave">确定</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup>
- import { ref, reactive, computed, onMounted } from 'vue'
- import { ElMessage, ElMessageBox } from 'element-plus'
- import { getPointPage, addPoint, updatePoint, deletePoint, getEquipmentByPoint, savePointRel, deletePointRel, getEquipmentByTopLevelType, getPipeNetworkOptions } from '@/api/pipeNetwork/basic'
- import { getDicts } from '@/api/system/dict/data'
- const loading = ref(false)
- const tableData = ref([])
- const pageNum = ref(1)
- const pageSize = ref(10)
- const total = ref(0)
- const searchForm = reactive({ pointName: '', pointType: '' })
- const dialogVisible = ref(false)
- const dialogTitle = ref('新增')
- const formRef = ref(null)
- const formData = reactive({
- pointId: '', pointCode: '', pointName: '', pointType: '',
- networkId: '', location: '', longitude: null, latitude: null, status: 'ACTIVE'
- })
- const pointTypeDict = ref([])
- const pointStatusDict = ref([])
- const networkOptions = ref([])
- const deviceDialogVisible = ref(false)
- const currentPoint = reactive({ pointId: '', pointName: '' })
- const deviceList = ref([])
- const deviceLoading = ref(false)
- const bindForm = reactive({ equipmentId: '' })
- const equipmentOptions = ref([])
- const unboundEquipmentOptions = computed(() => {
- const boundIds = deviceList.value.map(d => d.equipmentId)
- return equipmentOptions.value.filter(e => !boundIds.includes(e.equipmentId))
- })
- function getDictLabel(dict, value) {
- const item = dict.find(d => d.dictValue === String(value))
- return item ? item.dictLabel : value
- }
- function getNetworkName(networkId) {
- if (!networkId) return '-'
- const n = networkOptions.value.find(o => o.networkId === networkId)
- return n ? n.networkName : networkId
- }
- async function loadDicts() {
- const [typeRes, statusRes] = await Promise.all([
- getDicts('point_type'),
- getDicts('point_status')
- ])
- pointTypeDict.value = typeRes.data
- pointStatusDict.value = statusRes.data
- }
- async function loadData() {
- loading.value = true
- try {
- const res = await getPointPage(pageNum.value, pageSize.value, searchForm)
- tableData.value = res.data.records || []
- total.value = res.data.total || 0
- } catch (e) { console.error(e) } finally { loading.value = false }
- }
- function handleSearch() { pageNum.value = 1; loadData() }
- function handleReset() { Object.assign(searchForm, { pointName: '', pointType: '' }); handleSearch() }
- async function loadNetworkOptions() {
- if (networkOptions.value.length > 0) return
- try { const res = await getPipeNetworkOptions(); networkOptions.value = res.data || [] } catch (e) { console.error(e) }
- }
- function handleAdd() {
- dialogTitle.value = '新增测点'
- Object.assign(formData, { pointId: '', pointCode: '', pointName: '', pointType: '', networkId: '', location: '', longitude: null, latitude: null, status: 'ACTIVE' })
- dialogVisible.value = true
- loadNetworkOptions()
- }
- function handleEdit(row) { dialogTitle.value = '编辑'; Object.assign(formData, row); dialogVisible.value = true; loadNetworkOptions() }
- async function handleSave() {
- try {
- if (formData.pointId) { await updatePoint(formData); ElMessage.success('修改成功') }
- else { await addPoint(formData); ElMessage.success('新增成功') }
- dialogVisible.value = false; loadData()
- } catch (e) { console.error(e) }
- }
- function handleDelete(row) {
- ElMessageBox.confirm('确认删除该测点?', '提示', { type: 'warning' }).then(async () => {
- await deletePoint(row.pointId); ElMessage.success('删除成功'); loadData()
- }).catch(() => {})
- }
- async function handleRelDevice(row) {
- Object.assign(currentPoint, { pointId: row.pointId, pointName: row.pointName })
- bindForm.equipmentId = ''
- deviceDialogVisible.value = true
- if (equipmentOptions.value.length === 0) { await loadEquipmentOptions() }
- loadDeviceList()
- }
- async function loadDeviceList() {
- deviceLoading.value = true
- try {
- const res = await getEquipmentByPoint(currentPoint.pointId)
- const raw = res.data || []
- const eqMap = new Map(equipmentOptions.value.map(e => [e.equipmentId, e]))
- deviceList.value = raw.map(r => {
- const full = eqMap.get(r.equipmentId)
- return {
- relId: r.relId,
- equipmentId: r.equipmentId,
- equipmentName: full ? full.equipmentName : '',
- equipmentCode: full ? full.equipmentCode : '',
- equipmentModel: full ? full.equipmentModel : '',
- manufacturer: full ? full.manufacturer : '',
- equipmentLocation: full ? full.equipmentLocation : ''
- }
- })
- } catch (e) { console.error(e) } finally { deviceLoading.value = false }
- }
- async function loadEquipmentOptions() {
- try {
- const res = await getEquipmentByTopLevelType('燃气')
- equipmentOptions.value = res.data || []
- } catch (e) { console.error(e) }
- }
- async function submitBind() {
- if (!bindForm.equipmentId) { ElMessage.warning('请先选择设备'); return }
- try {
- await savePointRel({ equipmentId: bindForm.equipmentId, pointId: currentPoint.pointId })
- ElMessage.success('关联成功')
- bindForm.equipmentId = ''
- loadDeviceList()
- } catch (e) { console.error(e) }
- }
- function handleUnbind(dev) {
- ElMessageBox.confirm('确认解除该设备关联?', '提示', { type: 'warning' }).then(async () => {
- await deletePointRel(dev.relId)
- ElMessage.success('解绑成功')
- loadDeviceList()
- }).catch(() => {})
- }
- onMounted(async () => { await loadDicts(); loadNetworkOptions(); loadData() })
- </script>
- <style scoped>
- .point-container { padding: 16px; }
- .search-card { margin-bottom: 16px; }
- </style>
|