开发交换机注册模块

This commit is contained in:
康冉冉
2025-10-11 18:19:16 +08:00
parent 2b58b00e3b
commit a1737a6c85
32 changed files with 1805 additions and 805 deletions

View File

@@ -145,7 +145,7 @@ aside {
//main-container全局样式
.app-container {
//height: calc(100vh - 85px);
height: calc(100vh - 85px);
padding: 8px 20px 20px;
overflow: auto;
}

View File

@@ -108,7 +108,7 @@
/** 表单布局 **/
.form-header {
font-size: 15px;
font-size: 16px;
color: #6379bb;
border-bottom: 1px solid #ddd;
margin: 8px 10px 25px 10px;

View File

@@ -2,7 +2,7 @@
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" :label-width="config && config.labelWidth || '130px'" :key="config && config.key" class="demo-ruleForm">
<template v-for="(formItem,index) of formList">
<h4 v-if="formItem && formItem.config && formItem.config.title" class="form-header h4">{{formItem.config.title}}</h4>
<h4 v-if="formItem && formItem.config && formItem.config.title" style="color: #000;" class="form-header h4">{{formItem.config.title}}</h4>
<el-row>
<el-col v-for="(formVal,key,index) of formItem['controls']" :span="formVal.span" v-if="!formVal.hidden" :class="formItem.config.colSpan" :style="formVal.style">
<el-form-item
@@ -261,7 +261,7 @@
// 返回
handleReset() {
this.$refs.ruleForm.resetFields();
this.$emit("fnClick", {fnCode: 'cancle'});
this.$emit("fnClick", {fnCode: 'cancel'});
},
// change事件
handleChange(key, val, formVal) {

View File

@@ -52,9 +52,19 @@
<el-table-column v-if="config && config.tableButton && config.tableButton.line" :width="config.tableButton.line.length * 60 + `px`" label="操作" fixed="right" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<template v-for="item of config.tableButton.line">
<!-- <el-tooltip v-if="item && item.content" :content="item.content" placement="top">-->
<template v-if="item && item.more && item.more.length > 0">
<el-dropdown size="mini" trigger="click" @command="(command) => handleClick({fnCode: command}, scope.row)">
<el-button size="mini" type="text" icon="el-icon-d-arrow-right"><span style="margin-left: -5px;">{{item && item.title ? item.title : '更多'}}</span></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="dropBut of item.more" :command="dropBut.fnCode" :icon="dropBut.icon" :hasPermi="[dropBut.hasPermi]">{{dropBut.content}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<template v-else>
<!-- <el-tooltip v-if="item && item.content" :content="item.content" placement="top">-->
<el-button v-if="item && item.content" size="mini" link :type="item.type" :icon="item.icon" v-show="scope.row[item.showName] === item.showVal" @click="handleClick(item, scope.row)" :hasPermi="[item.hasPermi]">{{item.content}}</el-button>
<!-- </el-tooltip>-->
<!-- </el-tooltip>-->
</template>
</template>
</template>
</el-table-column>

View File

@@ -197,20 +197,6 @@ export const dynamicRoutes = [
}
]
},
// {
// path: '/disRevenue/earnManage/server/graphicAnalysis',
// component: Layout,
// hidden: true,
// permissions: ['disRevenue:earnManage:server:graphicAnalysis'],
// children: [
// {
// path: 'index/:dialogVal?',
// component: () => import('@/views/disRevenue/earnManage/server/dialogView'),
// name: 'DialogView',
// meta: { title: '图形分析', activeMenu: '/disRevenue/earnManage/server' }
// }
// ]
// },
// 交换机带宽收益
{
path: '/earnManage/switch/list',
@@ -226,20 +212,6 @@ export const dynamicRoutes = [
}
]
},
// {
// path: '/disRevenue/earnManage/switch/edit',
// component: Layout,
// hidden: true,
// permissions: ['disRevenue:earnManage:switch:edit'],
// children: [
// {
// path: 'index/:switchId?',
// component: () => import('@/views/disRevenue/earnManage/server/details'),
// name: 'SwitchEdit',
// meta: { title: '生成月均日95值', activeMenu: '/disRevenue/earnManage/switch' }
// }
// ]
// },
// 业务管理
{
path: '/earnManage/business/details',
@@ -255,6 +227,7 @@ export const dynamicRoutes = [
}
]
},
// 资源注册
{
path: '/resource/register/edit',
component: Layout,
@@ -265,7 +238,50 @@ export const dynamicRoutes = [
path: 'index/:id?',
component: () => import('@/views/resource/register/handle'),
name: 'RegisterEdit',
meta: { title: '相关数据', activeMenu: '/resource/register' }
meta: { title: '资源注册信息', activeMenu: '/resource/register' }
}
]
},
// 交换机管理
{
path: '/resource/switchRegister/edit',
component: Layout,
hidden: true,
permissions: ['resource:switchRegister:edit'],
children: [
{
path: 'index/:id?',
component: () => import('@/views/resource/switchRegister/handle'),
name: 'SwitchRegisterEdit',
meta: { title: '交换机注册信息', activeMenu: '/resource/switchRegister' }
}
]
},
{
path: '/resource/switchRegister/portRemarks',
component: Layout,
hidden: true,
permissions: ['resource:switchRegister:portRemarks'],
children: [
{
path: ':id?',
component: () => import('@/views/resource/switchRegister/portRemarks'),
name: 'SwitchRegisterPortRemarks',
meta: { title: '接口备注', activeMenu: '/resource/switchRegister' }
}
]
},
{
path: '/resource/switchRegister/monitorChart',
component: Layout,
hidden: true,
permissions: ['resource:switchRegister:echartView'],
children: [
{
path: ':id?',
component: () => import('@/views/resource/switchRegister/monitorChart'),
name: 'SwitchRegisterChart',
meta: { title: '图形监控', activeMenu: '/resource/switchRegister' }
}
]
},

View File

@@ -75,7 +75,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/group");
break;
default:

View File

@@ -63,7 +63,7 @@
this.loading = false;
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/earnManage/business");
break;
default:

View File

@@ -372,7 +372,7 @@
switch (result.fnCode) {
case 'submit':
break;
case 'cancle':
case 'cancel':
break;
default:
}

View File

@@ -90,7 +90,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
if (this.paramsData && this.paramsData.resourceType === '1') {
this.$router.push("/earnManage/server");
}

View File

@@ -108,7 +108,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/agentUpdate");
break;
default:

View File

@@ -129,7 +129,7 @@
switch (result.fnCode) {
case 'details':
this.$router.push({
path:'/disRevenue/resource/alarmLog/details',
path:'/resource/alarmLog/details',
query:{
id: rowData.id
}

View File

@@ -58,7 +58,7 @@
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'cancle':
case 'cancel':
this.$router.push("/resource/alarmLog");
break;
default:

View File

@@ -10,7 +10,7 @@
</div>
</div>
</div>
<el-button v-if="paramsData && paramsData.readonly === 'true'" class="mb20 mt20" style="float: right;" @click="callback({fnCode: 'cancle'})">返回</el-button>
<el-button v-if="paramsData && paramsData.readonly === 'true'" class="mb20 mt20" style="float: right;" @click="callback({fnCode: 'cancel'})">返回</el-button>
</div>
</template>
@@ -111,7 +111,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/fileManage");
break;
default:

View File

@@ -85,7 +85,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/group");
break;
// case 'includedDevicesId':

View File

@@ -60,12 +60,12 @@
],
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'disRevenue:resource:register:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'disRevenue:resource:register:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'disRevenue:resource:register:export'},
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:register:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'resource:register:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'resource:register:export'},
],
line: [
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'disRevenue:resource:register:edit'},
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'resource:register:edit'},
]
}
}

