|
|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div class="container" >
|
|
|
+ <div class="container">
|
|
|
<el-row :gutter="20" class="equal-height-row">
|
|
|
<!-- 左侧设备列表 -->
|
|
|
<el-col :span="12" class="col-height">
|
|
|
@@ -32,13 +32,10 @@
|
|
|
|
|
|
<el-scrollbar height="500px">
|
|
|
<el-checkbox-group v-model="selectedDevices">
|
|
|
- <div
|
|
|
- v-for="device in filteredDevices"
|
|
|
- :key="device.id"
|
|
|
- class="checkbox-item"
|
|
|
- >
|
|
|
+ <div v-for="device in filteredDevices" :key="device.id" class="checkbox-item">
|
|
|
<el-checkbox :label="device.id">
|
|
|
- {{ device.deviceCode }} ({{ device.deviceName }}) - {{ device.deptName }} —— {{ device.devicePersons }}
|
|
|
+ {{ device.deviceCode }} ({{ device.deviceName }}) - {{ device.deptName }} ——
|
|
|
+ {{ device.devicePersons }}
|
|
|
</el-checkbox>
|
|
|
</div>
|
|
|
</el-checkbox-group>
|
|
|
@@ -51,7 +48,12 @@
|
|
|
<div class="card right-card">
|
|
|
<h3>{{ t('configDevice.deptList') }}</h3>
|
|
|
<ContentWrap class="dept-tree-container" height="400px">
|
|
|
- <DeptTree2 ref="deptTreeRef" v-model="selectedDeptId" height="100%" @update:modelValue="handleDeptChange"/>
|
|
|
+ <DeptTree2
|
|
|
+ ref="deptTreeRef"
|
|
|
+ v-model="selectedDeptId"
|
|
|
+ height="100%"
|
|
|
+ @update:model-value="handleDeptChange"
|
|
|
+ />
|
|
|
</ContentWrap>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
@@ -83,7 +85,10 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="control-group">
|
|
|
- <label class="control-title">{{ t('configDevice.reasonForAdjustment') }}<span class="required-star">*</span></label>
|
|
|
+ <label class="control-title"
|
|
|
+ >{{ t('configDevice.reasonForAdjustment')
|
|
|
+ }}<span class="required-star">*</span></label
|
|
|
+ >
|
|
|
<div class="reason-input-wrapper">
|
|
|
<el-input
|
|
|
v-model="formData.reason"
|
|
|
@@ -104,15 +109,11 @@
|
|
|
<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 prop="deptId" label="部门id" v-if="false" />
|
|
|
<el-table-column prop="reason" label="调拨原因" />
|
|
|
<el-table-column label="操作" width="120">
|
|
|
<template #default="{ row }">
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- size="small"
|
|
|
- @click="removeTempRelation(row.deviceId)"
|
|
|
- >
|
|
|
+ <el-button type="danger" size="small" @click="removeTempRelation(row.deviceId)">
|
|
|
删除
|
|
|
</el-button>
|
|
|
</template>
|
|
|
@@ -123,13 +124,12 @@
|
|
|
<el-button
|
|
|
type="primary"
|
|
|
size="large"
|
|
|
- style="min-width: 180px;"
|
|
|
+ style="min-width: 180px"
|
|
|
@click="submitRelations"
|
|
|
:disabled="tempRelations.length === 0 || !formData.reason.trim()"
|
|
|
>
|
|
|
{{ t('iotMaintain.save') }}
|
|
|
</el-button>
|
|
|
-
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -137,14 +137,14 @@
|
|
|
<script setup lang="ts">
|
|
|
import { ref, computed, onMounted } from 'vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
-import {defaultProps, handleTree} from "@/utils/tree";
|
|
|
-import * as DeptApi from "@/api/system/dept";
|
|
|
-import * as UserApi from "@/api/system/user";
|
|
|
-import {IotDeviceApi, IotDeviceVO} from "@/api/pms/device";
|
|
|
-import DeptTree2 from "@/views/pms/device/DeptTree2.vue";
|
|
|
+import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
+import * as DeptApi from '@/api/system/dept'
|
|
|
+import * as UserApi from '@/api/system/user'
|
|
|
+import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
|
|
|
+import DeptTree2 from '@/views/pms/device/DeptTree2.vue'
|
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
|
-import { useTagsViewStore } from "@/store/modules/tagsView";
|
|
|
-import {UserVO} from "@/api/system/user";
|
|
|
+import { useTagsViewStore } from '@/store/modules/tagsView'
|
|
|
+import { UserVO } from '@/api/system/user'
|
|
|
|
|
|
const router = useRouter()
|
|
|
const route = useRoute() // 获取路由参数
|
|
|
@@ -168,33 +168,36 @@ const formData = ref({
|
|
|
deviceStatus: undefined,
|
|
|
reason: '',
|
|
|
assetProperty: undefined,
|
|
|
- picUrl: undefined,
|
|
|
+ picUrl: undefined
|
|
|
})
|
|
|
|
|
|
const queryParams = reactive({
|
|
|
- deptId: formData.value.deptId,
|
|
|
+ deptId: formData.value.deptId
|
|
|
})
|
|
|
|
|
|
const deptTreeRef = ref<InstanceType<typeof DeptTree2>>()
|
|
|
|
|
|
const emit = defineEmits(['success', 'node-click']) // 定义 success 树点击 事件,用于操作成功后的回调
|
|
|
|
|
|
-const simpleUsers = ref<UserVO[]>([]) // 人员下拉列表选项
|
|
|
+const simpleUsers = ref<UserVO[]>([]) // 人员下拉列表选项
|
|
|
const selectedPersons = ref<number[]>([]) // 存储选中的人员ID
|
|
|
|
|
|
// 响应式数据
|
|
|
-const tempRelationsMap = ref(new Map<number, {
|
|
|
- deviceId: number
|
|
|
- deviceNames: string
|
|
|
- deptId: number
|
|
|
- deptName: string
|
|
|
- reason: string
|
|
|
-}>())
|
|
|
+const tempRelationsMap = ref(
|
|
|
+ new Map<
|
|
|
+ number,
|
|
|
+ {
|
|
|
+ deviceId: number
|
|
|
+ deviceNames: string
|
|
|
+ deptId: number
|
|
|
+ deptName: string
|
|
|
+ reason: string
|
|
|
+ }
|
|
|
+ >()
|
|
|
+)
|
|
|
|
|
|
// 计算属性转换 Map 为数组
|
|
|
-const tempRelations = computed(() =>
|
|
|
- Array.from(tempRelationsMap.value.values())
|
|
|
-)
|
|
|
+const tempRelations = computed(() => Array.from(tempRelationsMap.value.values()))
|
|
|
|
|
|
const updateTempRelations = () => {
|
|
|
if (!selectedDeptId.value) {
|
|
|
@@ -218,8 +221,8 @@ const updateTempRelations = () => {
|
|
|
})
|
|
|
|
|
|
// 添加/更新当前选中设备的关联
|
|
|
- selectedDevices.value.forEach(deviceId => {
|
|
|
- const device = simpleDevices.value.find(d => d.id === deviceId)
|
|
|
+ selectedDevices.value.forEach((deviceId) => {
|
|
|
+ const device = simpleDevices.value.find((d) => d.id === deviceId)
|
|
|
if (device) {
|
|
|
tempRelationsMap.value.set(deviceId, {
|
|
|
deviceId,
|
|
|
@@ -233,9 +236,13 @@ const updateTempRelations = () => {
|
|
|
}
|
|
|
|
|
|
// 添加设备选择监听
|
|
|
-watch([selectedDevices, selectedDeptId], () => {
|
|
|
- updateTempRelations();
|
|
|
-}, {deep: true, immediate: true, debounce: 100})
|
|
|
+watch(
|
|
|
+ [selectedDevices, selectedDeptId],
|
|
|
+ () => {
|
|
|
+ updateTempRelations()
|
|
|
+ },
|
|
|
+ { deep: true, immediate: true, debounce: 100 }
|
|
|
+)
|
|
|
|
|
|
// 监听部门变化
|
|
|
watch(selectedDeptId, (newVal) => {
|
|
|
@@ -302,7 +309,7 @@ const loadDeptPersons = async (deptId: number) => {
|
|
|
// 调用API获取部门人员
|
|
|
const params = { deptId: deptId, pageNo: 1, pageSize: 10 }
|
|
|
const data = await UserApi.simpleUserList(params)
|
|
|
- simpleUsers.value = data.map(user => ({
|
|
|
+ simpleUsers.value = data.map((user) => ({
|
|
|
id: user.id,
|
|
|
nickname: user.nickname || user.username
|
|
|
}))
|
|
|
@@ -313,12 +320,11 @@ const loadDeptPersons = async (deptId: number) => {
|
|
|
}
|
|
|
|
|
|
// 计算选中的设备原部门集合
|
|
|
-const originDeptIds = computed(() =>
|
|
|
- selectedDevices.value
|
|
|
- .map(deviceId =>
|
|
|
- simpleDevices.value.find(d => d.id === deviceId)?.deptId
|
|
|
- )
|
|
|
- .filter(Boolean) as number[]
|
|
|
+const originDeptIds = computed(
|
|
|
+ () =>
|
|
|
+ selectedDevices.value
|
|
|
+ .map((deviceId) => simpleDevices.value.find((d) => d.id === deviceId)?.deptId)
|
|
|
+ .filter(Boolean) as number[]
|
|
|
)
|
|
|
|
|
|
// 部门选择校验方法
|
|
|
@@ -338,7 +344,7 @@ const filteredDevices = computed(() => {
|
|
|
const searchText = deviceFilterText.value.toLowerCase().trim()
|
|
|
if (!searchText) return simpleDevices.value
|
|
|
|
|
|
- return simpleDevices.value.filter(device => {
|
|
|
+ return simpleDevices.value.filter((device) => {
|
|
|
return (
|
|
|
(device.deviceCode || '').toLowerCase().includes(searchText) ||
|
|
|
(device.deviceName || '').toLowerCase().includes(searchText)
|
|
|
@@ -348,29 +354,35 @@ const filteredDevices = computed(() => {
|
|
|
|
|
|
// 在计算属性区域添加 selectedPersonNames
|
|
|
const selectedPersonNames = computed(() => {
|
|
|
- return selectedPersons.value.map(id => {
|
|
|
- const user = simpleUsers.value.find(u => u.id === id)
|
|
|
- return user?.nickname || ''
|
|
|
- }).filter(Boolean) // 过滤掉空值
|
|
|
+ return selectedPersons.value
|
|
|
+ .map((id) => {
|
|
|
+ const user = simpleUsers.value.find((u) => u.id === id)
|
|
|
+ return user?.nickname || ''
|
|
|
+ })
|
|
|
+ .filter(Boolean) // 过滤掉空值
|
|
|
})
|
|
|
|
|
|
const removeTempRelation = (deviceId: number) => {
|
|
|
tempRelationsMap.value.delete(deviceId)
|
|
|
- selectedDevices.value = selectedDevices.value.filter(id => id !== deviceId)
|
|
|
-};
|
|
|
+ selectedDevices.value = selectedDevices.value.filter((id) => id !== deviceId)
|
|
|
+}
|
|
|
|
|
|
const submitRelations = async () => {
|
|
|
try {
|
|
|
// 提交前二次校验
|
|
|
- const invalidDept = tempRelations.value.some(r =>
|
|
|
- originDeptIds.value.includes(r.deptId)
|
|
|
- )
|
|
|
+ const invalidDept = tempRelations.value.some((r) => originDeptIds.value.includes(r.deptId))
|
|
|
if (invalidDept) {
|
|
|
ElMessage.error('存在调拨部门与设备原属部门相同的情况,请检查')
|
|
|
return
|
|
|
}
|
|
|
+
|
|
|
+ if (!selectedPersons.value.length) {
|
|
|
+ ElMessage.error('请选择责任人')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
// 转换为后端需要的格式
|
|
|
- const submitData = tempRelations.value.map(r => ({
|
|
|
+ const submitData = tempRelations.value.map((r) => ({
|
|
|
deviceId: r.deviceId,
|
|
|
deptId: r.deptId,
|
|
|
reason: r.reason,
|
|
|
@@ -408,14 +420,14 @@ onMounted(async () => {
|
|
|
// 否则使用第一个节点
|
|
|
targetDeptId = deptList.value[0].id
|
|
|
} else {
|
|
|
- console.warn("部门树数据为空,无法设置默认值")
|
|
|
+ console.warn('部门树数据为空,无法设置默认值')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 设置默认选中的部门(转换后树的第一个节点)
|
|
|
// if (deptList.value.length > 0) {
|
|
|
- // 获取转换后树的第一个节点
|
|
|
- // const firstRootNode = deptList.value[0]
|
|
|
+ // 获取转换后树的第一个节点
|
|
|
+ // const firstRootNode = deptList.value[0]
|
|
|
|
|
|
// 设置设备部门的默认值
|
|
|
formData.value.deptId = targetDeptId
|
|
|
@@ -426,11 +438,11 @@ onMounted(async () => {
|
|
|
await handleDeptDeviceTreeNodeClick(targetDeptNode)
|
|
|
}
|
|
|
// } else {
|
|
|
- // console.warn("部门树数据为空,无法设置默认值")
|
|
|
+ // console.warn("部门树数据为空,无法设置默认值")
|
|
|
// }
|
|
|
} catch (error) {
|
|
|
- console.error("初始化部门树失败:", error)
|
|
|
- ElMessage.error("加载部门数据失败")
|
|
|
+ console.error('初始化部门树失败:', error)
|
|
|
+ ElMessage.error('加载部门数据失败')
|
|
|
}
|
|
|
|
|
|
nextTick(() => {
|
|
|
@@ -452,7 +464,6 @@ const findDeptNode = (nodes: Tree[], deptId: number): Tree | null => {
|
|
|
}
|
|
|
return null
|
|
|
}
|
|
|
-
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
@@ -469,12 +480,12 @@ const findDeptNode = (nodes: Tree[], deptId: number): Tree | null => {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
height: 100%; /* 根据实际需要调整整体高度 */
|
|
|
- box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
|
|
+ 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);
|
|
|
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
|
|
}
|
|
|
|
|
|
.list-item {
|
|
|
@@ -559,7 +570,7 @@ h3 {
|
|
|
.col-height {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- min-height: 400px;/* 统一最小高度 */
|
|
|
+ min-height: 400px; /* 统一最小高度 */
|
|
|
}
|
|
|
|
|
|
.filter-input {
|