|
@@ -18,7 +18,7 @@
|
|
|
@node-click="handleDeptDeviceTreeNodeClick"
|
|
|
/>
|
|
|
</div>
|
|
|
- <el-scrollbar height="400px">
|
|
|
+ <el-scrollbar height="500px">
|
|
|
<el-checkbox-group v-model="selectedDevices">
|
|
|
<div
|
|
|
v-for="device in simpleDevices"
|
|
@@ -38,46 +38,41 @@
|
|
|
<el-col :span="12" class="col-height">
|
|
|
<div class="card right-card">
|
|
|
<h3>部门列表</h3>
|
|
|
- <ContentWrap class="dept-tree-container" >
|
|
|
- <DeptTree2 ref="deptTreeRef" v-model="selectedDeptId" height="100%" @update:modelValue="handleDeptChange"/>
|
|
|
- </ContentWrap>
|
|
|
-
|
|
|
- <div class="action-bar">
|
|
|
-
|
|
|
- </div>
|
|
|
+ <ContentWrap class="dept-tree-container" height="400px">
|
|
|
+ <DeptTree2 ref="deptTreeRef" v-model="selectedDeptId" height="100%" @update:modelValue="handleDeptChange"/>
|
|
|
+ </ContentWrap>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
<!-- 暂存关联列表 -->
|
|
|
- <div class="temp-list card">
|
|
|
- <h3>待提交的关联关系</h3>
|
|
|
- <el-table :data="tempRelations" style="width: 100%">
|
|
|
- <el-table-column prop="deviceNames" label="设备" width="200" />
|
|
|
- <el-table-column prop="deptName" label="部门" />
|
|
|
- <el-table-column prop="deptId" label="部门id" v-if="false"/>
|
|
|
- <el-table-column label="操作" width="120">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="small"
|
|
|
- @click="removeTempRelation(row.deviceIds)"
|
|
|
- >
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <div class="submit-area">
|
|
|
- <el-button
|
|
|
- type="primary"
|
|
|
- size="large"
|
|
|
- @click="submitRelations"
|
|
|
- :disabled="tempRelations.length === 0"
|
|
|
- >
|
|
|
- 提交全部关联关系
|
|
|
- </el-button>
|
|
|
+ <div class="submit-area">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="large"
|
|
|
+ @click="submitRelations"
|
|
|
+ :disabled="tempRelations.length === 0"
|
|
|
+ >
|
|
|
+ 保 存
|
|
|
+ </el-button>
|
|
|
+ <div class="temp-list card" v-if="false">
|
|
|
+ <h3>待提交的关联关系</h3>
|
|
|
+ <el-table :data="tempRelations" style="width: 100%">
|
|
|
+ <el-table-column prop="deviceNames" label="设备" width="200" />
|
|
|
+ <el-table-column prop="deptName" label="部门" />
|
|
|
+ <el-table-column prop="deptId" label="部门id" v-if="false"/>
|
|
|
+ <el-table-column label="操作" width="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ size="small"
|
|
|
+ @click="removeTempRelation(row.deviceId)"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -89,7 +84,6 @@ import { ElMessage } from 'element-plus'
|
|
|
import {defaultProps, handleTree} from "@/utils/tree";
|
|
|
import * as DeptApi from "@/api/system/dept";
|
|
|
import {IotDeviceApi, IotDeviceVO} from "@/api/pms/device";
|
|
|
-import {IotDevicePersonApi, IotDevicePersonVO} from "@/api/pms/iotdeviceperson";
|
|
|
import DeptTree2 from "@/views/pms/device/DeptTree2.vue";
|
|
|
|
|
|
defineOptions({ name: 'ConfigDeviceAllot' })
|
|
@@ -120,46 +114,57 @@ const deptTreeRef = ref<InstanceType<typeof DeptTree2>>()
|
|
|
const emit = defineEmits(['success', 'node-click']) // 定义 success 树点击 事件,用于操作成功后的回调
|
|
|
|
|
|
// 响应式数据
|
|
|
-const tempRelations = ref<Array<{
|
|
|
- deviceIds: []
|
|
|
+const tempRelationsMap = ref(new Map<number, {
|
|
|
deviceId: number
|
|
|
deviceNames: string
|
|
|
- deptName: string
|
|
|
deptId: number
|
|
|
- reason: string
|
|
|
-}>>([])
|
|
|
+ deptName: string
|
|
|
+}>())
|
|
|
|
|
|
-// 添加设备选择监听
|
|
|
-watch([selectedDevices, selectedDeptId], () => {
|
|
|
- updateTempRelations();
|
|
|
-}, {deep: true})
|
|
|
+// 计算属性转换 Map 为数组
|
|
|
+const tempRelations = computed(() =>
|
|
|
+ Array.from(tempRelationsMap.value.values())
|
|
|
+)
|
|
|
|
|
|
const updateTempRelations = () => {
|
|
|
- if (!selectedDeptId.value || selectedDevices.value.length === 0) return;
|
|
|
+ if (!selectedDeptId.value) {
|
|
|
+ // 未选择部门时清除所有关联
|
|
|
+ tempRelationsMap.value.clear()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取部门信息
|
|
|
+ const treeNode = deptTreeRef.value?.treeRef?.getNode(selectedDeptId.value)
|
|
|
+ const deptName = treeNode?.data?.name || '未知部门'
|
|
|
|
|
|
- const treeNode = deptTreeRef.value?.treeRef?.getNode(selectedDeptId.value);
|
|
|
- const deptName = treeNode?.data?.name || '未知部门';
|
|
|
+ // 创建当前应该存在的设备集合
|
|
|
+ const currentDeviceIds = new Set(selectedDevices.value)
|
|
|
+
|
|
|
+ // 清理无效关联(包含:1.当前部门外的关联 2.未选中的设备)
|
|
|
+ Array.from(tempRelationsMap.value.entries()).forEach(([deviceId, relation]) => {
|
|
|
+ if (relation.deptId !== selectedDeptId.value || !currentDeviceIds.has(deviceId)) {
|
|
|
+ tempRelationsMap.value.delete(deviceId)
|
|
|
+ }
|
|
|
+ })
|
|
|
|
|
|
- const newRelations = selectedDevices.value
|
|
|
- .map(deviceId => {
|
|
|
- const device = simpleDevices.value.find(d => d.id === deviceId);
|
|
|
- return device ? {
|
|
|
- deviceIds: [deviceId],
|
|
|
- deviceId: deviceId,
|
|
|
+ // 添加/更新当前选中设备的关联
|
|
|
+ selectedDevices.value.forEach(deviceId => {
|
|
|
+ const device = simpleDevices.value.find(d => d.id === deviceId)
|
|
|
+ if (device) {
|
|
|
+ tempRelationsMap.value.set(deviceId, {
|
|
|
+ deviceId,
|
|
|
deviceNames: `${device.deviceCode} (${device.deviceName})`,
|
|
|
- deptId: selectedDeptId.value,
|
|
|
- deptName: deptName
|
|
|
- } : null;
|
|
|
- })
|
|
|
- .filter(Boolean);
|
|
|
-
|
|
|
- tempRelations.value = [
|
|
|
- ...tempRelations.value.filter(r =>
|
|
|
- !selectedDevices.value.includes(r.deviceId)
|
|
|
- ),
|
|
|
- ...newRelations
|
|
|
- ];
|
|
|
-};
|
|
|
+ deptId: selectedDeptId.value as number,
|
|
|
+ deptName
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 添加设备选择监听
|
|
|
+watch([selectedDevices, selectedDeptId], () => {
|
|
|
+ updateTempRelations();
|
|
|
+}, {deep: true, immediate: true, debounce: 100})
|
|
|
|
|
|
// 修改部门变更处理方法
|
|
|
const handleDeptChange = (deptId) => {
|
|
@@ -167,11 +172,11 @@ const handleDeptChange = (deptId) => {
|
|
|
updateTempRelations()
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/** 处理 部门-设备 树 被点击 */
|
|
|
const handleDeptDeviceTreeNodeClick = async (row: { [key: string]: any }) => {
|
|
|
emit('node-click', row)
|
|
|
formData.value.deptId = row.id
|
|
|
+ selectedDevices.value = []
|
|
|
await getDeviceList()
|
|
|
}
|
|
|
|
|
@@ -187,13 +192,9 @@ const getDeviceList = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const removeTempRelation = (deviceIds: number[]) => {
|
|
|
- tempRelations.value = tempRelations.value.filter(
|
|
|
- r => !deviceIds.includes(r.deviceId)
|
|
|
- );
|
|
|
- selectedDevices.value = selectedDevices.value.filter(
|
|
|
- id => !deviceIds.includes(id)
|
|
|
- );
|
|
|
+const removeTempRelation = (deviceId: number) => {
|
|
|
+ tempRelationsMap.value.delete(deviceId)
|
|
|
+ selectedDevices.value = selectedDevices.value.filter(id => id !== deviceId)
|
|
|
};
|
|
|
|
|
|
const submitRelations = async () => {
|
|
@@ -237,6 +238,15 @@ onMounted(async () => {
|
|
|
padding: 20px;
|
|
|
margin-bottom: 20px;
|
|
|
background: white;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100%; /* 根据实际需要调整整体高度 */
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
|
|
+ transition: box-shadow 0.2s;
|
|
|
+}
|
|
|
+
|
|
|
+.card:hover {
|
|
|
+ box-shadow: 0 4px 16px rgba(0,0,0,0.15);
|
|
|
}
|
|
|
|
|
|
.list-item {
|
|
@@ -264,7 +274,7 @@ onMounted(async () => {
|
|
|
}
|
|
|
|
|
|
.submit-area {
|
|
|
- margin-top: 20px;
|
|
|
+ margin-top: 5px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
@@ -273,49 +283,6 @@ h3 {
|
|
|
color: #303133;
|
|
|
}
|
|
|
|
|
|
-.radio-item {
|
|
|
- width: 100%;
|
|
|
- padding: 8px 12px;
|
|
|
- border-bottom: 1px solid #f0f0f0;
|
|
|
-}
|
|
|
-
|
|
|
-.radio-item .el-radio {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
-}
|
|
|
-
|
|
|
-.radio-item .el-radio__label {
|
|
|
- display: block;
|
|
|
- white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow: ellipsis;
|
|
|
-}
|
|
|
-
|
|
|
-.dept-node {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 8px;
|
|
|
- width: 100%;
|
|
|
- padding: 5px 0;
|
|
|
-
|
|
|
- :deep(.el-radio) {
|
|
|
- flex: 1;
|
|
|
- .el-radio__label {
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .el-tag {
|
|
|
- margin-left: auto;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-.card {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- height: 600px; /* 根据实际需要调整整体高度 */
|
|
|
-}
|
|
|
-
|
|
|
.dept-select {
|
|
|
flex-shrink: 0; /* 防止搜索框被压缩 */
|
|
|
}
|
|
@@ -350,11 +317,6 @@ h3 {
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
-/* 确保内容区域填充高度 */
|
|
|
-.h-full {
|
|
|
- height: 100%;
|
|
|
-}
|
|
|
-
|
|
|
/* 调整树形组件内部滚动 */
|
|
|
:deep(.el-tree) {
|
|
|
height: 100%;
|
|
@@ -364,12 +326,14 @@ h3 {
|
|
|
.equal-height-row {
|
|
|
display: flex;
|
|
|
align-items: stretch; /* 关键:等高布局 */
|
|
|
+ /* height: 500px; */
|
|
|
}
|
|
|
|
|
|
.col-height {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- min-height: 600px; /* 统一最小高度 */
|
|
|
+ min-height: 400px;/* 统一最小高度 */
|
|
|
+ /* height: 100% !important; */
|
|
|
}
|
|
|
|
|
|
</style>
|