View File

@@ -59,13 +59,13 @@
],
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'disRevenue:resource:monitorTemp:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'disRevenue:resource:monitorTemp:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'disRevenue:resource:monitorTemp:export'},
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:monitorTemp:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'resource:monitorTemp:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'resource:monitorTemp:export'},
],
line: [
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'disRevenue:resource:monitorTemp:edit'},
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'disRevenue:resource:monitorTemp:details'},
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'resource:monitorTemp:edit'},
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'resource:monitorTemp:details'},
// {content: '复制', fnCode: 'copy', type: 'text', icon: 'el-icon-document-copy', hasPermi: 'disRevenue:resource:monitorTemp:copy'},
]
}
@@ -113,11 +113,11 @@
switch (result.fnCode) {
case 'add':
this.$router.push({
path:'/disRevenue/resource/monitorTemp/details/index'});
path:'/resource/monitorTemp/details/index'});
break;
case 'edit':
this.$router.push({
path:'/disRevenue/resource/monitorTemp/details/index',
path:'/resource/monitorTemp/details/index',
query:{
id: rowData.id
}
@@ -125,7 +125,7 @@
break;
case 'details':
this.$router.push({
path:'/disRevenue/resource/monitorTemp/view/index',
path:'/resource/monitorTemp/view/index',
query:{
id: rowData.id,
readonly: true

View File

@@ -114,7 +114,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/register")
break;
default:

View File

@@ -2,14 +2,56 @@
<div class="app-container pageTopForm">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" size="small" label-width="auto">
<el-col :span="6">
<el-form-item label="交换机名称" prop="resourceName">
<el-form-item label="资源名称" prop="resourceName">
<el-input
v-model="queryParams.resourceName"
placeholder="请输入交换机名称"
placeholder="请输入交换机名称/服务器名称"
clearable
@keyup.enter.native="handleQuery"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="资源类型" prop="resourceType">
<el-select
v-model="queryParams.resourceType"
placeholder="请选择资源类型"
clearable>
<el-option
v-for="dict in dict.type.rm_register_resource_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Agent注册状态" title="Agent注册状态" prop="registrationStatus">
<el-select
v-model="queryParams.registrationStatus"
placeholder="请选择Agent注册状态"
clearable>
<el-option
v-for="dict in dict.type.rm_register_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="Agent在线状态" title="Agent在线状态" prop="onlineStatus">
<el-select
v-model="queryParams.onlineStatus"
placeholder="请选择Agent在线状态"
clearable>
<el-option
v-for="dict in dict.type.rm_register_online_state"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="交换机在线状态" title="交换机在线状态" prop="switchStatus">
<el-select
@@ -76,39 +118,29 @@
// 列显隐信息
columns: {
id: { label: `ID`,width: '80'},
switchName: { label: `交换机名称`, visible: true, minWidth: '200'},
hardwareSn: { label: `硬件SN`,minWidth: '250'},
resourceType: { label: `交换机类型`, minWidth: '100', slotName: 'tempType'},
snmpCollectAddr: { label: `SNMP采集地址`, visible: true, minWidth: '150'},
snmpCollectPort: { label: `SNMP采集端口`, visible: true, minWidth: '150'},
switchStatus: { label: `在线状态`, slotName: 'tempOnlineStatus', minWidth: '120', visible: true },
showTime:{ label: `上级时间`,minWidth: '160'},
updateTime:{ label: `修改时间`,minWidth: '160'},
createTime:{ label: `创建时间`,minWidth: '160'},
agentNum: { label: `交换机心跳检测次数`, minWidth: '180'},
agentWeek: { label: `交换机心跳检测周期`, minWidth: '180'},
agentOID: { label: `交换机心跳检测OID`, minWidth: '180'},
protocol: { label: `SNMP版本`, minWidth: '80'},
rwPermission: { label: `读写权限`, minWidth: '120'},
securityLevel: { label: `安全级别`, minWidth: '120'},
encryption: { label: `加密方式`, minWidth: '120'},
teamName: { label: `团体名称`, minWidth: '120'},
resourceUserName: { label: `用户名`, minWidth: '120'},
resourcePwd: { label: `密码`, minWidth: '120'}
hardwareSn: { label: `硬件SN`,minWidth: '250', visible: true },
resourceType: { label: `资源类型`, minWidth: '100', slotName: 'tempType', visible: true },
resourceName: { label: `资源名称`, visible: true, minWidth: '200'},
ipAddress: { label: `IP地址`, minWidth: '200', visible: true },
resourcePort: { label: `端口`, slotName: 'tempPort', minWidth: '80', visible: true },
protocol: { label: `协议`, minWidth: '80', slotName: 'tempProtocol', visible: true },
registrationStatus: { label: `Agent注册状态`, slotName: 'tempStatus', minWidth: '120', visible: true },
onlineStatus: { label: `Agent在线状态`, slotName: 'tempOnlineStatus', minWidth: '120', visible: true },
switchStatus: { label: `交换机在线状态`, slotName: 'tempOnlineStatus', minWidth: '120', visible: true }
},
config: {
searcherForm: [
{label: '交换机名称', prop: 'roleName', type: 'selset', options: []}
],
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:register:add'},
{content: '端口备注', fnCode: 'portRemarks', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:register:portRemarks'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'resource:register:export'},
],
line: [
{content: '图形监控', fnCode: 'echartView', type: 'text', icon: 'el-icon-data-analysis', hasPermi: 'resource:register:graphicAnalysis'},
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'resource:register:edit'},
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'resource:register:details'},
// {content: '注册', fnCode: 'enroll', showName: 'registrationStatus', showVal: '0', type: 'text', icon: 'el-icon-circle-check', hasPermi: 'resource:register:enroll'},
// {content: '取消注册', fnCode: 'unenroll', showName: 'registrationStatus', showVal: '1', type: 'text', icon: 'el-icon-circle-close', hasPermi: 'resource:register:unenroll'},
{content: '注册', fnCode: 'enroll', showName: 'registrationStatus', showVal: '0', type: 'text', icon: 'el-icon-circle-check', hasPermi: 'resource:register:enroll'},
{content: '取消注册', fnCode: 'unenroll', showName: 'registrationStatus', showVal: '1', type: 'text', icon: 'el-icon-circle-close', hasPermi: 'resource:register:unenroll'},
]
}
},

View File

@@ -16,7 +16,7 @@
</el-timeline-item>
</el-timeline>
</div>
<el-button v-if="paramsData && paramsData.readonly === 'true'" type="primary" class="mb20 mt20" style="float: right;" @click="callback({fnCode: 'cancle'})">返回</el-button>
<el-button v-if="paramsData && paramsData.readonly === 'true'" type="primary" class="mb20 mt20" style="float: right;" @click="callback({fnCode: 'cancel'})">返回</el-button>
</div>
</template>
@@ -114,7 +114,7 @@
// this.$modal.msgError("操作失败")
// });
// break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/remoteManage");
break;
default:

View File

@@ -156,7 +156,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
if (this.paramsData && this.paramsData.resourceType === '1') {
this.$router.push("/earnManage/server");
}

View File

@@ -223,14 +223,14 @@
fnDetails(row,type) {
if (type && type === '1') {
this.$router.push({
path:'/disRevenue/resource/resMonitor/digitalSuper',
path:'/resource/resMonitor/digitalSuper',
query:{
id: row.id
}
});
} else {
this.$router.push({
path:'/disRevenue/resource/resMonitor/digitalAutoFind',
path:'/resource/resMonitor/digitalAutoFind',
query:{
id: row.id
}
@@ -260,7 +260,7 @@
switch (result.fnCode) {
case 'details':
this.$router.push({
path:'/disRevenue/resource/resMonitor/details/index',
path:'/resource/resMonitor/details/index',
query:{
id: rowData.id
}

View File

@@ -1,160 +0,0 @@
<template>
<div class="app-container pageTopForm">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" size="small" label-width="130px">
<el-col :span="6">
<el-form-item label="交换机名称" prop="switchName">
<el-input
v-model="queryParams.switchName"
placeholder="请输入交互机名称"
clearable
@keyup.enter.native="handleQuery"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item class="lastBtnSty">
<el-button type="primary" size="mini" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-form>
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="roleList" @fnClick="callback" @fnRenderList="getList" @value-change="handleValueChange">
<template #tempType="{ row, column }">
<dict-tag :options="dict.type.rm_topology_type" :value="row.connectedDeviceType"/>
</template>
</TableList>
</div>
</template>
<script setup>
import TableList from "@/components/table/index.vue"
import {listTopology, delTopology} from "@/api/disRevenue/resource"
export default {
name: 'SwitchManage',
components: {TableList},
dicts: ['rm_topology_type'],
data() {
return {
loading: true,
showSearch: true,
roleList: [],
queryParams: {
total: 0,
pageNum: 1,
pageSize: 10
},
// 列显隐信息
columns: {
id: { label: `ID`, width: '50', visible: false },
switchName: { label: `交换机名称`, minWidth: '150', visible: true },
switchSn: { label: `交换机硬件SN`, minWidth: '200', visible: false},
interfaceName: { label: `接口名称`, minWidth: '100', visible: true },
connectedDeviceType: { label: `接口连接设备类型`, slotName: 'tempType', minWidth: '150', visible: true },
serverName: { label: `服务器名称`, minWidth: '200', visible: true},
serverSn: { label: `服务器硬件SN`, minWidth: '200', visible: false},
serverPort: { label: `服务器网口`, minWidth: '250', visible: true },
createTime: { label: `创建时间`, minWidth: '150', visible: false},
updateTime:{ label: `修改时间`, minWidth: '150', visible: false}
},
config: {
searcherForm: [
{label: '交换机名称', prop: 'roleName', type: 'selset', options: []}
],
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:topology:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'resource:topology:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'resource:topology:export'},
{content: '拓扑展示', fnCode: 'echarts', type: 'warning', icon: 'el-icon-picture-outline-round', hasPermi: 'resource:topology:echarts'},
],
line: [
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'resource:topology:edit'},
]
}
}
}
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
listTopology(this.addDateRange(this.queryParams)).then(response => {
this.roleList = response.rows;
this.queryParams.total = response.total;
this.loading = false;
})
},
// 处理子组件传递的新值
handleValueChange(newValue) {
// 父组件更新自身数据,实现同步
this.showSearch = newValue;
// console.log('父组件拿到新值:', newValue);
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryRef");
this.handleQuery();
},
callback(result, rowData, selectChange) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'add':
this.$router.push({
path:'/resource/topology/edit/index'});
break;
case 'edit':
this.$router.push({
path:'/resource/topology/edit/index',
query:{
id: rowData.id
}
});
break;
case 'delete':
this.$modal.confirm('是否确认删除数据项?').then(function() {
return delTopology(selectChange)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功")
}).catch(() => {});
break;
case 'echarts':
this.$router.push({
path:'/resource/topology/gplot/index',
query:{
id: rowData.id
}
});
break;
case 'export':
// let dataList = [];
// Object.keys(this.columns).forEach(item => {
// if (item.visible) {
// dataList.push(item.prop);
// }
// });
// this.download("/system/management/export", {properties: dataList,}, `拓扑管理_${new Date().getTime()}.xlsx`);
let paramsList = Object.assign({}, this.queryParams,rowData);
this.download("system/management/export", paramsList, `拓扑管理_${new Date().getTime()}.xlsx`, null, 'json');
break;
default:
}
}
}
}
}
</script>
<style scoped>
::v-deep .lastBtnSty .el-form-item__content{
margin-left: 10px!important;
}
</style>

View File

@@ -0,0 +1,95 @@
<template>
<div style="padding: 8px 20px 20px;">
<div class="w100 plr-20" style="font-size: 14px">
<div v-for="(item, key, index) of formListTow" class="w50 disInlineBlock p10">
<span class="w50 disInlineBlock">{{item}}</span><span class="w50">{{formValue[key]}}</span>
</div>
</div>
<div v-for="item of resultData" class="w100 mt20 mb20" style="height: 200px;border-top: 1px solid #d8dce5">
<EchartsLine class="w100 h100" :lineData="item.dataVal" :title="item.title" :chartData="(valData) => chartDataEvent(valData, item.fnEvent)"></EchartsLine>
</div>
</div>
</template>
<script setup>
import EchartsLine from "@/components/echartsList/line.vue";
export default {
name: 'FirstMonitor',
components: {EchartsLine},
data() {
return {
formListTow: [],
formValue: {remarks: 'aaa', address: 'aaa', objId: 'aaa', macAddress: 'aaa',
time: 'aaa', sbName: 'aaa', msg: 'aaa', versions: 'aaa', sysName: 'aaa'},
paramsData: {},
resultData: [{
title: '设备CPU使用率(%)',
dataVal: {
titleVal: {textAlign: 'left', left: '1%'},
gridTop: '35%',
legend: {top: '15%', left: '10%'},
lineXData: ['2025-9-1', '2025-9-2', '2025-9-3', '2025-9-4', '2025-9-5', '2025-9-6', '2025-9-7'],
dataList: [{
name: '设备CPU使用率',
data: [120, 132, 101, 134, 90, 230, 210],
}]
}
},{
title: '设备内存使用率(%)',
dataVal: {
titleVal: {textAlign: 'left', left: '1%'},
gridTop: '35%',
legend: {top: '15%', left: '10%'},
lineXData: ['2025-9-1', '2025-9-2', '2025-9-3', '2025-9-4', '2025-9-5', '2025-9-6', '2025-9-7'],
dataList: [{
name: '设备内存使用率',
data: [120, 132, 101, 134, 90, 230, 210],
},{
name: 'CPU运行用户进程所花费的时间',
data: [220, 182, 191, 234, 290, 330, 310]
}]
}
},{
title: '功率',
dataVal: {
titleVal: {textAlign: 'left', left: '1%'},
gridTop: '35%',
legend: {top: '15%', left: '10%'},
lineXData: ['2025-9-1', '2025-9-2', '2025-9-3', '2025-9-4', '2025-9-5', '2025-9-6', '2025-9-7'],
dataList: [{
name: '系统平均功率(mW)',
data: [120, 132, 101, 134, 90, 230, 210],
},{
name: '系统实时功率(mW)',
data: [220, 182, 191, 234, 290, 330, 310]
}]
}
}],
}
},
created() {
// this.paramsData = this.$route && this.$route.query;
this.fnFormList();
// this.switchList();
},
methods: {
// formList集合
fnFormList() {
let formFirst = {
remarks: '系统描述', address: '系统位置', objId: '系统Object ID', macAddress: '系统MAC地址',
time: '系统运行时间', sbName: '设备名称', msg: '系统联系信息', versions: '设备软件版本', sysName: '系统名称'
};
this.formListTow = {...formFirst};
},
chartDataEvent(valData, funcName) {
// 检查函数是否存在,避免报错
if (typeof this[funcName] === 'function') {
// 调用实际函数,并传递参数(如选中的值、当前项)
// this[funcName]({startTime: valData[0], endTime: valData[1]});
} else {
console.warn(`函数 ${funcName} 未定义`);
}
},
}
}
</script>

View File

@@ -0,0 +1,202 @@
<template>
<div class="app-container">
<Form :formList="formList" :config="this.paramsData && this.paramsData.readonly ? {labelWidth: '140px', buttonGroup: []} : {labelWidth: '140px'}" :ruleFormData="ruleForm" @fnClick="callback"></Form>
<div v-if="this.paramsData && this.paramsData.readonly">
<p style="font-size: 1rem;font-weight: 500;border-bottom: 1px solid #ddd;">接口备注信息</p>
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="tableList" @fnClick="callback">
<template #tempHandle="{ row, column }">
<div>
<!-- 非编辑状态显示文本 -->
<template v-if="!row.editStatus">
<span>{{ row.resourceName }}</span>
<el-button icon="el-icon-edit" type="text" @click="rowDataChange(row)"></el-button>
</template>
<template v-else>
<!-- 编辑状态显示输入框 -->
<el-col :span="16">
<el-input v-model="row.resourceName" size="mini"></el-input>
</el-col>
<el-col :span="8">
<el-button size="mini" type="primary" @click="submit(row)">确定</el-button>
<el-button size="mini" @click="cancel(row)">取消</el-button>
</el-col>
</template>
</div>
</template>
</TableList>
</div>
<el-button v-if="this.paramsData && this.paramsData.readonly" style="float: right;margin-top: 12px;margin-left: 10px;" @click="callback({fnCode: 'cancel'})">返回</el-button>
</div>
</template>
<script setup name="Handle">
import Form from '@/components/form/index.vue';
import TableList from '@/components/table/index.vue';
import {addHandle, getHandle, updateHandle,listHandle, delTopology} from "@/api/disRevenue/resource"
export default {
name: 'RegisterHandle',
components: {Form, TableList},
dicts: ['rm_register_resource_type', 'rm_register_online_state','rm_register_version', 'rm_register_security_level', 'rm_register_permission', 'rm_register_encryption'],
data() {
return {
ruleForm: {
resourceVersion: '1',
securityLevel: '2',
rwPermission: '2',
encryption: '2',
switchNum: '3次',
switchWeek: '5秒',
switchOID: '1.3.6.1.2.1.1.5',
// agentWeek: '5秒',
// agentNum: '3次',
// agentOID: '1.3.6.1.2.1.1.5'
},
formList: [],
paramsData: {},
tableList: [],
// 列显隐信息
columns: {
id: { label: `ID`,width: '80'},
resourceName: { label: `接口名称`, slotName: 'tempHandle', visible: true, minWidth: '200'},
hardwareSn: { label: `接口备注`, visible: true, minWidth: '250'},
},
queryParams: {
pageNum: 1,
pageSize: 10,
total: 0
},
editStatus: false,
config: {
colTopHiddenIcon: true, colHiddenCheck: true,
tableButton: {
line: [
{content: '删除', fnCode: 'delete', type: 'text', icon: 'el-icon-delete'},
]
}
},
}
},
created() {
this.paramsData = this.$route && this.$route.query;
if (this.paramsData && this.paramsData.id) {
this.getFormDataList(this.paramsData.id);
} else {
this.fnFormList(this.ruleForm);
}
if(this.paramsData && this.paramsData.readonly) {
this.getList();
}
},
methods: {
rowDataChange(row) {
this.$set(row, 'editStatus', true);
},
getList(){
listHandle(this.addDateRange(this.queryParams)).then(response => {
this.tableList = response.rows;
this.queryParams.total = response.total;
})
},
// formList集合
fnFormList(objVal) {
this.formList = [{
config: {title: '基本信息', readonly: this.paramsData && this.paramsData.readonly},
controls: {
id: {label: 'ID',hidden: true},
switchName: {label: '交换机名称', span: 12, type: 'input', required: true},
hardwareSn: {label: '硬件SN', span: 12, type: 'input'},
switchNum: {label: '交换机心跳检测次数', span: 12, type: 'input', disabled: true},
switchWeek: {label: '交换机心跳检测周期', span: 12, type: 'input', disabled: true},
switchOID: {label: '交换机心跳检测OID', span: 12, type: 'input', disabled: true},
resourceVersion: {label: 'SNMP版本', span: 12, type: 'radio', eventName: 'change', required: true, options: this.dict.type.rm_register_version},
rwPermission: {label: '读写权限', span: 12, type: 'radio', options: this.dict.type.rm_register_permission},
securityLevel: {label: '安全级别', span: 12, type: 'radio', options: this.dict.type.rm_register_security_level, hidden: objVal && objVal.resourceVersion === '1' ? true : false},
encryption: {label: '加密方式', span: 12, type: 'radio', options: this.dict.type.rm_register_encryption, hidden: objVal && objVal.resourceVersion === '1' ? true : false},
teamName: {label: '团体名称', span: 12, type: 'input'},
snmpCollectAddr: {label: 'SNMP采集地址', span: 12, type: 'input',required: true},
snmpCollectPort: {label: 'SNMP采集端口', span: 12, type: 'input',required: true},
resourceUserName: {label: '用户名', span: 12, type: 'input', hidden: objVal && objVal.resourceVersion === '1' ? true : false},
resourcePwd: {label: '密码', span: 12, type: 'input', hidden: objVal && objVal.resourceVersion === '1' ? true : false},
updateTime: {label: '修改时间', span: 12, type: 'date', hidden: this.paramsData && this.paramsData.readonly ? false : true},
createTime: {label: '创建时间', span: 12, type: 'date', hidden: this.paramsData && this.paramsData.readonly ? false : true},
onlineStatus: {label: '在线状态', span: 12, type: 'select', options: this.dict.type.rm_register_online_state, hidden: this.paramsData && this.paramsData.readonly ? false : true},
resourceType: {label: '交换机类型', span: 12, type: 'select', required: true, options: this.dict.type.rm_register_resource_type},
showTime: {label: '上机时间', span: 12, type: 'date', hidden: this.paramsData && this.paramsData.readonly ? false : true},
}
}];
},
// 获取详情
getFormDataList(id) {
getHandle(id).then(val => {
this.ruleForm = val && val.data;
this.fnFormList(this.ruleForm);
}).catch(() => {
this.fnFormList(this.ruleForm);
this.$modal.msgError("操作失败")
});
},
submit(rowData) {
this.$set(rowData, 'editStatus', false);
// updateHandle(rowData).then(response => {
// this.$set(rowData, 'editStatus', false);
// this.getList();
// this.$modal.msgSuccess(response.msg);
// }).catch(() => {
// this.$modal.msgError("操作失败");
// });
},
// 取消列表修改
cancel(rowData) {
this.$set(rowData, 'editStatus', false);
},
// 监听事件
callback(result, dataVal, selectChange) {
console.log('result===',result);
if (result && result.fnCode) {
switch (result.fnCode) {
case 'resourceVersion':
if (dataVal === '2') {
this.formList[0].controls.securityLevel['hidden'] = false;
this.formList[0].controls.encryption['hidden'] = false;
this.formList[0].controls.resourceUserName['hidden'] = false;
this.formList[0].controls.resourcePwd['hidden'] = false;
} else {
this.formList[0].controls.securityLevel['hidden'] = true;
this.formList[0].controls.encryption['hidden'] = true;
this.formList[0].controls.resourceUserName['hidden'] = true;
this.formList[0].controls.resourcePwd['hidden'] = true;
}
break;
case 'submit':
let fnType = addHandle;
if (dataVal && dataVal.id) {
fnType = updateHandle;
}
fnType(dataVal).then(response => {
this.$modal.msgSuccess(response.msg);
this.$router.push("/resource/switchRegister");
}).catch(() => {
this.$modal.msgError("操作失败")
});
break;
case 'cancel':
this.$router.push("/resource/switchRegister");
break;
case 'delete':
this.$modal.confirm('是否确认删除数据项?').then(function() {
return delTopology(selectChange)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功")
}).catch(() => {});
break;
default:
}
}
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,239 @@
<template>
<div class="app-container pageTopForm">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" size="small" label-width="auto">
<el-col :span="6">
<el-form-item label="交换机名称" prop="resourceName">
<el-input
v-model="queryParams.resourceName"
placeholder="请输入交换机名称"
clearable
@keyup.enter.native="handleQuery"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="交换机在线状态" title="交换机在线状态" prop="switchStatus">
<el-select
v-model="queryParams.switchStatus"
placeholder="请选择交换机在线状态"
clearable>
<el-option
v-for="dict in dict.type.rm_register_online_state"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item class="lastBtnSty">
<el-button type="primary" size="mini" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-form>
<!-- 表格数据 -->
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="roleList" @fnClick="callback" @fnRenderList="getList" @value-change="handleValueChange">
<!-- 资源类型 -->
<template #tempType="{ row, column }">
<dict-tag :options="dict.type.rm_register_resource_type" :value="row.resourceType"/>
</template>
<!-- 端口 -->
<template #tempPort="{ row, column }">
<dict-tag :options="dict.type.rm_register_port" :value="row.resourcePort"/>
</template>
<!-- 协议 -->
<template #tempProtocol="{ row, column }">
<dict-tag :options="dict.type.rm_register_protocol" :value="row.protocol"/>
</template>
<!-- 注册状态 -->
<template #tempStatus="{ row, column }">
<dict-tag :options="dict.type.rm_register_status" :value="row.registrationStatus"/>
</template>
<!-- 在线状态 -->
<template #tempOnlineStatus="{ row, column }">
<dict-tag :options="dict.type.rm_register_online_state" :value="row.onlineStatus"/>
</template>
</TableList>
<!-- 弹窗 -->
<el-dialog title="添加监控策略" :visible.sync="open" width="1000px" append-to-body>
<MonitorStrategy :open="open" @dialogResult="fnDialogResult"></MonitorStrategy>
</el-dialog>
</div>
</template>
<script setup name="Register">
import {listHandle, updateregisterType} from '@/api/disRevenue/resource';
import TableList from '@/components/table/index.vue';
import MonitorStrategy from './monitorStrategy';
export default {
name: 'RegisterIndex',
components: {TableList, MonitorStrategy},
dicts: ['rm_register_resource_type', 'rm_register_protocol', 'rm_register_status', 'rm_register_port', 'rm_register_online_state'],
data() {
return {
open: false,
roleList: [],
loading: true,
showSearch: true,
ids: [],
single: true,
meltiple: true,
// 列显隐信息
columns: {
id: { label: `ID`,width: '80'},
switchName: { label: `交换机名称`, visible: true, minWidth: '200'},
hardwareSn: { label: `硬件SN`,minWidth: '250'},
resourceType: { label: `交换机类型`, minWidth: '100', slotName: 'tempType'},
snmpCollectAddr: { label: `SNMP采集地址`, visible: true, minWidth: '150'},
snmpCollectPort: { label: `SNMP采集端口`, visible: true, minWidth: '150'},
onlineStatus: { label: `在线状态`, slotName: 'tempOnlineStatus', minWidth: '120', visible: true },
showTime:{ label: `上机时间`,minWidth: '160'},
updateTime:{ label: `修改时间`,minWidth: '160'},
createTime:{ label: `创建时间`,minWidth: '160'},
agentNum: { label: `交换机心跳检测次数`, minWidth: '180'},
agentWeek: { label: `交换机心跳检测周期`, minWidth: '180'},
agentOID: { label: `交换机心跳检测OID`, minWidth: '180'},
protocol: { label: `SNMP版本`, minWidth: '80'},
rwPermission: { label: `读写权限`, minWidth: '120'},
securityLevel: { label: `安全级别`, minWidth: '120'},
encryption: { label: `加密方式`, minWidth: '120'},
teamName: { label: `团体名称`, minWidth: '120'},
resourceUserName: { label: `用户名`, minWidth: '120'},
resourcePwd: { label: `密码`, minWidth: '120'}
},
config: {
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'resource:switchRegister:add'},
{content: '接口备注', fnCode: 'portRemarks', type: 'success', icon: 'el-icon-plus', hasPermi: 'resource:switchRegister:portRemarks'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'resource:switchRegister:export'},
],
line: [
{content: '图形监控', fnCode: 'echartView', type: 'text', icon: 'el-icon-data-analysis', hasPermi: 'resource:switchRegister:graphicAnalysis'},
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'resource:switchRegister:edit'},
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'resource:switchRegister:details'},
{title: ' 执行策略', more: [
{content: '执行监控策略', fnCode: 'monitorStrategy', type: 'text', icon: 'el-icon-circle-check', hasPermi: 'resource:switchRegister:monitorStrategy'},
]
},{},{}
// {content: '注册', fnCode: 'enroll', showName: 'registrationStatus', showVal: '0', type: 'text', icon: 'el-icon-circle-check', hasPermi: 'resource:register:enroll'},
// {content: '取消注册', fnCode: 'unenroll', showName: 'registrationStatus', showVal: '1', type: 'text', icon: 'el-icon-circle-close', hasPermi: 'resource:register:unenroll'},
]
}
},
queryParams: {
pageNum: 1,
pageSize: 10,
total: 0
}
}
},
created() {
this.getList();
},
methods: {
// 处理子组件传递的新值
handleValueChange(newValue) {
// 父组件更新自身数据,实现同步
this.showSearch = newValue;
// console.log('父组件拿到新值:', newValue);
},
/** 查询角色列表 */
getList() {
this.loading = true
listHandle(this.addDateRange(this.queryParams)).then(response => {
this.roleList = response.rows;
this.queryParams.total = response.total;
this.loading = false;
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.$refs['queryRef'].resetFields();
this.queryParams = {pageNum: 1, pageSize: 10,total: 0};
// this.resetForm("queryRef");
this.handleQuery();
},
/** 多选框选中数据 */
handleSelectionChange(selection) {
this.ids = selection.map(item => item.roleId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
fnDialogResult(res){
this.open = false;
},
callback(result, rowData, selectChange) {
console.log('result==',result);
if (result && result.fnCode) {
switch (result.fnCode) {
case 'add':
this.$router.push("/resource/switchRegister/edit/index");
break;
case 'portRemarks':
if (selectChange && selectChange.length <= 0) {
this.$modal.msgWarning("请选择数据!");
return;
}
this.$router.push({
path: '/resource/switchRegister/portRemarks',
query: {ids: selectChange}
});
break;
case 'edit':
this.$router.push({
path:'/resource/switchRegister/edit/index/',
query: {id: rowData.id}
});
break;
case 'details':
this.$router.push({
path:'/resource/switchRegister/edit/index/',
query: {id: rowData.id, readonly: true}
});
break;
case 'echartView':
this.$router.push({
path:'/resource/switchRegister/monitorChart'
});
break;
case 'monitorStrategy':
this.open = true;
break;
case 'export':
// let dataList = [];
// Object.keys(this.columns).forEach(item => {
// if (item.visible) {
// dataList.push(item.prop);
// }
// });
// this.download("/system/registration/export", {properties: dataList,}, `资源管理_${new Date().getTime()}.xlsx`);
let paramsList = Object.assign({}, this.queryParams,rowData);
this.download("system/registration/export", paramsList, `资源注册_${new Date().getTime()}.xlsx`, null, 'json');
break;
default:
}
}
}
}
}
</script>
<style scoped>
::v-deep .lastBtnSty .el-form-item__content{
margin-left: 10px!important;
}
::v-deep .el-dialog__body {
padding: 0px!important;
}
</style>

View File

@@ -0,0 +1,41 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="监控项" name="first">
<FirstMonitor></FirstMonitor>
</el-tab-pane>
<el-tab-pane label="自动发现项" name="second">
<template v-if="activeName === 'second'">
<SecondAutoFind></SecondAutoFind>
</template>
</el-tab-pane>
</el-tabs>
<div style="float: right;margin-top: 20px;">
<el-button type="primary" @click="goBack">返回</el-button>
</div>
</div>
</template>
<script>
import FirstMonitor from "./firstMonitor";
import SecondAutoFind from "./secondAutoFind";
export default {
name: "MonitorChart",
components: {FirstMonitor, SecondAutoFind},
data() {
return {
activeName: 'first',
}
},
methods: {
handleClick(tab, event) {},
goBack() {
this.$router.push("/resource/switchRegister");
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,239 @@
<template>
<div class="app-container">
<div style="width: 80%; margin: auto;">
<Form ref="formRef" :formList="formList" :config="{labelWidth: '140px',buttonGroup: []}" :ruleFormData="ruleFormData" @fnClick="callback"></Form>
</div>
<div>
<h3 style="background: #d4e3fc;padding: 15px 10px;">策略内容</h3>
<el-tabs v-model="activeName" class="plr-20">
<el-tab-pane label="监控项" name="first">
<div v-for="item of firstData">
<div class="plr-50">
<div v-for="city of item.checkList" class="w100 mt10 mb10 disInlineBlock fontSize15">
<div class="disInlineBlock w50">
<span style="width: 200px" class="disInlineBlock">{{city.id}}--{{ city.metricKey }}</span>
<span>{{city.metricName}}</span>
</div>
<div class="disInlineBlock" style="color: #606266">
采集周期<el-select v-model="city['time']" placeholder="请选择" clearable>
<el-option v-for="val in timeOptions" :key="val.value" :label="val.label" :value="val.value"></el-option>
</el-select>
</div>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="自动发现项" name="second">
<el-collapse v-model="activeTwoName">
<el-collapse-item v-for="(item,key,index) of secondData" :title="item.title" :name="index">
<template slot="title">
<span class="disInlineBlock" style="width: 15%;">{{item.title}}</span>
<div style="font-size: 13px;margin-left: 10%;">
采集周期<el-select v-model="item['time']" id="selDisabled" :disabled="key === 'switchNet' ? true : false" clearable placeholder="请选择">
<el-option v-for="val in timeOptions" :key="val.value" :label="val.label" :value="val.value"></el-option>
</el-select>
</div>
</template>
<div class="plr-50">
<div v-for="city of item.checkList" class="w100 mt10 mb10 disBlock fontSize15">
<span style="width: 300px" class="disInlineBlock">{{city.id}}--{{city.metricKey}}</span>
<span>{{city.metricName}}</span>
</div>
</div>
</el-collapse-item>
</el-collapse>
</el-tab-pane>
</el-tabs>
</div>
<el-button style="float: right;margin-top: 12px;margin-left: 10px;" @click="cancel">取消</el-button>
<el-button type="primary" style="float: right;margin-top: 12px;" @click="submit">提交</el-button>
</div>
</template>
<script>
import Form from '@/components/form/index.vue';
export default {
name: "MonitorStrategy",
components: {Form},
dicts: ['rm_register_resource_type', 'collection_cycle'],
props: {
open: {
type: Boolean,
default: false
}
},
watch: {
open: {
handler(val) {
if (!val) {
// 清空form
this.$refs['formRef'].$refs.ruleForm.resetFields();
}
},
deep: true,
immediate: true
},
},
data() {
return {
activeName: 'first',
activeTwoName: [0,1,2,3,4],
timeOptions: [],
ruleFormData: {},
formList: [],
firstData: [
{checkList: [
{id: '1', metricKey: 'sysDescr', metricName: '系统描述', time: ''},
{id: '2', metricKey: 'sysObjectID', metricName: '系统ObjectID', time: ''},
{id: '3', metricKey: 'sysUpTime', metricName: '系统运行时间', time: ''},
{id: '4', metricKey: 'hwStackSystemMac', metricName: '系统MAC地址', time: ''},
{id: '5', metricKey: 'entPhysicalSoftwareRev', metricName: '设备软件版本', time: ''},
{id: '6', metricKey: 'hwEntityMemUsage', metricName: '设备内存使用率(%)', time: ''},
]}
],
secondData: {
switchNet: {title: '网络端口发现', time: '300',
checkList: [
{id: '11', metricKey: 'ifIndex', metricName: '端口索引'},
{id: '12', metricKey: 'ifHCOutOctets', metricName: '端口发送Bites总数'},
{id: '13', metricKey: 'ifRevRate', metricName: '端口实时接收速率(bites/sec)'},
{id: '14', metricKey: 'ifSentRate', metricName: '端口实时发送速率(bites/sec)'},
]
},
switchModule: {title: '光模块发现', time: '',
checkList: [
{id: '15', metricKey: 'fiberEntIndex', metricName: '光模块端口索引'},
{id: '16', metricKey: 'hwEntityOpticalTxLowThreshold', metricName: '光模块发送光衰阈值(dBm)'},
{id: '17', metricKey: 'hwEntityOpticalRxLowThreshold', metricName: '光模块接收光衰阈值(dBm)'},
{id: '18', metricKey: 'hwEntityOpticalTxPower', metricName: '光模块发送功率(dBm)'},
]
},
switchMpu: {title: 'MPU发现', time: '',
checkList: [
{id: '19', metricKey: 'mpuEntIndex', metricName: 'MPU索引'},
{id: '20', metricKey: 'mpuEntityCpuUsage', metricName: 'MPU的CPU使用率'},
{id: '21', metricKey: 'mpuEntityMemUsage', metricName: 'MPU的内存使用率'},
{id: '22', metricKey: 'mpuPhysicalSoftwareRev', metricName: 'MPU的操作系统'},
]
},
switchPwr: {title: '电源发现', time: '',
checkList: [
{id: '23', metricKey: 'pwrEntIndex', metricName: '电源索引'},
{id: '24', metricKey: 'pwrName', metricName: '电源名称'},
{id: '25', metricKey: 'pwrEntityPwrState', metricName: '电源状态'},
{id: '26', metricKey: 'pwrEntityPwrCurrent', metricName: '电源电流(mA)'},
]
},
switchFan: {title: '风扇发现', time: '',
checkList: [
{id: '27', metricKey: 'fanEntIndex', metricName: '风扇索引'},
{id: '28', metricKey: 'pwrEntityPwrState', metricName: '电源状态'},
{id: '29', metricKey: 'pwrEntityPwrCurrent', metricName: '电源电流(mA)'},
{id: '30', metricKey: 'pwrEntityPwrVoltage', metricName: '电源电压(mV)'},
]
},
}
}
},
created() {
console.log('dddd===');
this.timeOptions = this.dict.type.collection_cycle;
this.fnFormList();
},
methods: {
// formList集合
fnFormList(objVal) {
this.formList = [{
config: {},
controls: {
id: {label: 'ID',hidden: true},
switchName: {label: '策略名称', span: 24, type: 'input', required: true},
hardwareSn: {label: '描述', span: 24, type: 'textarea'},
resourceType: {label: '交换机类型', span: 24, type: 'select', required: true, options: this.dict.type.rm_register_resource_type},
bushu: {label: '部署设备', span: 24, type: 'textarea', rows: 15},
}
}];
},
// form验证
fnFormValid() {
return new Promise((resolve) => {
this.ruleFormData = {};
const formValid = this.$refs.formRef.$refs.ruleForm;
// 3. 操作form如验证
formValid.validate((valid) => {
if (valid) {
this.ruleFormData = formValid.model;
resolve(true);
} else {
resolve(false);
}
});
});
},
async submit() {
if (!await this.fnFormValid()) return;
// 监控项
let idsList = [];
this.firstData.forEach(item => {
item && item.checkList.forEach(ids => {
if (ids && ids.time) {
idsList.push({id: ids.id, collectionCycle: ids.time});
}
});
});
// 自动发现项
let autoIds = [];
Object.keys(this.secondData).forEach(key => {
if (this.secondData[key].time) {
this.secondData[key] && this.secondData[key].checkList.forEach(ids => {
autoIds.push({id: ids.id, collectionCycle: this.secondData[key].time});
});
}
});
console.log('ruleFormData===',this.ruleFormData);
console.log('idsList===',idsList);
console.log('autoIds===',autoIds);
this.$emit("dialogResult", {open: false});
},
cancel() {
this.$emit("dialogResult", {open: false});
},
// 监听事件
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'submit':
let fnType = addHandle;
if (dataVal && dataVal.id) {
fnType = updateHandle;
}
fnType(dataVal).then(response => {
this.$modal.msgSuccess(response.msg);
this.$router.push("/resource/switchRegister");
}).catch(() => {
this.$modal.msgError("操作失败")
});
break;
case 'cancel':
this.$router.push("/resource/switchRegister");
break;
default:
}
}
},
}
}
</script>
<style scoped>
::v-deep #selDisabled{
color: #303133!important;
}
::v-deep .el-collapse-item__header {
background-color: #d4e3fc!important;
/*color: #fff!important;*/
padding-left: 20px;
font-size: 1rem;
}
</style>

View File

@@ -0,0 +1,130 @@
<template>
<div class="app-container">
<Form :formList="formList" :ruleFormData="ruleForm" :config="{labelWidth: '140px'}" @fnClick="callback"></Form>
</div>
</template>
<script setup>
import Form from '@/components/form/index.vue';
import {listHandle, resNameBtType, addTopology, getTopology, updateTopology, postInterFaceName} from "@/api/disRevenue/resource"
export default {
name: 'PortRemarks',
components: {Form},
dicts: ['rm_topology_type'],
data() {
return {
loading: false,
ruleForm: {},
formList: [],
paramsData: {},
switchNameList: [],
interfaceNameList: [],
}
},
created() {
this.paramsData = this.$route && this.$route.query;
if (this.paramsData && this.paramsData.id) {
this.getFormDataList(this.paramsData.id);
} else {
this.switchList();
}
this.fnFormList();
},
methods: {
// formList集合
fnFormList(objVal) {
this.formList = [{
config: {title: '基本信息',labelWidth: '140px', colSpan: 'disBlock'},
controls: {
id: {label: 'ID',hidden: true},
switchName: {label: '交换机名称', span: 18, type: 'select', eventName: 'change', options:[], required: true},
interfaceName: {label: '交换机端口名称', span: 18, type: 'select', options:[], required: true},
serverPort: {label: '端口备注', span: 18, type: 'textarea', required: true},
}
}];
},
// 获取交换机下拉
switchList() {
resNameBtType({resourceType: 2}).then(val => {
this.switchNameList = val && val;
this.formList[0].controls.switchName['options'] = val && val.map(item => {
if (this.paramsData && this.paramsData.id) {
if (item.resourceName === this.ruleForm.switchName) {
this.fnInterFaceNameList({switchIp: item.ipAddress});
}
}
return Object.assign({label: item.resourceName, value: item.resourceName});
});
});
},
// 接口名称
fnInterFaceNameList(val) {
postInterFaceName(Object.assign({},{resourceType: 2}, val)).then(res => {
this.interfaceNameList = res;
this.formList[0].controls.interfaceName['options'] = res && res.map(item => {
return Object.assign({label: item.interfaceName, value: item.id});
});
});
},
// 获取详情
getFormDataList(id) {
getTopology(id).then(val => {
this.ruleForm = val && val.data;
this.switchList();
}).catch(() => {
this.$modal.msgError("操作失败")
});
},
// 监听事件
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'switchName':
let switchIp = '';
this.switchNameList.find(item => {
if (item.resourceName === dataVal) {
switchIp = item.ipAddress;
}
});
this.fnInterFaceNameList({switchIp: switchIp});
break;
case 'submit':
this.switchNameList.find(item => {
if (item.resourceName === dataVal['switchName'] || item.resourceName === dataVal['switchName']) {
dataVal['switchName'] = item.resourceName;
dataVal['switchIpAddress'] = item.ipAddress;
dataVal['switchSn'] = item.hardwareSn;
}
});
this.interfaceNameList.find(item => {
if (item.id === dataVal['interfaceName'] || item.interfaceName === dataVal['interfaceName']) {
dataVal['interfaceName'] = item.interfaceName;
}
});
let fnType = addTopology;
if (dataVal && dataVal.id) {
fnType = updateTopology;
}
if(this.loading) return;
this.loading = true;
fnType(dataVal).then(response => {
this.$modal.msgSuccess(response.msg);
this.$router.push("/resource/switchRegister")
this.loading = false;
}).catch(() => {
this.$modal.msgError("操作失败")
});
break;
case 'cancel':
this.$router.push("/resource/switchRegister");
break;
default:
}
}
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,156 @@
<template>
<div style="padding: 8px 20px 20px;">
<el-collapse v-model="activeNames">
<el-collapse-item v-for="(val,key, index) of linuxSystem" :title="val.title" :name="index">
<div class="mt10 w100">
<div class="w100 plr-20" style="font-size: 14px">
<div v-for="(item,key,index) of val.formList" class="w50 disInlineBlock p10">
<span class="w50 disInlineBlock">{{item}}</span><span class="w50">{{val.formModel[key]}}</span>
</div>
</div>
<div v-for="item of val.echartList" class="w100 mt20 mb20" style="height: 200px;border-top: 1px solid #d8dce5">
<EchartsLine class="w100 h100" :lineData="item.dataVal" :title="item.title" :chartData="(valData) => chartDataEvent(valData, item.fnEvent)"></EchartsLine>
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</template>
<script setup>
import EchartsLine from "@/components/echartsList/line.vue";
export default {
name: 'SecondAutoFind',
components: {EchartsLine},
data() {
return {
activeNames: [0, 1,2,3,4],
echartData: {
title: 'GE1/0/1的丢包数',
dataVal: {
titleVal: {textAlign: 'left', left: '1%'},
gridTop: '35%',
legend: {top: '15%', left: '10%'},
lineXData: ['2025-9-1', '2025-9-2', '2025-9-3', '2025-9-4', '2025-9-5', '2025-9-6', '2025-9-7'],
dataList: [{
name: '入站丢包',
data: [120, 132, 101, 134, 90, 230, 210],
},{
name: '出站丢包',
data: [220, 182, 191, 234, 290, 330, 310]
}]
}
},
linuxSystem: {
net: {
title: '网络端口GE1/0/1',
formList: {name: '端口名称', type: '端口类型', status: '端口状态', mbps: '端口适配速率(Mbps)'},
formModel: {name: 'GE1/0/1', type: 'ETHNET', status: 'up', mbps: '1000'},
config: {labelWidth: '160px', buttonGroup: []},
echartFors: [
{title: 'GE1/0/1的丢包数', oneName: '入站丢包', twoName: '出站丢包'},
{title: 'GE1/0/1的Bites总数', oneName: '端口发送Bites总数', twoName: '端口接收Bites总数'},
{title: 'GE1/0/1的错误包数量', oneName: '错误的入站数据包数量', twoName: '错误的出战数据包数量'},
{title: 'GE1/0/1的网络速率(bites/sec)', oneName: '端口实时接收速率(bites/sec)', twoName: '端口实时发送速率(bites/sec)'},
],
echartList: []
},
light: {
title: '光模块sabc',
formList: {name: '光模块端口名称'},
formModel: {name: 'sabc'},
config: {buttonGroup: []},
echartFors: [
{title: 'sabc的光衰阈值(dBm)', oneName: '光模块发送光衰阈值', twoName: '光模块接收光衰阈值'},
{title: 'sabc的功率(dBm)', oneName: '光模块接收功率', twoName: '光模块发送功率'}
],
echartList: []
},
mpu: {
title: 'MPU1',
formList: {name: 'MPU名称', system: 'MPU的操作系统'},
formModel: {name: 'MPU1', system: 'xxxx'},
config: {buttonGroup: []},
echartFors: [
{title: 'MPU1的CPU使用率(%)', oneName: 'CPU利用率'},
{title: 'MPU1的内存使用率(%)', oneName: '内存利用率'},
{title: 'MPU1的温度(°C)', oneName: '温度'},
],
echartList: []
},
pw: {
title: '电源PW1',
formList: {name: '电源名称', status: '电源状态'},
formModel: {name: 'PW1', status: '正在供电'},
config: {buttonGroup: []},
echartFors: [
{title: '电源电流(mA)', oneName: '电源电流'},
{title: '电源电压(mV)', oneName: '电源电压'}
],
echartList: []
},
fan: {
title: '风扇FAN1',
formList: {name: '风扇名称', status: '风扇状态'},
formModel: {name: 'FAN1', status: 'xxx'},
config: {buttonGroup: []},
echartFors: [],
echartList: []
}
},
}
},
created() {
// this.$nextTick(() => {
this.secondList();
// });
},
methods: {
deepClone(obj) {
return JSON.parse(JSON.stringify(obj))
},
// 第二节点 自动发现项
secondList(){
Object.keys(this.linuxSystem).forEach((key,index) => {
// 用可选链简化空值判断,避免报错
const targetModule = this.linuxSystem[key];
if (!targetModule?.echartFors?.length) return; // 无图表模板则跳过
targetModule.echartFors.forEach(item => {
// 深拷贝基础配置,确保每个图表配置独立
const chartData = this.deepClone(this.echartData);
// 3. 替换图表标题(模板有标题则用模板,无则保留基础配置的标题)
if (item.title) chartData.title = item.title;
if (item.twoName) {
chartData.dataVal.dataList[1].name = item.twoName;
} else {
chartData.dataVal.dataList.splice(1,1);
}
if (item.oneName) {
chartData.dataVal.dataList[0].name = item.oneName;
} else {
chartData.dataVal.dataList.splice(0,1);
}
this.linuxSystem[key].echartList.push(chartData);
});
});
},
chartDataEvent(valData, funcName) {
// 检查函数是否存在,避免报错
if (typeof this[funcName] === 'function') {
// 调用实际函数,并传递参数(如选中的值、当前项)
// this[funcName]({startTime: valData[0], endTime: valData[1]});
} else {
console.warn(`函数 ${funcName} 未定义`);
}
}
}
}
</script>
<style scoped>
::v-deep .el-collapse-item__header {
background-color: #d4e3fc!important;
/*color: #fff!important;*/
padding-left: 20px;
font-size: 1rem;
}
</style>

View File

@@ -165,7 +165,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/resource/topology");
break;
default:

View File

@@ -72,7 +72,7 @@
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
case 'cancel':
this.$router.push("/problemRecord");
break;
default:

File diff suppressed because it is too large Load Diff