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.

355 lines
12 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="120px">
<el-form-item :label="t('DataCollection.DeviceModel.attributeCode')" prop="attributeCode">
<el-input
v-model="queryParams.attributeCode"
:placeholder="t('DataCollection.DeviceModel.placeholderAttributeCode')" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.attributeName')" prop="attributeName">
<el-input
v-model="queryParams.attributeName"
:placeholder="t('DataCollection.DeviceModel.placeholderAttributeName')" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item :label="t('DataCollection.DeviceModel.attributeType')" prop="attributeType">
<el-select
v-model="queryParams.attributeType" clearable filterable
:placeholder="t('DataCollection.DeviceModel.placeholderAttributeType')" class="!w-240px">
<el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<!-- <el-form-item label="寄存器地址" prop="address">
<el-input
v-model="queryParams.address"
placeholder="请输入寄存器地址"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item> -->
<!-- <el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item> -->
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> {{ t('DataCollection.DeviceModel.search') }}
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('DataCollection.DeviceModel.reset') }}
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['iot:device-model:create']">
<Icon icon="ep:plus" class="mr-5px" /> {{ t('DataCollection.DeviceModel.create') }}
</el-button>
<el-button type="warning" plain @click="openImport" v-hasPermi="['iot:device-model:import']">
<Icon icon="ep:upload" class="mr-5px" /> {{ t('action.import') }}
</el-button>
<el-button
type="success" plain @click="handleExport" :loading="exportLoading"
v-hasPermi="['iot:device-model:export']">
<Icon icon="ep:download" class="mr-5px" /> {{ t('DataCollection.DeviceModel.export') }}
</el-button>
<el-button type="danger" plain @click="handleBatchDelete" v-hasPermi="['iot:device-model:delete']">
<Icon icon="ep:delete" class="mr-5px" /> {{ t('DataCollection.DeviceModel.batchDelete') }}
</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="ID" align="center" prop="id" /> -->
<el-table-column :label="t('DataCollection.DeviceModel.attributeCode')" align="center" prop="attributeCode" />
<el-table-column :label="t('DataCollection.DeviceModel.attributeName')" align="center" prop="attributeName" />
<el-table-column :label="t('DataCollection.DeviceModel.attributeType')" align="center" prop="typeName" />
<el-table-column :label="t('DataCollection.DeviceModel.dataType')" align="center" prop="dataType" />
<el-table-column :label="t('DataCollection.DeviceModel.address')" align="center" prop="address" />
<el-table-column :label="t('DataCollection.DeviceModel.dataUnit')" align="center" prop="dataUnit" />
<el-table-column :label="t('DataCollection.DeviceModel.ratio')" align="center" prop="ratio" />
<el-table-column :label="t('DataCollection.DeviceModel.remark')" align="center" prop="remark" />
<!-- <el-table-column label="采集设备模型id" align="center" prop="deviceModelId" /> -->
<el-table-column
:label="t('DataCollection.DeviceModel.createTime')" align="center" prop="createTime"
:formatter="dateFormatter" width="180px" />
<el-table-column :label="t('DataCollection.DeviceModel.operate')" align="center" width="150px" fixed="right">
<template #default="scope">
<el-button
link type="primary" @click="openForm('update', scope.row.id)"
v-hasPermi="['iot:device-model:update']">
{{ t('action.edit') }}
</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['iot:device-model:delete']">
{{ t('action.del') }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<DeviceModelAttributeForm ref="formRef" @success="getList" />
<!-- 导入弹窗 -->
<Dialog v-model="importDialogVisible" :title="t('action.import')" width="400">
<el-upload
ref="uploadRef" v-model:file-list="importFileList" :action="importUrl + '?updateSupport=' + updateSupport" :auto-upload="false"
:disabled="importLoading" :headers="uploadHeaders" :limit="1" :on-error="handleImportError"
:on-exceed="handleImportExceed" :on-success="handleImportSuccess" accept=".xlsx, .xls" drag>
<Icon icon="ep:upload" />
<div class="el-upload__text">
将文件拖到此处,或点击上传
</div>
<template #tip>
<div class="el-upload__tip text-center">
<div class="el-upload__tip">
<el-checkbox v-model="updateSupport" />
是否更新已存在的数据
</div>
<span>仅支持 .xlsx, .xls 格式</span>
<el-link
:underline="false" style="font-size: 12px; vertical-align: baseline" type="primary"
@click="importTemplate">
下载导入模板
</el-link>
</div>
</template>
</el-upload>
<template #footer>
<el-button :disabled="importLoading" type="primary" @click="submitImport">{{ t('common.ok') }}</el-button>
<el-button @click="importDialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DeviceModelAttributeApi, DeviceModelAttributeVO } from '@/api/iot/devicemodelattribute'
import DeviceModelAttributeForm from './DeviceModelAttributeForm.vue'
import { DeviceAttributeTypeApi, DeviceAttributeTypeVO } from '@/api/iot/deviceattributetype'
import { getAccessToken, getTenantId } from '@/utils/auth'
const props = defineProps<{
id?: number // id
}>()
const typeList = ref<DeviceAttributeTypeVO[]>([]) // 列表
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const tableRef = ref()
const loading = ref(false) // 列表的加载中
const list = ref<DeviceModelAttributeVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
id: undefined as unknown,
attributeCode: undefined,
attributeName: undefined,
attributeType: undefined,
dataType: undefined,
address: undefined,
dataUnit: undefined,
ratio: undefined,
remark: undefined,
deviceModelId: undefined,
createTime: [],
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const importDialogVisible = ref(false)
const importLoading = ref(false)
const uploadRef = ref()
const importUrl =
import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/iot/device-model-attribute/import'
const uploadHeaders = ref()
const importFileList = ref([])
const updateSupport = ref(0)
const selectedIds = ref<number[]>([])
const handleSelectionChange = (rows: any[]) => {
selectedIds.value = rows?.map((row) => row.id).filter((id) => id !== undefined) ?? []
}
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.id,
(val: number) => {
if (!val) {
return
}
queryParams.id = val
handleQuery()
},
{ immediate: true, deep: true }
)
/** 查询列表 */
async function getList() {
loading.value = true
try {
const data = await DeviceModelAttributeApi.getDeviceModelAttributePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
function handleQuery() {
if (!props.id) {
return
}
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
if (!props.id) {
return
}
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.id) {
message.error('请选择一个采集设备模型')
return
}
formRef.value.open(type, id, props.id)
}
const openImport = () => {
if (!props.id) {
message.error('请选择一个采集设备模型')
return
}
importDialogVisible.value = true
importLoading.value = false
importFileList.value = []
updateSupport.value = 0
}
/** 删除按钮操作 */
const buildIdsParam = (ids: number | number[]) => {
return Array.isArray(ids) ? ids.join(',') : String(ids)
}
const handleDelete = async (ids: number | number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await DeviceModelAttributeApi.deleteDeviceModelAttribute(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
}
}
const submitImport = async () => {
if (importFileList.value.length === 0) {
message.error('请选择导入文件')
return
}
uploadHeaders.value = {
Authorization: 'Bearer ' + getAccessToken(),
tenantId: getTenantId(),
}
importLoading.value = true
uploadRef.value?.submit()
}
const handleImportSuccess = (response: any) => {
if (!response || response.code !== 0) {
message.error(response?.msg || '导入失败')
importLoading.value = false
return
}
message.success('导入成功')
importLoading.value = false
importDialogVisible.value = false
getList()
}
const handleImportError = () => {
message.error('导入失败')
importLoading.value = false
}
const handleImportExceed = () => {
message.error('只能上传一个文件')
}
const importTemplate = async () => {
const res = await DeviceModelAttributeApi.importDeviceModelAttributeTemplate()
download.excel(res, '采集设备模型-点位导入模板.xls')
}
/** 初始化 **/
onMounted(async () => {
typeList.value = await DeviceAttributeTypeApi.getDeviceAttributeTypeList()
// typeList.value = JSON.parse(JSON.stringify(await DeviceAttributeTypeApi.getDeviceAttributeTypePage(queryParams))).list
})
</script>