Files
admin-govern/src/views/govern/device/officialUser/index.vue

388 lines
12 KiB
Vue
Raw Normal View History

2025-11-14 16:19:18 +08:00
<template>
2026-04-24 09:13:48 +08:00
<div class="device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<OfficialUserTree @node-click="selectUser" @selectUser="selectUser"></OfficialUserTree>
<div style="flex: 1" class="pt10 pr10">
<div class="el-descriptions__header">
<div class="el-descriptions__title">工程 / 设备列表</div>
<el-button type="primary" icon="el-icon-Sort" @click="getEnginnerDev">绑定工程 / 设备</el-button>
</div>
2025-11-14 16:19:18 +08:00
2026-04-24 09:13:48 +08:00
<!-- 使用flex布局平均分配高度 -->
<div class="tables-container">
<div class="table-wrapper" :style="{ height: pageHeight1.height }">
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
<vxe-column field="name" title="工程名称"></vxe-column>
<vxe-column title="操作" width="200px">
<template v-slot:default="scoped">
<el-button link size="small" type="danger" @click="deleteEngineering(scoped.row)">
移除
</el-button>
</template>
</vxe-column>
</vxe-table>
</div>
</div>
2025-11-14 16:19:18 +08:00
</div>
2026-04-24 09:13:48 +08:00
<!-- 短信配置 -->
<div style="width: 400px" class="pt10 pr10">
<div class="el-descriptions__header">
<div class="el-descriptions__title">短信配置</div>
<el-button type="primary" icon="el-icon-Select" @click="saveConfiguration">保存</el-button>
</div>
<!-- 使用flex布局平均分配高度 -->
<div :style="{ height: pageHeight1.height }" class="border">
<el-tree
ref="treeRef"
class="mt10"
node-key="id"
default-expand-all
:data="tableData"
:props="defaultProps"
show-checkbox
>
<template #default="{ node, data }">
<span>{{ data.name.replace(/\([^)]*\)/, '') }}</span>
</template>
</el-tree>
</div>
2025-11-14 16:19:18 +08:00
</div>
2026-04-24 09:13:48 +08:00
<!-- 对话框为左右布局 -->
<el-dialog
v-model.trim="dialogVisible"
draggable
title="绑定工程 / 设备"
class="cn-operate-dialog"
:close-on-click-modal="false"
>
<div class="dialog-content">
<!-- 工程部分 -->
<div class="dialog-section">
<div class="section-header">
<span>工程列表</span>
<el-input
maxlength="32"
show-word-limit
v-model.trim="filterText"
placeholder="搜索工程"
clearable
class="search-input"
>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
</div>
<vxe-table
ref="tableRef"
v-bind="defaultAttribute"
:data="tableData2.filter((item: any) => {
return item.name.includes(filterText)
})"
height="400px"
style="width: 100%"
>
<vxe-column type="checkbox" width="60"></vxe-column>
<vxe-column field="name" title="工程名称"></vxe-column>
</vxe-table>
</div>
<!-- 设备部分 -->
<div class="dialog-section">
<div class="section-header">
<span>设备列表</span>
<el-input
maxlength="32"
show-word-limit
v-model.trim="deviceFilterText"
placeholder="搜索设备"
clearable
class="search-input"
>
<template #prefix>
<Icon name="el-icon-Search" style="font-size: 16px" />
</template>
</el-input>
</div>
<vxe-table
ref="deviceTableRef"
v-bind="defaultAttribute"
:data="deviceTableData2.filter((item: any) => {
return item.name.includes(deviceFilterText)
})"
height="400px"
style="width: 100%"
>
<vxe-column type="checkbox" width="60"></vxe-column>
<vxe-column field="name" title="便携式设备名称"></vxe-column>
</vxe-table>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addData"> </el-button>
</span>
</template>
</el-dialog>
</div>
2025-11-14 16:19:18 +08:00
</template>
<script setup lang="ts">
defineOptions({
2026-04-24 09:13:48 +08:00
name: 'govern/officialUser/index'
2025-11-14 16:19:18 +08:00
})
import { defaultAttribute } from '@/components/table/defaultAttribute'
import OfficialUserTree from '@/components/tree/govern/officialUserTree.vue'
import { mainHeight } from '@/utils/layout'
2026-04-24 09:13:48 +08:00
import { queryRunPortableDevByUseId, queryUnlinkEngineeringByUseId } from '@/api/cs-device-boot/user'
import {
add,
removeUserDev,
queryDevByUseId,
addUserDevices,
queryDeviceIdsByUserId
} from '@/api/cs-system-boot/official'
2025-11-14 16:19:18 +08:00
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
2026-01-04 14:55:31 +08:00
const pageHeight = mainHeight(60)
2026-04-24 09:13:48 +08:00
const pageHeight1 = mainHeight(125)
2025-11-14 16:19:18 +08:00
const loading = ref(true)
const user: any = ref({})
const tableData = ref([])
const deviceTableData = ref([]) // 设备表格数据
const tableData2 = ref([]) // 工程数据源
const deviceTableData2 = ref([]) // 设备数据源
const dialogVisible = ref(false)
const filterText = ref('') // 工程搜索文本
const deviceFilterText = ref('') // 设备搜索文本
const tableRef = ref()
const deviceTableRef = ref() // 设备表格引用
2026-04-24 09:13:48 +08:00
const defaultProps = {
children: 'devList',
label: 'name'
}
2025-11-14 16:19:18 +08:00
const selectUser = (e: any) => {
2026-05-28 20:36:49 +08:00
if (e == undefined) return (loading.value = false)
2026-04-24 09:13:48 +08:00
user.value = e
loading.value = true
queryDevByUseId({ userId: e.id })
.then(engineeringRes => {
loading.value = false
tableData.value = engineeringRes.data.engineeringList || []
deviceTableData.value = engineeringRes.data.portableDevList || []
queryDeviceIdsByUserId({
userId: user.value.id
}).then(res => {
treeRef.value!.setCheckedKeys(res.data, false)
})
})
.catch(() => {
loading.value = false
})
2025-11-14 16:19:18 +08:00
}
const getEnginnerDev = () => {
2026-04-24 09:13:48 +08:00
filterText.value = ''
deviceFilterText.value = ''
// 同时获取工程和设备数据
Promise.all([
queryUnlinkEngineeringByUseId({ userId: user.value.id }),
queryRunPortableDevByUseId({ userId: user.value.id })
]).then(([engineeringRes, deviceRes]) => {
tableData2.value = engineeringRes.data || []
deviceTableData2.value = deviceRes.data || []
dialogVisible.value = true
setTimeout(() => {
tableRef.value?.clearCheckboxRow()
deviceTableRef.value?.clearCheckboxRow()
}, 0)
})
2025-11-14 16:19:18 +08:00
}
const deleteEngineering = (row: any) => {
2026-04-24 09:13:48 +08:00
ElMessageBox.confirm('是否移出该工程?', '请确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 只移除工程,设备列表为空
const form = {
engineeringList: [row.id], // 要移除的工程ID
portableDevList: [], // 设备列表为空
userId: user.value.id
}
removeUserDev(form).then((res: any) => {
ElMessage.success(res.message)
selectUser(user.value)
})
2025-11-14 16:19:18 +08:00
})
}
// 删除设备方法
const deleteDevice = (row: any) => {
console.log('删除设备', row)
2026-04-24 09:13:48 +08:00
ElMessageBox.confirm('是否移出该设备?', '请确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 只移除设备,工程列表为空
const form = {
engineeringList: [], // 工程列表为空
portableDevList: [row.id], // 要移除的设备ID
userId: user.value.id
}
removeUserDev(form).then((res: any) => {
ElMessage.success(res.message)
selectUser(user.value)
})
2025-11-14 16:19:18 +08:00
})
}
const addData = () => {
2026-04-24 09:13:48 +08:00
const selectedEngineers = tableRef.value.getCheckboxRecords()
const selectedDevices = deviceTableRef.value.getCheckboxRecords()
// 如果没有选择任何项,则提示
if (selectedEngineers.length === 0 && selectedDevices.length === 0) {
ElMessage.warning('请至少选择一项工程或设备')
return
}
// 构造请求参数对象
const form = {
engineeringList: [] as any[],
portableDevList: [] as any[],
userId: user.value.id
}
// // 处理已有的工程数据
// tableData.value.forEach((item: any) => {
// form.engineeringList.push(item.id)
// })
// // 处理已有的设备数据
// deviceTableData.value.forEach((item: any) => {
// form.portableDevList.push(item.id)
// })
// 添加新选择的工程
selectedEngineers.forEach((item: any) => {
form.engineeringList.push(item.id)
})
// 添加新选择的设备
selectedDevices.forEach((item: any) => {
form.portableDevList.push(item.id)
})
// 发送请求
add(form).then((res: any) => {
ElMessage.success(res.message)
selectUser(user.value)
dialogVisible.value = false
})
}
const treeRef = ref()
// 保存短信配置
const saveConfiguration = () => {
// treeRef.value!.getCheckedNodes(false, false)
let deviceIds = treeRef
.value!.getCheckedNodes(false, false)
.filter((item: any) => item.devList == null)
.map((item: any) => item.id)
if (deviceIds.length == 0) {
return ElMessage.warning('请选择设备!')
}
addUserDevices({
deviceIds: deviceIds,
userId: user.value.id
}).then((res: any) => {
return ElMessage.success('短信配置成功!')
})
2025-11-14 16:19:18 +08:00
}
</script>
<style lang="scss" scoped>
.device-manage {
display: flex;
2026-04-24 09:13:48 +08:00
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
display: flex;
flex-direction: column;
2025-11-14 16:19:18 +08:00
2026-04-24 09:13:48 +08:00
.el-descriptions__header {
// height: 27px;
display: flex;
justify-content: flex-end;
/* 靠右显示 */
align-items: center;
}
2025-11-14 16:19:18 +08:00
2026-04-24 09:13:48 +08:00
.tables-container {
flex: 1;
display: flex;
flex-direction: column;
2025-11-14 16:19:18 +08:00
2026-04-24 09:13:48 +08:00
.table-wrapper {
flex: 1;
min-height: 0;
&:first-child {
// margin-bottom: 10px;
}
}
2025-11-14 16:19:18 +08:00
}
}
2026-04-24 09:13:48 +08:00
}
:deep(.el-descriptions__header) {
margin-bottom: 10px !important;
2025-11-14 16:19:18 +08:00
}
.dialog-content {
2026-04-24 09:13:48 +08:00
display: flex;
gap: 20px;
.dialog-section {
flex: 1;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
span {
font-weight: bold;
font-size: 16px;
}
.search-input {
width: 200px;
}
}
2025-11-14 16:19:18 +08:00
}
}
2026-04-24 09:13:48 +08:00
.border {
border: 1px solid var(--el-border-color);
}
</style>