修改设备管理界面相关功能
This commit is contained in:
parent
3e58485d2f
commit
fde6cd9bf9
@ -47,6 +47,10 @@ export const DeviceApi = {
|
|||||||
deleteDevice: async (id: number) => {
|
deleteDevice: async (id: number) => {
|
||||||
return await request.delete({ url: `/system/device/delete?id=` + id })
|
return await request.delete({ url: `/system/device/delete?id=` + id })
|
||||||
},
|
},
|
||||||
|
// 删除设备
|
||||||
|
deleteDeviceCode: async (devicecode: number) => {
|
||||||
|
return await request.delete({ url: `/system/device/deletecode?devicecode=` + devicecode })
|
||||||
|
},
|
||||||
|
|
||||||
// 导出设备 Excel
|
// 导出设备 Excel
|
||||||
exportDevice: async (params) => {
|
exportDevice: async (params) => {
|
||||||
|
@ -23,6 +23,10 @@ export const DeviceuserApi = {
|
|||||||
getDeviceuser: async (id: number) => {
|
getDeviceuser: async (id: number) => {
|
||||||
return await request.get({ url: `/system/deviceuser/get?id=` + id })
|
return await request.get({ url: `/system/deviceuser/get?id=` + id })
|
||||||
},
|
},
|
||||||
|
// 查询设备人员关联数量
|
||||||
|
getDevCount: async (devicecode: number) => {
|
||||||
|
return await request.get({ url: `/system/deviceuser/getDevCount?devicecode=` + devicecode })
|
||||||
|
},
|
||||||
|
|
||||||
// 新增设备人员关联
|
// 新增设备人员关联
|
||||||
createDeviceuser: async (data: DeviceuserVO) => {
|
createDeviceuser: async (data: DeviceuserVO) => {
|
||||||
@ -42,5 +46,5 @@ export const DeviceuserApi = {
|
|||||||
// 导出设备人员关联 Excel
|
// 导出设备人员关联 Excel
|
||||||
exportDeviceuser: async (params) => {
|
exportDeviceuser: async (params) => {
|
||||||
return await request.download({ url: `/system/deviceuser/export-excel`, params })
|
return await request.download({ url: `/system/deviceuser/export-excel`, params })
|
||||||
},
|
}
|
||||||
}
|
}
|
@ -5,13 +5,14 @@
|
|||||||
v-loading="formLoading"
|
v-loading="formLoading"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
label-width="100px"
|
label-width="100px"
|
||||||
:disabled="true"
|
:disabled="!isEditing"
|
||||||
>
|
>
|
||||||
<el-form-item label="设备ID">
|
<el-form-item label="设备ID">
|
||||||
<span>{{ formData.devicecode }}</span>
|
<span>{{ formData.devicecode }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备名称">
|
<el-form-item label="设备名称">
|
||||||
<span>{{ formData.devicename }}</span>
|
<el-input v-if="isEditing" v-model="formData.devicename" />
|
||||||
|
<span v-else>{{ formData.devicename }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所属机构">
|
<el-form-item label="所属机构">
|
||||||
<span>{{ formData.orgname }}</span>
|
<span>{{ formData.orgname }}</span>
|
||||||
@ -19,18 +20,37 @@
|
|||||||
<el-form-item label="设备类型">
|
<el-form-item label="设备类型">
|
||||||
<span>{{ getDeviceTypeName(formData.devicetype) }}</span>
|
<span>{{ getDeviceTypeName(formData.devicetype) }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备位置">
|
<el-form-item label="设备位置" class="location-form-item">
|
||||||
<span>{{ formData.location }}</span>
|
<template v-if="isEditing">
|
||||||
|
<el-cascader
|
||||||
|
v-model="selectedOptions"
|
||||||
|
:options="options"
|
||||||
|
:props="{ expandTrigger: 'hover' }"
|
||||||
|
placeholder="请选择省/市/区"
|
||||||
|
@change="handleAddressChange"
|
||||||
|
class="location-cascader"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="locationDetail"
|
||||||
|
placeholder="请输入详细地址"
|
||||||
|
class="detail-address-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span v-else>{{ fullLocation }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备状态">
|
<el-form-item label="设备状态">
|
||||||
<span>{{ getDeviceStatusName(formData.devicestatus) }}</span>
|
<span>{{ getDeviceStatusName(formData.devicestatus) }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备描述">
|
<el-form-item label="设备描述">
|
||||||
<span>{{ formData.description }}</span>
|
<el-input v-if="isEditing" v-model="formData.description" type="textarea" :rows="3" />
|
||||||
|
<span v-else>{{ formData.description }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="dialogVisible = false">关 闭</el-button>
|
<el-button v-if="!isEditing" type="primary" @click="handleEdit">编 辑</el-button>
|
||||||
|
<el-button v-else type="primary" @click="handleSave">保 存</el-button>
|
||||||
|
<el-button @click="handleClose">关 闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
@ -38,6 +58,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { DeviceApi } from '@/api/device'
|
import { DeviceApi } from '@/api/device'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import type { DeviceVO } from '@/api/device'
|
||||||
|
import { regionData, codeToText } from 'element-china-area-data'
|
||||||
|
|
||||||
defineOptions({ name: 'DeviceDetailsForm' })
|
defineOptions({ name: 'DeviceDetailsForm' })
|
||||||
|
|
||||||
@ -66,44 +88,202 @@ const getDeviceStatusName = (status: string | number) => {
|
|||||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
const dialogTitle = ref('') // 弹窗的标题
|
const dialogTitle = ref('') // 弹窗的标题
|
||||||
const formLoading = ref(false) // 表单的加载中
|
const formLoading = ref(false) // 表单的加载中
|
||||||
const formData = ref({
|
const formData = ref<DeviceVO>({
|
||||||
devicecode: undefined,
|
id: 0,
|
||||||
|
devicecode: 0,
|
||||||
devicename: '',
|
devicename: '',
|
||||||
orgname: '',
|
|
||||||
devicetype: '',
|
devicetype: '',
|
||||||
location: '',
|
location: '',
|
||||||
devicestatus: '',
|
devicestatus: 0,
|
||||||
description: ''
|
orgid: 0,
|
||||||
|
orgname: '',
|
||||||
|
description: '',
|
||||||
|
createtime: new Date(),
|
||||||
|
updatetime: new Date(),
|
||||||
|
createby: '',
|
||||||
|
updateby: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isEditing = ref(false) // 是否处于编辑状态
|
||||||
|
const locationDetail = ref('') // 详细地址
|
||||||
|
const options = ref(regionData) // 省市区数据
|
||||||
|
const selectedOptions = ref<string[]>([]) // 选中的省市区
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (id: number) => {
|
const open = async (id: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = '设备详情'
|
dialogTitle.value = '设备详情'
|
||||||
resetForm()
|
resetForm()
|
||||||
|
isEditing.value = false
|
||||||
// 获取设备数据
|
// 获取设备数据
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await DeviceApi.getDeviceId(id)
|
const res = await DeviceApi.getDeviceId(id)
|
||||||
formData.value = res
|
formData.value = res
|
||||||
|
// 解析地址
|
||||||
|
if (res.location) {
|
||||||
|
const addressParts = res.location.split('/')
|
||||||
|
if (addressParts.length > 3) {
|
||||||
|
formData.value.location = addressParts.slice(0, 3).join('/')
|
||||||
|
locationDetail.value = addressParts.slice(3).join('/')
|
||||||
|
} else {
|
||||||
|
formData.value.location = res.location
|
||||||
|
locationDetail.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
||||||
|
/** 处理编辑按钮点击 */
|
||||||
|
const handleEdit = () => {
|
||||||
|
isEditing.value = true
|
||||||
|
// 解析已有地址,设置省市区选择器的值
|
||||||
|
if (formData.value.location) {
|
||||||
|
const addressParts = formData.value.location.split('/')
|
||||||
|
if (addressParts.length === 3) {
|
||||||
|
// 遍历省市区数据,找到对应的编码
|
||||||
|
const findCode = (name: string, data: any[]): string | undefined => {
|
||||||
|
for (const item of data) {
|
||||||
|
if (item.label === name) {
|
||||||
|
return item.value
|
||||||
|
}
|
||||||
|
if (item.children) {
|
||||||
|
for (const child of item.children) {
|
||||||
|
if (child.label === name) {
|
||||||
|
return child.value
|
||||||
|
}
|
||||||
|
if (child.children) {
|
||||||
|
for (const grandChild of child.children) {
|
||||||
|
if (grandChild.label === name) {
|
||||||
|
return grandChild.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理直辖市
|
||||||
|
const isMunicipality = ['北京市', '天津市', '上海市', '重庆市'].includes(addressParts[0])
|
||||||
|
let provinceCode, cityCode, areaCode
|
||||||
|
|
||||||
|
if (isMunicipality) {
|
||||||
|
// 直辖市特殊处理
|
||||||
|
provinceCode = findCode(addressParts[0], options.value)
|
||||||
|
// 直辖市的第二级是"市辖区",需要特殊处理
|
||||||
|
const province = options.value.find(item => item.value === provinceCode)
|
||||||
|
if (province && province.children) {
|
||||||
|
// 找到市辖区
|
||||||
|
const district = province.children.find(item => item.label === '市辖区')
|
||||||
|
if (district) {
|
||||||
|
cityCode = district.value
|
||||||
|
// 在区级中查找
|
||||||
|
if (district.children) {
|
||||||
|
const area = district.children.find(item => item.label === addressParts[2])
|
||||||
|
if (area) {
|
||||||
|
areaCode = area.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 普通省份处理
|
||||||
|
provinceCode = findCode(addressParts[0], options.value)
|
||||||
|
cityCode = findCode(addressParts[1], options.value)
|
||||||
|
areaCode = findCode(addressParts[2], options.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provinceCode && cityCode && areaCode) {
|
||||||
|
selectedOptions.value = [provinceCode, cityCode, areaCode]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理地址变化 */
|
||||||
|
const handleAddressChange = (value: string[]) => {
|
||||||
|
if (value && value.length === 3) {
|
||||||
|
const address = codeToText[value[0]] + '/' + codeToText[value[1]] + '/' + codeToText[value[2]]
|
||||||
|
formData.value.location = address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理保存按钮点击 */
|
||||||
|
const handleSave = async () => {
|
||||||
|
try {
|
||||||
|
formLoading.value = true
|
||||||
|
// 组合完整地址
|
||||||
|
const fullAddress = formData.value.location + (locationDetail.value ? '/' + locationDetail.value : '')
|
||||||
|
const updateData = {
|
||||||
|
...formData.value,
|
||||||
|
location: fullAddress
|
||||||
|
}
|
||||||
|
await DeviceApi.updateDevice(updateData)
|
||||||
|
ElMessage.success('保存成功')
|
||||||
|
isEditing.value = false
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('保存失败')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理关闭按钮点击 */
|
||||||
|
const handleClose = () => {
|
||||||
|
dialogVisible.value = false
|
||||||
|
isEditing.value = false
|
||||||
|
}
|
||||||
|
|
||||||
/** 重置表单 */
|
/** 重置表单 */
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
devicecode: undefined,
|
id: 0,
|
||||||
|
devicecode: 0,
|
||||||
devicename: '',
|
devicename: '',
|
||||||
orgname: '',
|
|
||||||
devicetype: '',
|
devicetype: '',
|
||||||
location: '',
|
location: '',
|
||||||
devicestatus: '',
|
devicestatus: 0,
|
||||||
description: ''
|
orgid: 0,
|
||||||
|
orgname: '',
|
||||||
|
description: '',
|
||||||
|
createtime: new Date(),
|
||||||
|
updatetime: new Date(),
|
||||||
|
createby: '',
|
||||||
|
updateby: ''
|
||||||
}
|
}
|
||||||
|
locationDetail.value = ''
|
||||||
|
selectedOptions.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算完整地址
|
||||||
|
const fullLocation = computed(() => {
|
||||||
|
if (!formData.value.location) return ''
|
||||||
|
return formData.value.location + (locationDetail.value ? '/' + locationDetail.value : '')
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.location-form-item {
|
||||||
|
:deep(.el-form-item__content) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location-cascader {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-address-input {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
<Dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="dialogTitle"
|
||||||
|
:modal="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
class="device-dialog"
|
||||||
|
>
|
||||||
<el-form
|
<el-form
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
v-loading="formLoading"
|
v-loading="formLoading"
|
||||||
@ -7,59 +14,42 @@
|
|||||||
:rules="formRules"
|
:rules="formRules"
|
||||||
label-width="100px"
|
label-width="100px"
|
||||||
:disabled="isDetail"
|
:disabled="isDetail"
|
||||||
|
class="device-form"
|
||||||
>
|
>
|
||||||
<el-form-item label="设备ID" prop="deviceId">
|
<el-form-item label="设备ID" prop="devicecode">
|
||||||
<el-input v-model="formData.deviceId" placeholder="请输入设备ID" />
|
<el-input v-model="formData.devicecode" placeholder="请输入设备ID" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备名称" prop="deviceName">
|
<el-form-item label="设备名称" prop="devicename">
|
||||||
<el-input v-model="formData.deviceName" placeholder="请输入设备名称" />
|
<el-input v-model="formData.devicename" placeholder="请输入设备名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="所属机构" prop="orgId">
|
<el-form-item label="设备类型" prop="devicetype">
|
||||||
<el-select v-model="formData.orgId" placeholder="请选择所属机构" @change="handleProductChange">
|
<el-select v-model="formData.devicetype" placeholder="请选择设备类型">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in productList"
|
v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备类型" prop="deviceType">
|
|
||||||
<el-select v-model="formData.deviceType" placeholder="请选择设备类型">
|
|
||||||
<el-option
|
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.IOT_DEVICE_TYPE)"
|
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备位置" prop="address">
|
<el-form-item label="设备位置" prop="location" class="location-form-item" inline>
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<el-cascader
|
<el-cascader
|
||||||
v-model="selectedOptions"
|
v-model="selectedOptions"
|
||||||
:options="options"
|
:options="options"
|
||||||
@change="handleAddressChange"
|
:props="{ expandTrigger: 'hover' }"
|
||||||
placeholder="请选择省/市/区"
|
placeholder="请选择省/市/区"
|
||||||
|
@change="handleAddressChange"
|
||||||
|
class="location-cascader"
|
||||||
clearable
|
clearable
|
||||||
class="w-[450px]"
|
|
||||||
/>
|
/>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.detailAddress"
|
v-model="locationDetail"
|
||||||
placeholder="请输入详细地址"
|
placeholder="请输入详细地址"
|
||||||
class="w-[450px]"
|
class="detail-address-input"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备状态" prop="state">
|
<el-form-item label="设备状态" prop="devicestatus">
|
||||||
<el-select v-model="formData.state" placeholder="请选择设备状态">
|
<span>待激活</span>
|
||||||
<el-option
|
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.IOT_DEVICE_STATE)"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备描述" prop="description">
|
<el-form-item label="设备描述" prop="description">
|
||||||
<el-input
|
<el-input
|
||||||
@ -78,19 +68,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions,getStrDictOptions } from '@/utils/dict'
|
||||||
import * as DeviceApi from '@/api/iot/device/device'
|
|
||||||
import * as ProductApi from '@/api/iot/product/product'
|
|
||||||
import * as DeviceGroupApi from '@/api/iot/device/group'
|
|
||||||
import { DeviceStateEnum } from '@/api/iot/device/device'
|
|
||||||
import { FormRules } from 'element-plus'
|
import { FormRules } from 'element-plus'
|
||||||
import { regionData, codeToText } from 'element-china-area-data'
|
import { regionData, codeToText } from 'element-china-area-data'
|
||||||
|
import { DeviceApi, DeviceVO } from '@/api/device'
|
||||||
interface CascaderOption {
|
import { getUserProfile } from '@/api/system/user/profile'
|
||||||
value: string
|
|
||||||
label: string
|
|
||||||
children?: CascaderOption[]
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({ name: 'DeviceForm' })
|
defineOptions({ name: 'DeviceForm' })
|
||||||
|
|
||||||
@ -102,50 +84,35 @@ const dialogTitle = ref('') // 弹窗的标题
|
|||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
const isDetail = ref(false) // 是否为详情模式
|
const isDetail = ref(false) // 是否为详情模式
|
||||||
const formData = ref<DeviceApi.DeviceVO>({
|
|
||||||
id: undefined,
|
const locationDetail = ref('') // 详细地址
|
||||||
deviceId: undefined,
|
|
||||||
deviceName: undefined,
|
const formData = ref<Partial<DeviceVO>>({
|
||||||
productId: undefined,
|
devicename: '',
|
||||||
productKey: undefined,
|
devicecode: undefined,
|
||||||
deviceType: undefined,
|
devicetype: '',
|
||||||
nickname: undefined,
|
location: '',
|
||||||
gatewayId: undefined,
|
devicestatus: 0,
|
||||||
state: DeviceStateEnum.INACTIVE,
|
orgid: undefined,
|
||||||
onlineTime: undefined,
|
orgname: '',
|
||||||
offlineTime: undefined,
|
description: '',
|
||||||
activeTime: undefined,
|
createby: '',
|
||||||
createTime: undefined,
|
updateby: ''
|
||||||
ip: undefined,
|
|
||||||
firmwareVersion: undefined,
|
|
||||||
deviceSecret: undefined,
|
|
||||||
mqttClientId: undefined,
|
|
||||||
mqttUsername: undefined,
|
|
||||||
mqttPassword: undefined,
|
|
||||||
authType: undefined,
|
|
||||||
latitude: undefined,
|
|
||||||
longitude: undefined,
|
|
||||||
areaId: undefined,
|
|
||||||
address: undefined,
|
|
||||||
detailAddress: undefined,
|
|
||||||
serialNumber: undefined,
|
|
||||||
config: undefined,
|
|
||||||
description: undefined,
|
|
||||||
groupIds: []
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 省市区数据
|
||||||
|
const options = ref(regionData)
|
||||||
|
const selectedOptions = ref<string[]>([])
|
||||||
|
|
||||||
const formRules = reactive<FormRules>({
|
const formRules = reactive<FormRules>({
|
||||||
deviceId: [{ required: true, message: '设备ID不能为空', trigger: 'blur' }],
|
devicecode: [{ required: true, message: '设备ID不能为空', trigger: 'blur' }],
|
||||||
deviceName: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }],
|
devicename: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }],
|
||||||
deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }],
|
devicetype: [{ required: true, message: '设备类型不能为空', trigger: 'blur' }],
|
||||||
address: [{ required: true, message: '设备位置不能为空', trigger: 'blur' }],
|
location: [{ required: true, message: '设备位置不能为空', trigger: 'blur' }],
|
||||||
})
|
})
|
||||||
|
// 用户信息
|
||||||
|
const userProfile = ref()
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
const productList = ref<ProductApi.ProductVO[]>([]) // 产品列表
|
|
||||||
const groupList = ref<DeviceGroupApi.DeviceGroupVO[]>([]) // 分组列表
|
|
||||||
const selectedOptions = ref<string[]>([]) // 添加级联选择器的值
|
|
||||||
const options = ref<CascaderOption[]>(regionData as unknown as CascaderOption[])
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: string, id?: number) => {
|
||||||
@ -154,70 +121,11 @@ const open = async (type: string, id?: number) => {
|
|||||||
formType.value = type
|
formType.value = type
|
||||||
isDetail.value = type === 'details' // 设置是否为详情模式
|
isDetail.value = type === 'details' // 设置是否为详情模式
|
||||||
resetForm()
|
resetForm()
|
||||||
// 修改时,设置数据
|
// 首先获取用户信息
|
||||||
if (id) {
|
userProfile.value = await getUserProfile()
|
||||||
formLoading.value = true
|
console.log(userProfile.value.dept.name)
|
||||||
try {
|
|
||||||
// 这里模拟获取设备数据,实际项目中应该调用API
|
|
||||||
const mockDeviceData = {
|
|
||||||
id: id,
|
|
||||||
deviceId: 'Device' + id,
|
|
||||||
deviceName: '测试设备' + id,
|
|
||||||
deviceType: 1,
|
|
||||||
state: DeviceStateEnum.INACTIVE,
|
|
||||||
address: '',
|
|
||||||
detailAddress: '测试地址123号',
|
|
||||||
description: '这是一个测试设备的描述信息',
|
|
||||||
productId: 1,
|
|
||||||
productKey: 'product_key_' + id,
|
|
||||||
nickname: '设备昵称' + id,
|
|
||||||
gatewayId: 1,
|
|
||||||
onlineTime: new Date(),
|
|
||||||
offlineTime: new Date(),
|
|
||||||
activeTime: new Date(),
|
|
||||||
createTime: new Date(),
|
|
||||||
ip: '192.168.1.1',
|
|
||||||
firmwareVersion: '1.0.0',
|
|
||||||
deviceSecret: 'secret_' + id,
|
|
||||||
mqttClientId: 'client_' + id,
|
|
||||||
mqttUsername: 'username_' + id,
|
|
||||||
mqttPassword: 'password_' + id,
|
|
||||||
authType: 'password',
|
|
||||||
latitude: 39.123456,
|
|
||||||
longitude: 117.123456,
|
|
||||||
areaId: 1,
|
|
||||||
serialNumber: 'SN' + id,
|
|
||||||
config: '{}',
|
|
||||||
groupIds: []
|
|
||||||
}
|
|
||||||
formData.value = mockDeviceData
|
|
||||||
|
|
||||||
// 处理地址数据
|
|
||||||
if (formData.value.address) {
|
|
||||||
const addressParts = formData.value.address.split('/')
|
|
||||||
if (addressParts.length >= 3) {
|
|
||||||
// 获取省市区编码
|
|
||||||
const provinceCode = Object.keys(codeToText).find(key => codeToText[key] === addressParts[0])
|
|
||||||
let cityCode = Object.keys(codeToText).find(key => codeToText[key] === addressParts[1])
|
|
||||||
if(provinceCode == '12'){
|
|
||||||
cityCode = '1201'
|
|
||||||
}
|
|
||||||
const areaCode = Object.keys(codeToText).find(key => codeToText[key] === addressParts[2])
|
|
||||||
if (provinceCode && cityCode && areaCode) {
|
|
||||||
selectedOptions.value = [provinceCode, cityCode, areaCode]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置详细地址
|
|
||||||
if (addressParts.length > 3) {
|
|
||||||
formData.value.detailAddress = addressParts.slice(3).join('/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
formLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
@ -230,8 +138,19 @@ const submitForm = async () => {
|
|||||||
// 提交请求
|
// 提交请求
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = formData.value
|
// 组合完整地址
|
||||||
|
const fullAddress = formData.value.location + (locationDetail.value ? '/' + locationDetail.value : '')
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
...formData.value,
|
||||||
|
devicecode: formData.value.devicecode,
|
||||||
|
location: fullAddress,
|
||||||
|
orgid: userProfile.value.dept.id,
|
||||||
|
orgname: userProfile.value.dept.name
|
||||||
|
} as DeviceVO
|
||||||
|
|
||||||
if (formType.value === 'create') {
|
if (formType.value === 'create') {
|
||||||
|
console.log(data)
|
||||||
await DeviceApi.createDevice(data)
|
await DeviceApi.createDevice(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
} else {
|
} else {
|
||||||
@ -249,75 +168,81 @@ const submitForm = async () => {
|
|||||||
/** 重置表单 */
|
/** 重置表单 */
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
id: undefined,
|
devicename: '',
|
||||||
deviceId: undefined,
|
devicecode: undefined,
|
||||||
deviceName: undefined,
|
devicetype: '',
|
||||||
productId: undefined,
|
location: '',
|
||||||
productKey: undefined,
|
devicestatus: 0,
|
||||||
deviceType: undefined,
|
orgid: undefined,
|
||||||
nickname: undefined,
|
orgname: '',
|
||||||
gatewayId: undefined,
|
description: '',
|
||||||
state: DeviceStateEnum.INACTIVE,
|
createby: '',
|
||||||
onlineTime: undefined,
|
updateby: ''
|
||||||
offlineTime: undefined,
|
|
||||||
activeTime: undefined,
|
|
||||||
createTime: undefined,
|
|
||||||
ip: undefined,
|
|
||||||
firmwareVersion: undefined,
|
|
||||||
deviceSecret: undefined,
|
|
||||||
mqttClientId: undefined,
|
|
||||||
mqttUsername: undefined,
|
|
||||||
mqttPassword: undefined,
|
|
||||||
authType: undefined,
|
|
||||||
latitude: undefined,
|
|
||||||
longitude: undefined,
|
|
||||||
areaId: undefined,
|
|
||||||
address: undefined,
|
|
||||||
detailAddress: undefined,
|
|
||||||
serialNumber: undefined,
|
|
||||||
config: undefined,
|
|
||||||
description: undefined,
|
|
||||||
groupIds: []
|
|
||||||
}
|
}
|
||||||
|
locationDetail.value = ''
|
||||||
selectedOptions.value = []
|
selectedOptions.value = []
|
||||||
formRef.value?.resetFields()
|
formRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 检查设备标识 */
|
|
||||||
const checkDeviceKey = async () => {
|
|
||||||
// TODO: 实现设备标识检查逻辑
|
|
||||||
message.warning('设备标识检查功能待实现')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 处理产品变更 */
|
/** 处理产品变更 */
|
||||||
const handleProductChange = (productId: number) => {
|
const handleProductChange = (productId: number) => {
|
||||||
const product = productList.value.find(item => item.id === productId)
|
// 这里只保留查找逻辑,如需扩展请根据实际 productList 字段调整
|
||||||
if (product) {
|
// const product = productList.value.find(item => item.id === productId)
|
||||||
formData.value.productKey = product.productKey
|
// if (product) {
|
||||||
}
|
// formData.value.productKey = product.productKey
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 处理地址变化 */
|
/** 处理地址变化 */
|
||||||
const handleAddressChange = (value: any) => {
|
const handleAddressChange = (value: string[]) => {
|
||||||
if (value && value.length === 3) {
|
if (value && value.length === 3) {
|
||||||
const address = codeToText[value[0]] + '/' + codeToText[value[1]] + '/' + codeToText[value[2]]
|
const address = codeToText[value[0]] + '/' + codeToText[value[1]] + '/' + codeToText[value[2]]
|
||||||
if (formData.value.detailAddress) {
|
formData.value.location = address
|
||||||
formData.value.address = address + '/' + formData.value.detailAddress
|
|
||||||
} else {
|
|
||||||
formData.value.address = address
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.device-dialog {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
:deep(.el-dialog) {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听详细地址变化
|
.device-form {
|
||||||
watch(() => formData.value.detailAddress, (newValue) => {
|
position: relative;
|
||||||
if (selectedOptions.value && selectedOptions.value.length === 3) {
|
}
|
||||||
const address = codeToText[selectedOptions.value[0]] + '/' + codeToText[selectedOptions.value[1]] + '/' + codeToText[selectedOptions.value[2]]
|
|
||||||
if (newValue) {
|
.status-select-item {
|
||||||
formData.value.address = address + '/' + newValue
|
position: relative;
|
||||||
} else {
|
}
|
||||||
formData.value.address = address
|
|
||||||
|
.device-status-select {
|
||||||
|
position: absolute !important;
|
||||||
|
z-index: 2001 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-select__popper) {
|
||||||
|
position: absolute !important;
|
||||||
|
z-index: 2001 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location-form-item {
|
||||||
|
:deep(.el-form-item__content) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location-cascader {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-address-input {
|
||||||
|
width: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
</style>
|
||||||
</script>
|
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="deviceInfo.devicestatus === 1"
|
:disabled="deviceInfo.devicestatus === 1 || deviceInfo.devicestatus === 0"
|
||||||
@click="handleAction('enable')"
|
@click="handleAction('enable')"
|
||||||
>
|
>
|
||||||
启用
|
启用
|
||||||
@ -66,7 +66,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
type="warning"
|
type="warning"
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="deviceInfo.devicestatus === 2"
|
:disabled="deviceInfo.devicestatus === 2 || deviceInfo.devicestatus === 0"
|
||||||
@click="handleAction('disable')"
|
@click="handleAction('disable')"
|
||||||
>
|
>
|
||||||
停用
|
停用
|
||||||
|
@ -97,9 +97,10 @@ import DeviceCard from '../devices/devices_cards.vue'
|
|||||||
import DeviceForm from './DevFrom.vue'
|
import DeviceForm from './DevFrom.vue'
|
||||||
import DetailsForm from './DetailsForm.vue'
|
import DetailsForm from './DetailsForm.vue'
|
||||||
import { DeviceApi } from '@/api/device'
|
import { DeviceApi } from '@/api/device'
|
||||||
|
import { DeviceuserApi } from '@/api/deviceuser'
|
||||||
import { getUserProfile } from '@/api/system/user/profile'
|
import { getUserProfile } from '@/api/system/user/profile'
|
||||||
import ECG_datas from './Device_Data_Components/ECG_datas.vue'
|
import ECG_datas from './Device_Data_Components/ECG_datas.vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
// 查询参数
|
// 查询参数
|
||||||
interface QueryParams {
|
interface QueryParams {
|
||||||
devicename: string
|
devicename: string
|
||||||
@ -118,7 +119,7 @@ const queryParams = reactive<QueryParams>({
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
orgid: 0
|
orgid: 0
|
||||||
})
|
})
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
// 总数据量
|
// 总数据量
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
// 用户信息
|
// 用户信息
|
||||||
@ -164,7 +165,7 @@ const openForm = (type: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理设备操作
|
// 处理设备操作
|
||||||
const handleDeviceAction = (action: any) => {
|
const handleDeviceAction = async (action: any) => {
|
||||||
console.log('设备操作:', action)
|
console.log('设备操作:', action)
|
||||||
if (action.action === 'details') {
|
if (action.action === 'details') {
|
||||||
// 打开表单并加载设备数据
|
// 打开表单并加载设备数据
|
||||||
@ -172,8 +173,26 @@ const handleDeviceAction = (action: any) => {
|
|||||||
} else if (action.action === 'openECGData') {
|
} else if (action.action === 'openECGData') {
|
||||||
// 打开心电数据组件
|
// 打开心电数据组件
|
||||||
ecgDataRef.value?.open(action.deviceId, action.deviceName)
|
ecgDataRef.value?.open(action.deviceId, action.deviceName)
|
||||||
|
} else if (action.action === 'delete') {
|
||||||
|
// 删除设备
|
||||||
|
const res = await DeviceuserApi.getDevCount(action.deviceId)
|
||||||
|
if (res> 0) {
|
||||||
|
message.error('设备下有人员,不能删除,请解绑后再进行操作')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ElMessageBox.confirm('是否删除该设备?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
const res2 = await DeviceApi.deleteDeviceCode(action.deviceId)
|
||||||
|
if (res2) {
|
||||||
|
message.success('删除成功')
|
||||||
|
handleQuery()
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('设备操作:', action)
|
//设备操作
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user