parent
47f9230ab1
commit
8dffb3fe8f
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,385 @@ |
|||||||
|
<template> |
||||||
|
<div class="app-container"> |
||||||
|
<el-card shadow="never"> |
||||||
|
<template #header> |
||||||
|
<div class="flex justify-between"> |
||||||
|
<div style="display: flex; align-items: center"> |
||||||
|
<el-icon><Grid /></el-icon> <span |
||||||
|
style="font-weight: 700; font-size: 14px; line-height: 16px" |
||||||
|
>设备参数树</span |
||||||
|
> |
||||||
|
</div> |
||||||
|
<div style="display: flex; align-items: center" v-if="loading"> |
||||||
|
<div class="rotate mr-0.5"> |
||||||
|
<el-icon><Loading /></el-icon> |
||||||
|
</div> |
||||||
|
<span style="font-weight: 700; font-size: 14px; line-height: 16px" |
||||||
|
>正在加载,请稍后...</span |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<el-scrollbar max-height="300"> |
||||||
|
<el-tree |
||||||
|
ref="deviceTreeRef" |
||||||
|
:highlight-current="true" |
||||||
|
:data="treeList" |
||||||
|
:props="{ |
||||||
|
children: 'children', |
||||||
|
label: 'label', |
||||||
|
}" |
||||||
|
:expand-on-click-node="false" |
||||||
|
default-expand-all |
||||||
|
> |
||||||
|
<template #default="{ node, data }"> |
||||||
|
<div class="custom-tree-node"> |
||||||
|
<div style="display: flex; justify-content: flex-start"> |
||||||
|
<div v-if="data.childNode === true"> |
||||||
|
<div style="margin-top: 1px" @click="handleNodeClick(data)"> |
||||||
|
<svg-icon class="mr-5px" size="15" icon-class="folder" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div v-else> |
||||||
|
<div style="margin-top: 1px"> |
||||||
|
<svg-icon class="mr-5px" size="15" icon-class="file" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div @click="changeCurrentTree(data)">{{ node.label }}</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</el-tree> |
||||||
|
</el-scrollbar> |
||||||
|
</el-card> |
||||||
|
<el-card shadow="never" class="mt-1"> |
||||||
|
<template #header> |
||||||
|
<div style="display: flex; align-items: center"> |
||||||
|
<el-icon><Grid /></el-icon> <span |
||||||
|
style="font-weight: 700; font-size: 14px; line-height: 16px" |
||||||
|
>设备操作</span |
||||||
|
> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<div v-if="currentTree.childNode === false"> |
||||||
|
<el-form :model="currentTree" v-loading="loading"> |
||||||
|
<el-descriptions :column="1" border> |
||||||
|
<el-descriptions-item |
||||||
|
label="参数名称" |
||||||
|
label-align="left" |
||||||
|
align="left" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
{{ currentTree?.nodePath }} |
||||||
|
</el-descriptions-item> |
||||||
|
<el-descriptions-item |
||||||
|
label="参数值" |
||||||
|
label-align="left" |
||||||
|
align="center" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
<el-form-item> |
||||||
|
<el-input v-model="currentTree.value" /> |
||||||
|
</el-form-item> |
||||||
|
</el-descriptions-item> |
||||||
|
</el-descriptions> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div v-else> |
||||||
|
<el-descriptions :column="1" border> |
||||||
|
<el-descriptions-item |
||||||
|
label="路径" |
||||||
|
label-align="center" |
||||||
|
align="left" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
{{ currentTree?.nodePath }} |
||||||
|
</el-descriptions-item> |
||||||
|
</el-descriptions> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<div class="flex-center"> |
||||||
|
<div v-if="!currentTree.childNode"> |
||||||
|
<el-button type="primary" @click="saveParam">保存参数</el-button> |
||||||
|
<el-button type="primary" @click="openParamAttribute" |
||||||
|
>参数属性</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<div v-else> |
||||||
|
<div v-if="currentTree.label != 'InternetGatewayDevice'"> |
||||||
|
<el-button type="primary" @click="addInstanceNode" |
||||||
|
>新增实例</el-button |
||||||
|
> |
||||||
|
<el-button type="primary" @click="deleteInstanceNode" |
||||||
|
>删除实例</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="ml-2"> |
||||||
|
<el-button type="danger" plain @click="reboot">远程重启</el-button> |
||||||
|
<el-button type="danger" plain @click="factoryReset" |
||||||
|
>恢复出厂</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</el-card> |
||||||
|
<tree-param-attribute ref="treeParamAttributeRef" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { Grid, Loading } from "@element-plus/icons-vue"; |
||||||
|
import { OptionTree } from "@/api/remote/types"; |
||||||
|
import { |
||||||
|
remoteAddInstanceNode, |
||||||
|
remoteDeleteInstanceNode, |
||||||
|
remoteFactoryReset, |
||||||
|
remoteGetParameterValues, |
||||||
|
remoteReboot, |
||||||
|
remoteSetParameterValues, |
||||||
|
remoteTreeNode, |
||||||
|
} from "@/api/remote"; |
||||||
|
import { confirm } from "@/utils/confirm"; |
||||||
|
import TreeParamAttribute from "@/views/family/operate/remote-operation/components/TreeParamAttribute.vue"; |
||||||
|
|
||||||
|
const route = useRoute(); |
||||||
|
let devId: number = parseInt(<string>route.params.devId); |
||||||
|
const treeParamAttributeRef = ref(); |
||||||
|
const deviceTreeRef = ref(); |
||||||
|
const loading = ref<boolean>(false); |
||||||
|
const treeList = ref<OptionTree[]>([ |
||||||
|
{ |
||||||
|
label: "InternetGatewayDevice", |
||||||
|
nodePath: "InternetGatewayDevice.", |
||||||
|
childNode: true, |
||||||
|
children: [], |
||||||
|
}, |
||||||
|
]); |
||||||
|
const currentTree = ref<OptionTree>({ |
||||||
|
label: "InternetGatewayDevice", |
||||||
|
nodePath: "InternetGatewayDevice.", |
||||||
|
childNode: true, |
||||||
|
children: [], |
||||||
|
}); |
||||||
|
const handleNodeClick = (data_: OptionTree) => { |
||||||
|
loading.value = true; |
||||||
|
let nodePath = data_.nodePath; |
||||||
|
remoteTreeNode(devId, nodePath) |
||||||
|
.then(({ data }) => { |
||||||
|
if (!data_.children) { |
||||||
|
data_.children = []; |
||||||
|
} |
||||||
|
data_.children = data; |
||||||
|
treeList.value = [...treeList.value]; |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
const changeCurrentTree = (data: OptionTree) => { |
||||||
|
currentTree.value = data; |
||||||
|
if (data.childNode) { |
||||||
|
return; |
||||||
|
} |
||||||
|
let nodePath = data.nodePath; |
||||||
|
loading.value = true; |
||||||
|
remoteGetParameterValues(devId, nodePath) |
||||||
|
.then(({ data }) => { |
||||||
|
currentTree.value.value = data.value; |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}; |
||||||
|
const saveParam = () => { |
||||||
|
confirm("确定保存该节点参数", () => { |
||||||
|
loading.value = true; |
||||||
|
remoteSetParameterValues( |
||||||
|
devId, |
||||||
|
currentTree.value.nodePath, |
||||||
|
<string>currentTree.value.value |
||||||
|
) |
||||||
|
.then(() => { |
||||||
|
ElMessage({ |
||||||
|
message: "操作成功", |
||||||
|
duration: 1000, |
||||||
|
type: "success", |
||||||
|
}); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
const openParamAttribute = () => { |
||||||
|
treeParamAttributeRef.value.open(devId, currentTree.value.nodePath); |
||||||
|
}; |
||||||
|
const childNode = ref<OptionTree>({}); |
||||||
|
const addInstanceNode = () => { |
||||||
|
confirm("确定添加实例吗", () => { |
||||||
|
loading.value = true; |
||||||
|
remoteAddInstanceNode(devId, currentTree.value.nodePath) |
||||||
|
.then(({ data }) => { |
||||||
|
childNode.value = data; |
||||||
|
addInstanceNode_(treeList.value[0], currentTree.value.nodePath); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
const deleteInstanceNode = () => { |
||||||
|
confirm(`确定删除${currentTree.value.label}实例吗`, () => { |
||||||
|
loading.value = true; |
||||||
|
remoteDeleteInstanceNode(devId, currentTree.value.nodePath) |
||||||
|
.then(() => { |
||||||
|
removeInstanceNode_(treeList.value[0], currentTree.value.nodePath); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
// 查找节点函数 |
||||||
|
const addInstanceNode_ = (tree: OptionTree, nodePath?: string) => { |
||||||
|
// 如果当前节点的 nodePath 匹配,返回当前节点 |
||||||
|
if (tree.nodePath === nodePath) { |
||||||
|
if (!tree.children) { |
||||||
|
tree.children = []; |
||||||
|
} |
||||||
|
tree.children?.push(childNode.value); |
||||||
|
console.log(treeList.value[0]); |
||||||
|
return; |
||||||
|
} |
||||||
|
// 如果当前节点有子节点,则递归查找子节点 |
||||||
|
if (tree.children) { |
||||||
|
for (const child of tree.children) { |
||||||
|
const result = addInstanceNode_(child, nodePath); |
||||||
|
if (result) { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// 如果未找到匹配节点,返回 undefined |
||||||
|
return undefined; |
||||||
|
}; |
||||||
|
const removeInstanceNode_ = (tree: OptionTree, nodePath?: string) => { |
||||||
|
if (!tree.children) return false; |
||||||
|
|
||||||
|
for (let i = 0; i < tree.children.length; i++) { |
||||||
|
const child = tree.children[i]; |
||||||
|
if (child.nodePath === nodePath) { |
||||||
|
// 找到并删除节点 |
||||||
|
tree.children.splice(i, 1); |
||||||
|
return true; |
||||||
|
} |
||||||
|
// 递归删除子节点 |
||||||
|
const result = removeInstanceNode_(child, nodePath); |
||||||
|
if (result) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
}; |
||||||
|
const reboot = () => { |
||||||
|
confirm("确认重启设备吗", () => { |
||||||
|
loading.value = true; |
||||||
|
remoteReboot(devId) |
||||||
|
.then(() => { |
||||||
|
ElMessage({ |
||||||
|
message: "操作成功", |
||||||
|
duration: 1000, |
||||||
|
type: "success", |
||||||
|
}); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
const factoryReset = () => { |
||||||
|
confirm("确认恢复出厂设置吗", () => { |
||||||
|
loading.value = true; |
||||||
|
remoteFactoryReset(devId) |
||||||
|
.then(() => { |
||||||
|
ElMessage({ |
||||||
|
message: "操作成功", |
||||||
|
duration: 1000, |
||||||
|
type: "success", |
||||||
|
}); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
:deep(.el-card__body) { |
||||||
|
padding: 10px 0; |
||||||
|
} |
||||||
|
:deep(.my-label) { |
||||||
|
width: 50px !important; |
||||||
|
text-align: center !important; |
||||||
|
background: var(--el-color-white) !important; |
||||||
|
} |
||||||
|
.rotate { |
||||||
|
animation: rotate 10s linear infinite; |
||||||
|
-webkit-animation: rotate 10s linear infinite; |
||||||
|
} |
||||||
|
@keyframes rotate { |
||||||
|
0% { |
||||||
|
transform: rotate(0); |
||||||
|
} |
||||||
|
|
||||||
|
25% { |
||||||
|
transform: rotate(90deg); |
||||||
|
} |
||||||
|
|
||||||
|
50% { |
||||||
|
transform: rotate(180deg); |
||||||
|
} |
||||||
|
|
||||||
|
75% { |
||||||
|
transform: rotate(270deg); |
||||||
|
} |
||||||
|
|
||||||
|
100% { |
||||||
|
transform: rotate(360deg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@-webkit-keyframes rotate { |
||||||
|
0% { |
||||||
|
transform: rotate(0); |
||||||
|
} |
||||||
|
|
||||||
|
25% { |
||||||
|
transform: rotate(90deg); |
||||||
|
} |
||||||
|
|
||||||
|
50% { |
||||||
|
transform: rotate(180deg); |
||||||
|
} |
||||||
|
|
||||||
|
75% { |
||||||
|
transform: rotate(270deg); |
||||||
|
} |
||||||
|
|
||||||
|
100% { |
||||||
|
transform: rotate(360deg); |
||||||
|
} |
||||||
|
} |
||||||
|
:deep(.el-form-item--default) { |
||||||
|
margin-bottom: 0; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,165 @@ |
|||||||
|
<template> |
||||||
|
<el-dialog class="com-dialog" v-model="openFlag" title="修改参数属性"> |
||||||
|
<el-form :model="formData" v-loading="loading"> |
||||||
|
<el-descriptions :column="1" border> |
||||||
|
<el-descriptions-item |
||||||
|
label="参数名称" |
||||||
|
label-align="center" |
||||||
|
align="left" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
InternetGatewayDevice.DeviceSummary |
||||||
|
</el-descriptions-item> |
||||||
|
<el-descriptions-item |
||||||
|
label="NotificationChange" |
||||||
|
label-align="center" |
||||||
|
align="left" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
<div class="flex justify-between"> |
||||||
|
<el-form-item> |
||||||
|
<el-checkbox-group v-model="formData.notification"> |
||||||
|
<el-checkbox value="true">Notification</el-checkbox> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-radio-group |
||||||
|
v-model="formData.param1" |
||||||
|
:disabled="formData.notification?.length != 1" |
||||||
|
> |
||||||
|
<el-radio value="0">OFF</el-radio> |
||||||
|
<el-radio value="1">PASSIVE</el-radio> |
||||||
|
<el-radio value="2">ACTIVE</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</div> |
||||||
|
</el-descriptions-item> |
||||||
|
<el-descriptions-item |
||||||
|
label="AccessListChange" |
||||||
|
label-align="center" |
||||||
|
align="left" |
||||||
|
label-class-name="my-label" |
||||||
|
class-name="my-content" |
||||||
|
width="15px" |
||||||
|
> |
||||||
|
<div class="flex justify-between"> |
||||||
|
<el-form-item> |
||||||
|
<el-checkbox-group v-model="formData.accessList"> |
||||||
|
<el-checkbox value="true">AccessList</el-checkbox> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-checkbox-group |
||||||
|
v-model="formData.param2" |
||||||
|
:disabled="formData.accessList?.length != 1" |
||||||
|
> |
||||||
|
<el-checkbox value="Subscriber">Subscriber</el-checkbox> |
||||||
|
<el-checkbox value="customAttribute" |
||||||
|
><el-input v-model="customAttribute" style="width: 130px" |
||||||
|
/></el-checkbox> |
||||||
|
</el-checkbox-group> |
||||||
|
</el-form-item> |
||||||
|
</div> |
||||||
|
</el-descriptions-item> |
||||||
|
</el-descriptions> |
||||||
|
</el-form> |
||||||
|
<template #footer> |
||||||
|
<el-button type="primary" @click="submitForm">确定</el-button> |
||||||
|
<el-button @click="openFlag = false">取消</el-button> |
||||||
|
</template> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { |
||||||
|
remoteGetParameterAttributes, |
||||||
|
remoteSetParameterAttributes, |
||||||
|
} from "@/api/remote"; |
||||||
|
import { confirm } from "@/utils/confirm"; |
||||||
|
|
||||||
|
interface ParamAttribute { |
||||||
|
accessList?: string[]; |
||||||
|
notification?: string[]; |
||||||
|
param1?: string; |
||||||
|
param2?: string[]; |
||||||
|
} |
||||||
|
const devId = ref<number>(0); |
||||||
|
const nodePath = ref<string>(""); |
||||||
|
const loading = ref<boolean>(false); |
||||||
|
const openFlag = ref<boolean>(false); |
||||||
|
const formData = ref<ParamAttribute>({}); |
||||||
|
const customAttribute = ref<string>(""); |
||||||
|
const open = (devId_: number, nodePath_: string) => { |
||||||
|
formData.value = { |
||||||
|
accessList: [], |
||||||
|
notification: [], |
||||||
|
}; |
||||||
|
devId.value = devId_; |
||||||
|
nodePath.value = nodePath_; |
||||||
|
getData(devId_, nodePath_); |
||||||
|
openFlag.value = true; |
||||||
|
}; |
||||||
|
const getData = (devId?: number, nodePath?: string) => { |
||||||
|
loading.value = true; |
||||||
|
remoteGetParameterAttributes(devId, nodePath) |
||||||
|
.then(({ data }) => { |
||||||
|
let value_: string = <string>data.value; |
||||||
|
let attributes = value_.split("|"); |
||||||
|
formData.value.param1 = attributes[0]; |
||||||
|
formData.value.param2 = [attributes[1]]; |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}; |
||||||
|
defineExpose({ open }); |
||||||
|
const submitForm = () => { |
||||||
|
confirm("确定修改参数属性吗", () => { |
||||||
|
let argValue = []; |
||||||
|
if (formData.value.notification?.length === 1) { |
||||||
|
argValue.push("true"); |
||||||
|
} else { |
||||||
|
argValue.push("false"); |
||||||
|
} |
||||||
|
argValue.push(formData.value.param1); |
||||||
|
if (formData.value.accessList?.length === 1) { |
||||||
|
argValue.push("true"); |
||||||
|
} else { |
||||||
|
argValue.push("false"); |
||||||
|
} |
||||||
|
if (formData.value.param2?.length === 1) { |
||||||
|
argValue.push(formData.value.param2[0]); |
||||||
|
} else if (formData.value.param2?.length === 2) { |
||||||
|
argValue.push(formData.value.param2[0] + "~" + customAttribute.value); |
||||||
|
} |
||||||
|
loading.value = true; |
||||||
|
remoteSetParameterAttributes( |
||||||
|
devId.value, |
||||||
|
nodePath.value, |
||||||
|
argValue.join("|") |
||||||
|
) |
||||||
|
.then(() => { |
||||||
|
ElMessage({ |
||||||
|
message: "操作成功", |
||||||
|
duration: 1000, |
||||||
|
type: "success", |
||||||
|
}); |
||||||
|
}) |
||||||
|
.finally(() => { |
||||||
|
loading.value = false; |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
:deep(.my-label) { |
||||||
|
width: 50px !important; |
||||||
|
text-align: center !important; |
||||||
|
background: var(--el-color-white) !important; |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue