You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
8.3 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
<el-form-item label="点位编码" prop="attributeCode">
<el-input
v-model="queryParams.attributeCode" placeholder="请输入点位编码" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="点位名称" prop="attributeName">
<el-input
v-model="queryParams.attributeName" placeholder="请输入点位名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="点位类型" prop="attributeType">
<el-select v-model="queryParams.attributeType" clearable filterable placeholder="请选择" class="!w-240px">
<el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.name" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['iot:device:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['iot:device:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="handleBatchDelete" v-hasPermi="['iot:device:delete']">
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table
ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column label="点位编码" align="left" prop="attributeCode" width="150px" />
<el-table-column label="点位名称" align="left" prop="attributeName" width="150px" />
<el-table-column label="点位类型" align="center" prop="attributeType" width="120px">
<template #default="scope">
{{ getAttributeTypeLabel(scope.row.attributeType) }}
</template>
</el-table-column>
<el-table-column label="数据类型" align="center" prop="dataType" width="120px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_DATA_TYPE" :value="scope.row.dataType" />
</template>
</el-table-column>
<el-table-column label="寄存器地址" align="center" prop="address" min-width="140px" />
<el-table-column label="最新值" align="center" prop="latestValue" min-width="120px">
<template #default="scope">
{{ scope.row.latestValue ?? '-' }}
</template>
</el-table-column>
<el-table-column label="单位" align="center" prop="dataUnit" width="80px" />
<el-table-column label="倍率" align="center" prop="ratio" width="80px" />
<el-table-column
label="最新采集时间" align="center" prop="latestCollectTime" :formatter="dateFormatter"
width="170px" />
<el-table-column label="顺序" align="center" prop="sort" width="80px">
<template #default="scope">
{{ scope.row.sort ?? '-' }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="160px" />
<el-table-column label="操作" align="center" width="150px" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['iot:device:update']">
编辑
</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['iot:device:delete']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<DeviceAttributeForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DeviceApi } from '@/api/iot/device'
import { DeviceModelAttributeApi } from '@/api/iot/devicemodelattribute'
import DeviceAttributeForm from './DeviceAttributeForm.vue'
import { DeviceAttributeTypeApi, DeviceAttributeTypeVO } from '@/api/iot/deviceattributetype'
const { t } = useI18n() //
const message = useMessage() //
const tableRef = ref()
const props = defineProps<{
deviceId?: number // id
}>()
const typeList = ref<DeviceAttributeTypeVO[]>([])
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceId: undefined as unknown,
attributeCode: undefined,
attributeName: undefined,
attributeType: undefined
})
const queryFormRef = ref()
const exportLoading = ref(false)
const selectedIds = ref<number[]>([])
const handleSelectionChange = (rows: any[]) => {
selectedIds.value = rows?.map((row) => row.id).filter((id) => id !== undefined) ?? []
}
const getAttributeTypeLabel = (attributeType: any) => {
if (attributeType === undefined || attributeType === null || attributeType === '') {
return ''
}
const matched = typeList.value.find(
(item) => item.name === attributeType || item.id === attributeType || item.code === attributeType
)
return matched?.name ?? String(attributeType)
}
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.deviceId,
(val: number) => {
if (!val) {
return
}
queryParams.deviceId = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
async function getList() {
loading.value = true
try {
const data = await DeviceApi.getDeviceAttributePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
function handleQuery() {
if (!props.deviceId) {
return
}
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
if (!props.deviceId) {
return
}
queryFormRef.value?.resetFields()
queryParams.attributeCode = undefined
queryParams.attributeName = undefined
queryParams.attributeType = undefined
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.deviceId) {
message.error('请选择一个物联设备')
return
}
formRef.value.open(type, id, props.deviceId)
}
/** 删除按钮操作 */
const buildIdsParam = (ids: number | number[]) => {
return Array.isArray(ids) ? ids.join(',') : String(ids)
}
const handleDelete = async (ids: number | number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await DeviceApi.deleteDeviceAttribute(buildIdsParam(ids))
message.success(t('common.delSuccess'))
selectedIds.value = []
tableRef.value?.clearSelection?.()
// 刷新列表
await getList()
} catch { }
}
const handleBatchDelete = async () => {
if (!selectedIds.value.length) {
message.error('请选择需要删除的数据')
return
}
await handleDelete(selectedIds.value)
}
/** 导出按钮操作 */
const handleExport = async () => {
if (!selectedIds.value.length) {
message.error('请选择需要导出的数据')
return
}
try {
await message.exportConfirm()
exportLoading.value = true
const data = await DeviceModelAttributeApi.exportDeviceModelAttribute({ ids: selectedIds.value.join(',') })
download.excel(data, '采集设备-点位管理.xls')
} catch {
} finally {
exportLoading.value = false
}
}
onMounted(async () => {
try {
const data = await DeviceAttributeTypeApi.getDeviceAttributeTypePage({ pageNo: 1, pageSize: 10 })
typeList.value = data?.list ?? []
} catch {
typeList.value = []
}
})
</script>