业务逻辑修改
This commit is contained in:
@@ -1,5 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import { onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
// 清除token和用户信息
|
||||
const clearAuthInfo = () => {
|
||||
const authStore = useAuthStore()
|
||||
// 清除token(这会自动同步到持久化存储)
|
||||
authStore.removeToken()
|
||||
// 清除localStorage中的用户信息
|
||||
localStorage.removeItem('username')
|
||||
// 清除Pinia持久化存储的auth数据(pinia-plugin-persistedstate默认使用'pinia-{storeName}'格式)
|
||||
localStorage.removeItem('pinia-auth')
|
||||
}
|
||||
|
||||
// 页面关闭时清除信息
|
||||
onMounted(() => {
|
||||
// 监听页面关闭/刷新事件(beforeunload在页面关闭或刷新前触发)
|
||||
const handleBeforeUnload = () => {
|
||||
clearAuthInfo()
|
||||
}
|
||||
|
||||
// 监听页面卸载事件(unload在页面卸载时触发)
|
||||
const handleUnload = () => {
|
||||
clearAuthInfo()
|
||||
}
|
||||
|
||||
// 监听页面隐藏事件(pagehide更可靠,可以区分刷新和关闭)
|
||||
const handlePageHide = (event: PageTransitionEvent) => {
|
||||
// 如果页面被缓存(bfcache),不清除信息
|
||||
// 只有在真正关闭时才清除
|
||||
if (!event.persisted) {
|
||||
clearAuthInfo()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
window.addEventListener('unload', handleUnload)
|
||||
window.addEventListener('pagehide', handlePageHide)
|
||||
|
||||
// 清理事件监听器
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
window.removeEventListener('unload', handleUnload)
|
||||
window.removeEventListener('pagehide', handlePageHide)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -45,3 +45,27 @@ export function devparamselect(data: any) {
|
||||
params: data,
|
||||
})
|
||||
}
|
||||
|
||||
// 为参数增加设备的devId
|
||||
export function devparamaddDevId(devId: number, paramId: number) {
|
||||
return request({
|
||||
url: '/devParam/addDevId',
|
||||
method: 'post',
|
||||
params: {
|
||||
devId,
|
||||
paramId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 为参数减少设备的devId
|
||||
export function devparamdelDevId(devId: number, paramId: number) {
|
||||
return request({
|
||||
url: '/devParam/delDevId',
|
||||
method: 'post',
|
||||
params: {
|
||||
devId,
|
||||
paramId,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -60,6 +60,11 @@ const router = createRouter({
|
||||
name: 'island-info',
|
||||
component: () => import('../views/islandInfo/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/devparam',
|
||||
name: 'devparam',
|
||||
component: () => import('../views/devparam/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/devinfo',
|
||||
name: 'devinfo',
|
||||
|
||||
@@ -32,68 +32,72 @@
|
||||
:collapse="false"
|
||||
>
|
||||
<el-menu-item index="/home">
|
||||
<el-icon><HomeFilled /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('首页')" /></el-icon>
|
||||
<span>首页</span>
|
||||
</el-menu-item>
|
||||
<el-sub-menu index="system">
|
||||
<template #title>
|
||||
<el-icon><Setting /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('系统管理')" /></el-icon>
|
||||
<span>系统管理</span>
|
||||
</template>
|
||||
<el-menu-item index="/user">
|
||||
<el-icon><User /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('用户管理')" /></el-icon>
|
||||
<span>用户管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/role">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('角色管理')" /></el-icon>
|
||||
<span>角色管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/department">
|
||||
<el-icon><OfficeBuilding /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('部门管理')" /></el-icon>
|
||||
<span>部门管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/position">
|
||||
<el-icon><Briefcase /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('职位管理')" /></el-icon>
|
||||
<span>职位管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/manage-log">
|
||||
<el-icon><Document /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('操作日志管理')" /></el-icon>
|
||||
<span>操作日志管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/user-role">
|
||||
<el-icon><UserFilled /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('用户角色管理')" /></el-icon>
|
||||
<span>用户角色管理</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="island">
|
||||
<template #title>
|
||||
<el-icon><Grid /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('业务管理')" /></el-icon>
|
||||
<span>业务管理</span>
|
||||
</template>
|
||||
<el-menu-item index="/plc-devinfo">
|
||||
<el-icon><Connection /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('PLC设备管理')" /></el-icon>
|
||||
<span>PLC设备管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/devparam">
|
||||
<el-icon><component :is="getMenuIcon('动作参数管理')" /></el-icon>
|
||||
<span>动作参数管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/devinfo">
|
||||
<el-icon><Monitor /></el-icon>
|
||||
<span>设备管理</span>
|
||||
<el-icon><component :is="getMenuIcon('动作管理')" /></el-icon>
|
||||
<span>动作管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/island-info">
|
||||
<el-icon><Setting /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('功能岛管理')" /></el-icon>
|
||||
<span>功能岛管理</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-sub-menu index="flow">
|
||||
<template #title>
|
||||
<el-icon><List /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('流程管理')" /></el-icon>
|
||||
<span>流程管理</span>
|
||||
</template>
|
||||
<el-menu-item index="/plc-device-control">
|
||||
<el-icon><Connection /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('PLC设备控制')" /></el-icon>
|
||||
<span>PLC设备控制</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/goods-info">
|
||||
<el-icon><Filter /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('样品管理')" /></el-icon>
|
||||
<span>样品管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/flow-info">
|
||||
@@ -101,7 +105,7 @@
|
||||
<span>标准流程管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/step-info">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<el-icon><component :is="getMenuIcon('流程创建')" /></el-icon>
|
||||
<span>流程创建</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
@@ -120,7 +124,26 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { User, Setting, Avatar, OfficeBuilding, Briefcase, Document, CaretBottom, UserFilled, Grid, Monitor, Connection, List, EditPen, Files, Tickets, Management, FolderOpened, Box, Filter, HomeFilled } from '@element-plus/icons-vue'
|
||||
import {
|
||||
User,
|
||||
Setting,
|
||||
Avatar,
|
||||
OfficeBuilding,
|
||||
Briefcase,
|
||||
Document,
|
||||
CaretBottom,
|
||||
UserFilled,
|
||||
Grid,
|
||||
Monitor,
|
||||
Connection,
|
||||
List,
|
||||
EditPen,
|
||||
Files,
|
||||
Box,
|
||||
Operation,
|
||||
Tools,
|
||||
House,
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const router = useRouter()
|
||||
@@ -140,17 +163,31 @@ const activeMenu = computed(() => {
|
||||
// 根据菜单名称获取图标
|
||||
const getMenuIcon = (menuName: string) => {
|
||||
const iconMap: Record<string, any> = {
|
||||
// 一级
|
||||
首页: House,
|
||||
系统管理: Setting,
|
||||
业务管理: Grid,
|
||||
流程管理: List,
|
||||
|
||||
// 系统管理
|
||||
用户管理: User,
|
||||
角色管理: Avatar,
|
||||
部门管理: OfficeBuilding,
|
||||
职位管理: Briefcase,
|
||||
操作日志管理: Document,
|
||||
用户角色管理: UserFilled,
|
||||
|
||||
// 业务管理
|
||||
PLC设备管理: Connection,
|
||||
动作参数管理: Tools,
|
||||
动作管理: Monitor,
|
||||
功能岛管理: Grid,
|
||||
|
||||
// 流程管理
|
||||
PLC设备控制: Operation,
|
||||
样品管理: Box,
|
||||
'标准流程管理': Files, // 文件图标,适合标准流程管理
|
||||
'流程创建': EditPen,
|
||||
'用户管理': User,
|
||||
'角色管理': Avatar,
|
||||
'部门管理': OfficeBuilding,
|
||||
'职位管理': Briefcase,
|
||||
'操作日志管理': Document,
|
||||
'用户角色管理': UserFilled,
|
||||
'功能岛管理': Setting,
|
||||
'设备管理': Monitor,
|
||||
'PLC设备管理': Connection,
|
||||
}
|
||||
return iconMap[menuName] || EditPen
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1291
rc_autoplc_front/src/views/devparam/index.vue
Normal file
1291
rc_autoplc_front/src/views/devparam/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -108,7 +108,7 @@
|
||||
v-model="drawerVisible"
|
||||
:title="drawerTitle"
|
||||
direction="rtl"
|
||||
size="500px"
|
||||
size="600px"
|
||||
:before-close="handleDrawerClose"
|
||||
>
|
||||
<el-form
|
||||
@@ -150,41 +150,39 @@
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isEdit" label="绑定设备">
|
||||
<div class="bind-device-wrapper">
|
||||
<el-button type="primary" @click="handleBindDevice">
|
||||
<el-icon><Plus /></el-icon>
|
||||
绑定设备
|
||||
</el-button>
|
||||
<div v-if="boundDevices.length > 0" class="bound-devices-table-wrapper">
|
||||
<el-table
|
||||
:data="boundDevices"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
style="width: 100%; margin-top: 12px"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" :index="getBoundDeviceIndex" />
|
||||
<el-table-column prop="devName" label="设备名称" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devName || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" size="small">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="devDesc" label="描述" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devDesc || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form-item v-if="isEdit" label="动作信息">
|
||||
<div class="device-list-wrapper">
|
||||
<el-table
|
||||
v-if="deviceList.length > 0"
|
||||
v-loading="deviceLoading"
|
||||
:data="deviceList"
|
||||
border
|
||||
stripe
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" :index="getDeviceIndex" />
|
||||
<el-table-column prop="devName" label="动作名称" width="180" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devName || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="plcAddr" label="PLC映射地址" width="140" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.plcAddr ?? '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" size="small">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="deviceList.length === 0 && !deviceLoading" class="no-devices">
|
||||
该功能岛暂无动作
|
||||
</div>
|
||||
<div v-else class="no-bound-devices">暂无绑定设备</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -198,67 +196,6 @@
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 绑定设备对话框 -->
|
||||
<el-dialog
|
||||
v-if="isEdit"
|
||||
v-model="bindDeviceDialogVisible"
|
||||
:title="isEdit ? '绑定/解绑设备' : '绑定设备'"
|
||||
width="800px"
|
||||
:before-close="handleBindDialogClose"
|
||||
>
|
||||
<el-table
|
||||
ref="deviceTableRef"
|
||||
v-loading="deviceLoading"
|
||||
:data="deviceListForBind"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
@selection-change="handleDeviceSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column type="index" label="序号" width="60" :index="getDeviceIndex" />
|
||||
<el-table-column prop="devName" label="设备名称" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devName || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="devModel" label="设备型号" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devModel || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ipAddr" label="IP地址" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.ipAddr || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="port" label="端口" width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.port !== null && row.port !== undefined ? row.port : '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="protocolType" label="协议" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.protocolType || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" size="small">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleBindDialogClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSaveDeviceBind" :loading="savingDeviceBind">
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -307,13 +244,12 @@ import {
|
||||
islandInfolist,
|
||||
islandInfobyid,
|
||||
} from '@/api/tb/islandinfo'
|
||||
import { devselect, devInfoupd } from '@/api/tb/devinfo'
|
||||
import { devselect } from '@/api/tb/devinfo'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
const submitting = ref(false)
|
||||
const deviceLoading = ref(false)
|
||||
const savingDeviceBind = ref(false)
|
||||
|
||||
// 功能岛列表
|
||||
const islandList = ref<any[]>([])
|
||||
@@ -344,12 +280,8 @@ const formData = reactive({
|
||||
islandDesc: '',
|
||||
})
|
||||
|
||||
// 绑定设备相关
|
||||
const bindDeviceDialogVisible = ref(false)
|
||||
const deviceListForBind = ref<any[]>([])
|
||||
const deviceTableRef = ref()
|
||||
const selectedDevices = ref<any[]>([])
|
||||
const boundDevices = ref<any[]>([])
|
||||
// 动作列表相关
|
||||
const deviceList = ref<any[]>([])
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
@@ -426,16 +358,11 @@ const getStatusText = (status: number | null | undefined) => {
|
||||
return '未知'
|
||||
}
|
||||
|
||||
// 获取设备序号
|
||||
// 获取动作序号
|
||||
const getDeviceIndex = (index: number) => {
|
||||
return index + 1
|
||||
}
|
||||
|
||||
// 获取已绑定设备序号
|
||||
const getBoundDeviceIndex = (index: number) => {
|
||||
return index + 1
|
||||
}
|
||||
|
||||
// 获取功能岛列表
|
||||
const getIslandList = async () => {
|
||||
try {
|
||||
@@ -513,8 +440,7 @@ const resetForm = () => {
|
||||
formData.islandName = ''
|
||||
formData.islandCode = ''
|
||||
formData.islandDesc = ''
|
||||
boundDevices.value = []
|
||||
selectedDevices.value = []
|
||||
deviceList.value = []
|
||||
formRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
@@ -540,9 +466,9 @@ const handleEdit = async (item: any) => {
|
||||
// 优先使用后端的 desc 字段,兼容其他可能的字段名
|
||||
formData.islandDesc = data.desc ?? data.islandDesc ?? data.description ?? ''
|
||||
|
||||
// 加载已绑定的设备
|
||||
// 加载该功能岛下的动作列表
|
||||
if (formData.id) {
|
||||
await loadBoundDevices(formData.id)
|
||||
await loadDeviceList(formData.id)
|
||||
}
|
||||
|
||||
isEdit.value = true
|
||||
@@ -559,39 +485,51 @@ const handleEdit = async (item: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 加载已绑定的设备
|
||||
const loadBoundDevices = async (islandId: number | string) => {
|
||||
// 加载该功能岛下的动作列表
|
||||
const loadDeviceList = async (islandId: number | string) => {
|
||||
try {
|
||||
deviceLoading.value = true
|
||||
const res: any = await devselect({})
|
||||
const allDevices = res?.data ?? res ?? []
|
||||
if (Array.isArray(allDevices)) {
|
||||
boundDevices.value = allDevices.filter((device: any) =>
|
||||
device.islandId && (device.islandId === islandId || device.islandId === String(islandId))
|
||||
)
|
||||
// 过滤出该功能岛下的动作,并排除PLC动作
|
||||
deviceList.value = allDevices.filter((device: any) => {
|
||||
const devModel = device.devModel || ''
|
||||
const isNotPlc = devModel.toUpperCase() !== 'PLC'
|
||||
const isBelongToIsland = device.islandId && (device.islandId === islandId || device.islandId === String(islandId))
|
||||
return isNotPlc && isBelongToIsland
|
||||
})
|
||||
} else {
|
||||
deviceList.value = []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载已绑定设备失败:', error)
|
||||
boundDevices.value = []
|
||||
console.error('加载动作列表失败:', error)
|
||||
deviceList.value = []
|
||||
} finally {
|
||||
deviceLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除功能岛
|
||||
const handleDelete = async (item: any) => {
|
||||
try {
|
||||
// 检查是否绑定了设备
|
||||
// 检查是否绑定了动作
|
||||
const res: any = await devselect({})
|
||||
const allDevices = res?.data ?? res ?? []
|
||||
const boundDevicesList = Array.isArray(allDevices)
|
||||
? allDevices.filter((device: any) =>
|
||||
device.islandId && (device.islandId === item.id || device.islandId === String(item.id))
|
||||
)
|
||||
? allDevices.filter((device: any) => {
|
||||
const devModel = device.devModel || ''
|
||||
const isNotPlc = devModel.toUpperCase() !== 'PLC'
|
||||
const isBelongToIsland = device.islandId && (device.islandId === item.id || device.islandId === String(item.id))
|
||||
return isNotPlc && isBelongToIsland
|
||||
})
|
||||
: []
|
||||
|
||||
if (boundDevicesList.length > 0) {
|
||||
const deviceNames = boundDevicesList.map((d: any) => d.devName || '未命名设备').join('、')
|
||||
const deviceNames = boundDevicesList.map((d: any) => d.devName || '未命名动作').join('、')
|
||||
const islandName = item.islandName || item.name || '未命名'
|
||||
await ElMessageBox.alert(
|
||||
`${islandName}已绑定${deviceNames},请先完成设备解绑`,
|
||||
`${islandName}下还有${deviceNames}等${boundDevicesList.length}个动作,请先完成动作解绑`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
@@ -674,164 +612,6 @@ const handleSubmit = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 打开绑定设备对话框
|
||||
const handleBindDevice = async () => {
|
||||
if (!isEdit.value || !formData.id) {
|
||||
// 新增功能岛不允许绑定设备(仅新增功能岛信息)
|
||||
return
|
||||
}
|
||||
try {
|
||||
deviceLoading.value = true
|
||||
const res: any = await devselect({})
|
||||
const allDevices = res?.data ?? res ?? []
|
||||
|
||||
if (Array.isArray(allDevices)) {
|
||||
// 编辑模式:显示未绑定的设备 + 已绑定该功能岛的设备,排除设备型号为PLC的设备
|
||||
deviceListForBind.value = allDevices.filter((device: any) => {
|
||||
// 排除设备型号为PLC的设备
|
||||
if (device.devModel && String(device.devModel).toUpperCase() === 'PLC') {
|
||||
return false
|
||||
}
|
||||
// 筛选条件:islandId为0或空的设备,或者已绑定该功能岛的设备
|
||||
return (
|
||||
!device.islandId ||
|
||||
device.islandId === formData.id ||
|
||||
device.islandId === String(formData.id) ||
|
||||
device.islandId === 0 ||
|
||||
device.islandId === '0'
|
||||
)
|
||||
})
|
||||
} else {
|
||||
deviceListForBind.value = []
|
||||
}
|
||||
|
||||
bindDeviceDialogVisible.value = true
|
||||
|
||||
// 等待DOM更新后设置已选中的设备
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
if (deviceTableRef.value && isEdit.value && formData.id) {
|
||||
// 编辑模式:默认选中已绑定的设备
|
||||
const boundDeviceIds = boundDevices.value.map((d: any) => d.id)
|
||||
deviceListForBind.value.forEach((device: any) => {
|
||||
if (boundDeviceIds.includes(device.id)) {
|
||||
deviceTableRef.value.toggleRowSelection(device, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取设备列表失败:', error)
|
||||
ElMessage.error('获取设备列表失败')
|
||||
} finally {
|
||||
deviceLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 设备选择变化
|
||||
const handleDeviceSelectionChange = (selection: any[]) => {
|
||||
selectedDevices.value = selection
|
||||
}
|
||||
|
||||
// 保存设备绑定
|
||||
const handleSaveDeviceBind = async () => {
|
||||
try {
|
||||
savingDeviceBind.value = true
|
||||
|
||||
// 获取当前选中的设备ID列表
|
||||
const selectedDeviceIds = selectedDevices.value.map((d: any) => d.id)
|
||||
|
||||
if (!isEdit.value || !formData.id) return
|
||||
|
||||
// 编辑模式:立即保存绑定关系
|
||||
// 获取之前已绑定的设备ID列表
|
||||
const previousBoundDeviceIds = boundDevices.value.map((d: any) => d.id)
|
||||
|
||||
// 需要绑定的设备(新增的)
|
||||
const devicesToBind = selectedDeviceIds.filter((id: any) => !previousBoundDeviceIds.includes(id))
|
||||
|
||||
// 需要解绑的设备(取消选中的)
|
||||
const devicesToUnbind = previousBoundDeviceIds.filter((id: any) => !selectedDeviceIds.includes(id))
|
||||
|
||||
// 执行绑定操作
|
||||
const bindPromises = devicesToBind.map((deviceId: any) => {
|
||||
const device = deviceListForBind.value.find((d: any) => d.id === deviceId)
|
||||
if (device) {
|
||||
// 包含设备名称等必填字段
|
||||
return devInfoupd({
|
||||
id: deviceId,
|
||||
devName: device.devName, // 必填字段
|
||||
islandId: formData.id,
|
||||
})
|
||||
}
|
||||
return Promise.resolve()
|
||||
})
|
||||
|
||||
// 执行解绑操作
|
||||
const unbindPromises = devicesToUnbind.map((deviceId: any) => {
|
||||
const device =
|
||||
deviceListForBind.value.find((d: any) => d.id === deviceId) ||
|
||||
boundDevices.value.find((d: any) => d.id === deviceId)
|
||||
if (device) {
|
||||
// 包含设备名称等必填字段
|
||||
return devInfoupd({
|
||||
id: deviceId,
|
||||
devName: device.devName, // 必填字段
|
||||
islandId: 0, // 解绑时设置为0
|
||||
})
|
||||
}
|
||||
return Promise.resolve()
|
||||
})
|
||||
|
||||
// 执行所有操作
|
||||
const allPromises = [...bindPromises, ...unbindPromises]
|
||||
if (allPromises.length > 0) {
|
||||
const results = await Promise.all(allPromises)
|
||||
// 检查是否有失败的请求
|
||||
const failedResults = results.filter((res: any) => {
|
||||
if (!res) return false
|
||||
// 检查响应数据(可能是直接返回的数据对象)
|
||||
const data = res.data || res
|
||||
return data && (data.code !== '0' && data.code !== 0 && data.code !== undefined && !data.success)
|
||||
})
|
||||
if (failedResults.length > 0) {
|
||||
const firstFailed = failedResults[0]
|
||||
const errorData = firstFailed?.data || firstFailed
|
||||
throw new Error(errorData?.message || errorData?.msg || '部分设备绑定/解绑失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 更新已绑定设备列表
|
||||
await loadBoundDevices(formData.id)
|
||||
|
||||
ElMessage.success('保存成功')
|
||||
|
||||
bindDeviceDialogVisible.value = false
|
||||
} catch (error: any) {
|
||||
console.error('保存设备绑定失败:', error)
|
||||
// 处理不同类型的错误
|
||||
let errorMessage = '保存设备绑定失败'
|
||||
if (error?.message) {
|
||||
errorMessage = error.message
|
||||
} else if (error?.response?.data?.message) {
|
||||
errorMessage = error.response.data.message
|
||||
} else if (error?.response?.data?.msg) {
|
||||
errorMessage = error.response.data.msg
|
||||
} else if (typeof error === 'string') {
|
||||
errorMessage = error
|
||||
}
|
||||
ElMessage.error(errorMessage)
|
||||
} finally {
|
||||
savingDeviceBind.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭绑定设备对话框
|
||||
const handleBindDialogClose = () => {
|
||||
bindDeviceDialogVisible.value = false
|
||||
selectedDevices.value = []
|
||||
if (deviceTableRef.value) {
|
||||
deviceTableRef.value.clearSelection()
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭抽屉
|
||||
const handleDrawerClose = () => {
|
||||
@@ -1048,15 +828,11 @@ onMounted(() => {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bind-device-wrapper {
|
||||
.device-list-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bound-devices-table-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.no-bound-devices {
|
||||
.no-devices {
|
||||
margin-top: 12px;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
@@ -1067,12 +843,6 @@ onMounted(() => {
|
||||
border: 1px dashed #dcdfe6;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
// 功能岛卡片动画:从下往上滑动
|
||||
@keyframes slideUpIn {
|
||||
from {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user