feat:修改绑定相机

This commit is contained in:
dzc committed 2025-08-06 17:31:07 +08:00
1 parent b1397a182e
commit 2cb3da7f83
7 files changed
+252 -11

No files matched your search

+1 -2
View File
@@ -1,11 +1,10 @@
<template>
<!-- @visible-change="(e: boolean) => e && getOptions()" -->
<el-tree-select class="stafftree" :props="{
label: 'treeLabel',
children: 'deviceChannelList',
}" node-key="treeValue" v-model="state.selectId" :placeholder="props.placeholder" :clearable="props.clearable"
:loading="state.loading" :data="state.options" :render-after-expand="false" show-checkbox multiple
style="width: 100%" filterable default-expand-all />
style="width: 100%" filterable default-expand-all @visible-change="(e: boolean) => e && getOptions()" />
</template>
<script setup lang="ts" name="select-tree-channel">
@@ -0,0 +1,208 @@
<template>
<el-tree-select class="radio-tree-select" :props="{
label: 'treeLabel',
children: 'deviceChannelList',
}" node-key="treeValue" v-model="state.selectId" :placeholder="props.placeholder" :clearable="props.clearable"
:disabled="props.disabled" :loading="state.loading" :data="state.options" :render-after-expand="false"
style="width: 100%" filterable default-expand-all @node-click="handleNodeClick" @clear="handleClear"
@visible-change="(e: boolean) => e && getOptions()" />
</template>
<script setup lang="ts" name="select-tree-channel-radio">
import * as DeviceManageApi from '/@/api/device/deviceManage'
const emit = defineEmits(["change"])
const selectId = defineModel()
type Props = {
placeholder?: string
disabled?: boolean
clearable?: boolean
autoFirst?: boolean
apiParams?: any
/** 是否只允许选择叶子节点 */
checkStrictly?: boolean
}
const props = withDefaults(
defineProps<Props>(),
{
placeholder: "请选择设备通道",
disabled: false,
clearable: true,
autoFirst: false,
apiParams: {},
checkStrictly: false,
},
)
const queryForm = reactive<any>({
name: "",
})
const state = reactive<any>({
loading: true,
selectId: selectId,
options: [],
})
// 监听外部传入的 selectId 变化
watch(
selectId,
(newVal, oldValue) => {
if (newVal === oldValue) return
state.selectId = newVal
if (!state.options.length) {
getOptions()
}
},
{ immediate: true },
)
// 监听内部 selectId 变化,同步到外部
watch(
() => state.selectId,
(newVal) => {
if (newVal !== selectId.value) {
selectId.value = newVal
emit("change", newVal)
}
}
)
// 处理节点点击事件
const handleNodeClick = (data: any, node: any) => {
// 如果设置了 checkStrictly,只允许选择叶子节点
if (props.checkStrictly && node.childNodes && node.childNodes.length > 0) {
return
}
// 单选模式,直接设置选中的值
state.selectId = data.treeValue
}
// 处理清空事件
const handleClear = () => {
state.selectId = null
}
// 获取选项数据
async function getOptions() {
try {
state.loading = true
const _pa = {
...queryForm,
...props.apiParams,
}
const { data } = await DeviceManageApi.channelTree(_pa)
state.options = data ?? []
// 如果设置了 autoFirst 且有数据,自动选择第一个
if (props.autoFirst && state.options.length > 0) {
const firstSelectableNode = findFirstSelectableNode(state.options)
if (firstSelectableNode) {
state.selectId = firstSelectableNode.treeValue
}
}
} catch (error) {
console.error('获取设备通道树数据失败:', error)
state.options = []
} finally {
setTimeout(() => (state.loading = false), 500)
}
}
// 查找第一个可选择的节点(如果设置了 checkStrictly,则查找第一个叶子节点)
const findFirstSelectableNode = (nodes: any[]): any => {
for (const node of nodes) {
if (props.checkStrictly) {
// 只选择叶子节点
if (!node.deviceChannelList || node.deviceChannelList.length === 0) {
return node
}
// 递归查找子节点
if (node.deviceChannelList && node.deviceChannelList.length > 0) {
const childResult = findFirstSelectableNode(node.deviceChannelList)
if (childResult) return childResult
}
} else {
// 可以选择任意节点
return node
}
}
return null
}
// 获取当前选中的节点信息
const getSelectedNode = () => {
if (!state.selectId) return null
const findNode = (nodes: any[], targetValue: any): any => {
for (const node of nodes) {
if (node.treeValue === targetValue) {
return node
}
if (node.deviceChannelList && node.deviceChannelList.length > 0) {
const childResult = findNode(node.deviceChannelList, targetValue)
if (childResult) return childResult
}
}
return null
}
return findNode(state.options, state.selectId)
}
// 暴露方法给父组件使用
defineExpose({
getSelectedNode,
refresh: getOptions,
clearSelection: handleClear
})
</script>
<style lang="scss">
.radio-tree-select {
.el-tree-select__tags {
// 单选模式下隐藏多选标签样式
.el-tag {
max-width: 100%;
}
}
// 隐藏复选框,因为我们使用单选模式
.el-tree-node__content .el-checkbox {
display: none !important;
}
// 添加单选样式指示
.el-tree-node__content {
position: relative;
&:hover {
background-color: var(--el-tree-node-hover-bg-color);
}
}
// 选中状态样式
.el-tree-node.is-current>.el-tree-node__content {
background-color: var(--el-color-primary-light-9);
color: var(--el-color-primary);
font-weight: 500;
&::before {
content: '';
position: absolute;
left: 8px;
top: 50%;
transform: translateY(-50%);
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--el-color-primary);
}
}
}
</style>
+2
View File
@@ -26,6 +26,7 @@ import SelectArea from "/@/components/Select/SelectArea.vue"
import SelectDevice from "/@/components/Select/SelectDevice.vue"
import SelectDutyType from "/@/components/Select/SelectDutyType.vue"
import SelectTreeChannel from "/@/components/Select/SelectTreeChannel.vue"
import SelectTreeChannelRadio from "/@/components/Select/SelectTreeChannelRadio.vue"
import ColumnBtn from "/@/components/Column/ColumnBtn.vue"
@@ -82,6 +83,7 @@ export default {
app.component('SelectDevice', SelectDevice);
app.component('SelectDutyType', SelectDutyType);
app.component('SelectTreeChannel', SelectTreeChannel);
app.component('SelectTreeChannelRadio', SelectTreeChannelRadio);
app.component('ColumnBtn', ColumnBtn);