开发资源远程管理模块、AGENT更新模块、服务器脚本策略

This commit is contained in:
康冉冉
2025-09-22 10:39:04 +08:00
parent b1166f5187
commit 2ab6c030eb
14 changed files with 1201 additions and 5 deletions

View File

@@ -89,6 +89,9 @@ div:focus {
.p20 {
padding: 20px;
}
.m0Auto {
margin: 0 auto;
}
.mtb10 {
margin: 10px 0;
}

View File

@@ -80,6 +80,7 @@
series = [{
data: dataXY.data,
type: 'line',
smooth: true,
// areaStyle: { // 阴影
// color: 'rgba(140, 158, 217, 1)'
// }

View File

@@ -7,10 +7,11 @@
<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
:key="index"
:label="formVal.label + ''"
:title="formVal.label"
:prop="key"
:required="formVal.required">
<template #label>
<span :title="formVal.label">{{formVal.label ? formVal.label + '' : ''}}</span>
</template>
<template v-if="formVal.type === 'input'">
<el-input
v-model="ruleForm[key]"
@@ -34,6 +35,7 @@
<template v-else-if="formVal.type === 'select'">
<el-select
v-model="ruleForm[key]"
:multiple="formVal.multiple"
:disabled="toBoolean(formVal.disabled || formItem.config.readonly)"
:placeholder="toBoolean(formVal.disabled || formItem.config.readonly) ? null : formVal.placeholder || `请输入${formVal.label}`"
:clearable="formVal.clearable !== false"
@@ -55,6 +57,7 @@
{{ option.label }}
</el-radio>
</el-radio-group>
<br/><span class="warningCol">{{formVal.warningTitle}}</span>
</template>
<template v-else-if="formVal.type === 'checkbox'">
@@ -68,6 +71,15 @@
</el-checkbox-group>
</template>
<template v-else-if="formVal.type === 'time'">
<el-time-picker
v-model="ruleForm[key]"
:disabled="toBoolean(formVal.disabled || formItem.config.readonly)"
:placeholder="toBoolean(formVal.disabled || formItem.config.readonly) ? null : formVal.placeholder || `请输入${formVal.label}`"
@[formVal.eventName]="(val) => handleChange(key,val,formVal)"
></el-time-picker>
</template>
<template v-else-if="formVal.type === 'date'">
<el-date-picker
v-model="ruleForm[key]"
@@ -129,7 +141,7 @@
<!-- 自定义插槽,用于特殊类型的表单控件 -->
<template v-else-if="formVal.slotName">
<slot :name="formVal.slotName" :model="ruleForm[key]" :field="formVal" :formData="ruleForm"></slot>
<slot :name="formVal.slotName" :field="formVal"></slot>
</template>
</el-form-item>
</el-col>
@@ -267,5 +279,8 @@
text-overflow: ellipsis;
white-space: nowrap;
}
.warningCol {
color: #ED7B2F;
}
</style>

View File

@@ -12,6 +12,17 @@
<!-- 表格数据 -->
<el-table v-loading="loading" :data="tableList" ref="selChangeList" :key="tableKey" highlight-selection-row @selection-change="handleSelectionChange">
<el-table-column v-if="!(config && config.colHiddenCheck)" fixed="left" type="selection" width="55" align="center" />
<!-- 展开列内容 -->
<el-table-column v-if="config && config.expand" type="expand">
<template #default="props">
<slot
name="tableExpand"
:row="props.row"
:rowIndex="props.$index"
:props="props"
></slot>
</template>
</el-table-column>
<template v-for="(column, key, index) of columns">
<el-table-column v-if="column && column.visible" :label="column.label" :key="key" :prop="key" :width="column.width" :min-width="column.minWidth || '100px'" align="left" :show-overflow-tooltip="true">
<!-- 插槽 自定义列表表头数据格式 -->

View File

@@ -457,6 +457,51 @@ export const dynamicRoutes = [
}
]
},
// 服务器脚本策略
{
path: '/disRevenue/resource/serverScript/details',
component: Layout,
hidden: true,
permissions: ['disRevenue:resource:serverScript:details'],
children: [
{
path: ':id?',
component: () => import('@/views/disRevenue/resource/serverScript/serverScriptDetails'),
name: 'serverScriptDetails',
meta: { title: '服务器脚本策略信息', activeMenu: '/disRevenue/resource/serverScript' }
}
]
},
// 资源远程管理
{
path: '/disRevenue/resource/remoteManage/view',
component: Layout,
hidden: true,
permissions: ['disRevenue:resource:remoteManage:view'],
children: [
{
path: ':id?',
component: () => import('@/views/disRevenue/resource/remoteManage/remoteManageView'),
name: 'remoteManageView',
meta: { title: '文件管理信息', activeMenu: '/disRevenue/resource/remoteManage' }
}
]
},
// agent更新
{
path: '/disRevenue/resource/agentUpdate/view',
component: Layout,
hidden: true,
permissions: ['disRevenue:resource:agentUpdate:view'],
children: [
{
path: ':id?',
component: () => import('@/views/disRevenue/resource/agentUpdate/agentUpdateView'),
name: 'agentUpdateView',
meta: { title: '文件管理信息', activeMenu: '/disRevenue/resource/agentUpdate' }
}
]
},
// agent采集数据
{
path: '/agentCollect/cpuData/view',

View File

@@ -0,0 +1,177 @@
<template>
<div class="app-container pageTopForm">
<el-form :model="queryParams" ref="queryRef" size="small" v-show="showSearch" label-width="auto">
<el-col :span="8">
<el-form-item label="搜索" prop="switchName">
<el-input
v-model="queryParams.switchName"
placeholder="请输入资源名称/内网IP地址"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="更新结果" prop="bandwidthType">
<el-select
v-model="queryParams.bandwidthType"
placeholder="请选择更新结果"
clearable>
<el-option
v-for="dict in dict.type.eps_bandwidth_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item class="lastBtnSty">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-form>
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="tableList" @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 {listMonitorTemp, delMonitorTemp} from "@/api/disRevenue/resource"
export default {
name: 'AgentUpdate',
components: {TableList},
dicts: ['rm_topology_type','eps_bandwidth_type'],
data() {
return {
loading: true,
showSearch: true,
tableList: [],
queryParams: {
total: 0,
pageNum: 1,
pageSize: 10
},
// 列显隐信息
columns: {
id: { label: `ID`,width: '50'},
sn: { label: `硬件SN`, minWidth: '150'},
switchName: { label: `资源名称`, minWidth: '250', visible: true },
switchSn: { label: `内网IP`,minWidth: '100'},
interfaceName: { label: `AGENT版本`,minWidth: '150', visible: true },
type: { label: `状态`, minWidth: '100' },
serverName: { label: `定义更新频率`,minWidth: '200'},
connectedDeviceType: { label: `定义更新时间`,minWidth: '150', visible: true },
connected: { label: `文件目录`,minWidth: '200'},
conType: { label: `最后一次更新结果`,minWidth: '160', visible: true},
createTime: { label: `最后一次更新时间`,minWidth: '160', visible: true},
},
config: {
searcherForm: [
{label: '模版名称', prop: 'roleName', type: 'selset', options: []}
],
tableButton: {
top: [
{content: '配置更新策略', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'disRevenue:resource:agentUpdate:add'},
],
line: [
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'disRevenue:resource:agentUpdate:details'},
{content: '修改更新策略', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'disRevenue:resource:agentUpdate:edit'},
{content: '手动更新', fnCode: 'update', type: 'text', icon: 'el-icon-refresh-right', hasPermi: 'disRevenue:resource:agentUpdate:update'},
{},{}
]
}
}
}
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
listMonitorTemp(this.queryParams).then(response => {
this.tableList = 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:'/disRevenue/resource/agentUpdate/view'});
break;
case 'edit':
this.$router.push({
path:'/disRevenue/resource/agentUpdate/view',
query:{
id: rowData.id
}
});
break;
case 'details':
this.$router.push({
path:'/disRevenue/resource/agentUpdate/view',
query:{
id: rowData.id,
readonly: true
}
});
break;
case 'delete':
this.$modal.confirm('是否确认删除数据项?').then(function() {
return delMonitorTemp(selectChange)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功")
}).catch(() => {});
break;
case 'export':
// let dataList = [];
// Object.keys(this.columns).forEach(item => {
// if (item.visible) {
// dataList.push(item.prop);
// }
// });
// this.download("/system/alarmManage/export", {properties: dataList,}, `拓扑管理_${new Date().getTime()}.xlsx`);
let paramsList = Object.assign({}, this.queryParams,rowData);
this.download("system/alarmManage/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,108 @@
<template>
<div class="app-container">
<Form :formList="formList" :ruleFormData="ruleForm" :config="config" @fnClick="callback"></Form>
</div>
</template>
<script setup name="Handle">
import Form from '@/components/form/index.vue';
import {addGroup, getGroup, updateGroup, resNameList} from "@/api/disRevenue/resource"
export default {
name: 'AgentUpdateView',
components: {Form},
data() {
return {
ruleForm: {},
formList: [],
paramsData: {},
config: {}
}
},
created() {
this.paramsData = this.$route && this.$route.query;
if (this.paramsData && this.paramsData.id) {
this.getFormDataList(this.paramsData.id);
}
if (this.paramsData && this.paramsData.readonly) {
this.config = {
buttonGroup: [{title: '返回', fnCode: 'goBack'}]
};
}
this.fnFormList();
this.getResNameList();
},
methods: {
// formList集合
fnFormList(objVal) {
this.formList = [{
config: {title: '配置更新策略', colSpan: 'disBlock', readonly: this.paramsData.readonly},
controls: {
id: {label: 'ID',hidden: true},
sn: {label: '硬件SN', span: 12, type: 'input', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
name: {label: '资源名称', span: 12, type: 'input', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
ip: {label: '内网IP', span: 12, type: 'input', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
type: {label: '状态', span: 12, type: 'select', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
agent: {label: 'AGENT版本', span: 12, type: 'input', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
groupName: {label: '定义更新频率', span: 12, type: 'select', required: true},
date: {label: '定义更新时间', span: 12, type: 'date', required: true},
fileType: {label: '文件格式', span: 12, type: 'radio', required: true,options: [{label:'平台文件地址', value: '1'}, {label: '外网HTTP(S)',value: '2'}],
hidden: this.paramsData && this.paramsData.id ? true : false, warningTitle: '注意当文件大小超过100M时请选择【外网HTTP(S)】地址格式'},
address: {label: '文件目录', span: 12, type: 'select', required: true, warningTitle: '您选择的文件已经超过100M请更改文件地址格式选择'},
includedDevices: {label: '生效服务器', span: 24,required: true, type: 'transfer',options: [],hidden: this.paramsData && this.paramsData.id ? true : false},
lastResult: {label: '最后一次更新结果', span: 12, type: 'select', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
lastTime: {label: '最后一次更新时间', span: 12, type: 'datetimme', disabled: true, hidden: this.paramsData && this.paramsData.id ? false : true},
}
}];
},
// 获取详情
getFormDataList(id) {
getGroup(id).then(val => {
if (val && val.data) {
if (val.data && val.data['includedDevices']) {
val.data['includedDevices'] = val.data['includedDevices'].split(',');
}
this.ruleForm = val.data;
}
}).catch(() => {
// this.$modal.msgError("操作失败")
});
},
// 包含设备
getResNameList() {
resNameList().then(val => {
this.formList[0].controls['includedDevices']['options']= val && val.map(item => {
return Object.assign({label: item.resourceName, key: item.resourceName});
});
}).catch(() => {
this.$modal.msgError("操作失败")
});
},
// 监听事件
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'submit':
dataVal['includedDevices'] = dataVal['includedDevices'].join();
let fnType = addGroup;
if (dataVal && dataVal.id) {
fnType = updateGroup;
}
fnType(dataVal).then(response => {
this.$modal.msgSuccess(response.msg);
this.$router.push("/resource/agentUpdate")
}).catch(() => {
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
this.$router.push("/resource/agentUpdate");
break;
default:
}
}
}
}
}
</script>
<style>
</style>

View File

@@ -34,7 +34,7 @@
id: {label: 'ID',hidden: true},
groupName: {label: '名称', span: 24, type: 'input', rules: [{required: true, message: '请输入名称', trigger: 'blur'}]},
description: {label: '描述', span: 24, type: 'textarea'},
includedDevices: {label: '包含设备', span: 12, type: 'transfer',options: []}
includedDevices: {label: '包含设备', span: 24, type: 'transfer',options: []}
}
}];
},

View File

@@ -62,7 +62,7 @@
id: { label: `ID`,width: '50'},
switchName: { label: `策略名称`, minWidth: '250', visible: true },
switchSn: { label: `描述`,minWidth: '200',visible: false},
interfaceName: { label: `关联资源组控项`,minWidth: '150', visible: true },
interfaceName: { label: `关联资源组`,minWidth: '150', visible: true },
serverName: { label: `包含设备`,minWidth: '200'},
connectedDeviceType: { label: `关联监控模版`,minWidth: '150', visible: true },
connected: { label: `策略内容`,minWidth: '200'},

View File

@@ -60,6 +60,7 @@
encryption: {label: '加密方式', span: 12, type: 'radio', options: this.dict.type.rm_register_encryption,hidden: objVal && objVal.id ? false : true, disabled: objVal && objVal.registrationStatus === '1' ? true : false},
teamName: {label: '团体名称', span: 12, type: 'input', hidden: objVal && objVal.snmpDetect === '1' ? false : true,disabled: objVal && objVal.registrationStatus === '1' ? true : false},
snmpCollectAddr: {label: 'SNMP采集地址', span: 12, type: 'input',required: true, hidden: objVal && objVal.snmpDetect === '1' ? false : true, disabled: objVal && objVal.registrationStatus === '1' ? true : false},
snmpCollectPort: {label: 'SNMP采集端口', span: 12, type: 'input',required: true, hidden: objVal && objVal.snmpDetect === '1' ? false : true, disabled: objVal && objVal.registrationStatus === '1' ? true : false},
resourceUserName: {label: '用户名', span: 12, type: 'input', hidden: objVal && objVal.id ? false : true, disabled: objVal && objVal.registrationStatus === '1' ? true : false},
resourcePwd: {label: '密码', span: 12, type: 'input', hidden: objVal && objVal.id ? false : true, disabled: objVal && objVal.registrationStatus === '1' ? true : false},
description: {label: '描述', span: 12, type: 'textarea',disabled: objVal && objVal.registrationStatus === '1' ? true : false},

View File

@@ -0,0 +1,293 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<!--部门数据-->
<pane size="16">
<el-col>
<div class="head-container">
<el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
</div>
<div class="head-container">
<el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false" :filter-node-method="filterNode" ref="tree" node-key="id" default-expand-all highlight-current @node-click="handleNodeClick" />
</div>
</el-col>
</pane>
<!--用户数据-->
<pane size="84">
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" size="small" label-width="80px">
<el-col :span="7">
<el-form-item label="名称" prop="switchName">
<el-input
v-model="queryParams.switchName"
placeholder="请输入名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="类型" prop="bandwidthType">
<el-select
v-model="queryParams.bandwidthType"
placeholder="请选择类型"
clearable>
<el-option
v-for="dict in dict.type.rm_topology_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item class="lastBtnSty">
<el-button type="primary" size="mini" icon="Search" @click="handleQuery(1)">搜索</el-button>
<el-button icon="Refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-form>
<input type="file" ref="fileInput" @change="handleFileChange" style="display: none;">
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="roleList" @fnClick="callback" @fnRenderList="getList" @value-change="handleValueChange">
<template v-slot:tableExpand="slotProps">
<div v-for="(val, key) of expandList" style="padding: 5px 0 5px 70px;">
<div style="width: 150px;" class="ml10 disInlineBlock">{{val}}</div>
<div class="ml10 disInlineBlock">{{slotProps.row[key]}}</div>
</div>
</template>
</TableList>
<!-- 新建文件夹 -->
<el-dialog title="命令执行结果" :visible.sync="open" width="600px" append-to-body>
<div class="block">
<el-timeline>
<el-timeline-item timestamp="2018/4/12" placement="top">
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/12 20:46</p>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/3" placement="top">
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/3 20:46</p>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/2" placement="top">
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/2 20:46</p>
</el-timeline-item>
</el-timeline>
</div>
</el-dialog>
</pane>
</splitpanes>
</el-row>
</div>
</template>
<script setup>
import TableList from "@/components/table/index.vue"
import EchartsPie from "@/components/echartsList/pie.vue"
import {listTopology, delTopology} from "@/api/disRevenue/resource"
import {deptTreeSelect } from "@/api/system/user"
import { Splitpanes, Pane } from "splitpanes"
import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import "splitpanes/dist/splitpanes.css"
export default {
name: 'RemoteManage',
components: {TableList,EchartsPie, Splitpanes, Pane, Treeselect},
dicts: ['rm_topology_type'],
data() {
return {
loading: true,
// 部门名称
deptName: undefined,
// 所有部门树选项
deptOptions: undefined,
defaultProps: {
children: "children",
label: "label",
disabled: true
},
showSearch: true,
roleList: [],
queryParams: {
total: 0,
pageNum: 1,
pageSize: 10
},
// 列显隐信息
columns: {
id: { label: `ID`, width: '50', visible: false },
switchName: { label: `名称`, minWidth: '250', visible: true },
switchSn: { label: `类型`, minWidth: '200', visible: true},
interfaceName: { label: `大小(KB)`, minWidth: '100', visible: true },
connectedDeviceType: { label: `路径`, minWidth: '200', visible: true },
serverName: { label: `描述`, minWidth: '200', visible: true},
md5: { label: `md5值`, minWidth: '160', visible: true},
createBy: { label: `创建人`, minWidth: '160', visible: true},
createTime: { label: `创建时间`, minWidth: '160', visible: true},
serverPort: { label: `修改时间`,minWidth: '160', visible: true }
},
config: {
expand: true,
searcherForm: [
{label: '交换机名称', prop: 'roleName', type: 'selset', options: []}
],
tableButton: {
line: [
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'disRevenue:resource:fileManage:details'},
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'disRevenue:resource:fileManage:edit'},
{content: '查看脚本执行结果', fnCode: 'result', type: 'text', icon: 'el-icon-s-check', hasPermi: 'disRevenue:resource:fileManage:result'},
{}
]
}
},
expandList: {
switchName: '接口名称',
switchSn: 'MAC地址',
interfaceName: '接口类型',
serverName: 'IPv4地址',
},
open: false,
title: '',
moveList: [],
catalogList: null,
formList:{
switchName: '',
remarks: ''
}
}
},
watch: {
// 根据名称筛选部门树
deptName(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList();
this.getDeptTree();
},
methods: {
// 处理文件选择
handleFileChange(e) {
console.log('e====',e);
// const file = e.target.files[0] // 获取第一个选中的文件
// if (file) {
// selectedFile = file
// selectedFileName = file.name // 显示文件名
// // 可选:自动上传
// // uploadFile()
// } else {
// clearFile() // 未选择文件时清空
// }
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
this.deptOptions = response.data;
})
},
// 筛选节点
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
// 节点单击事件
handleNodeClick(data) {
this.queryParams.deptId = data.id;
this.handleQuery();
},
/** 查询列表 */
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(val) {
if (val && val === 1) {
delete this.queryParams.deptId;
}
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryRef");
this.handleQuery();
},
submitForm(num){
if (num === 1) {
this.$refs['noticeRef'].validate((valid) => {
if (!valid) {
return false;
}
this.open = false;
});
}
},
/** 取消按钮 */
cancel(val) {
this.open = false;
},
callback(result, rowData, selectChange, selectList) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'edit':
this.$router.push({
path:'/disRevenue/resource/remoteManage/view',
query:{
id: rowData.id
}
});
break;
case 'details':
this.$router.push({
path:'/disRevenue/resource/remoteManage/view',
query:{
id: rowData.id,
readonly: true
}
});
break;
case 'result':
this.open = true;
break;
case 'delete':
this.$modal.confirm('是否确认删除数据项?').then(function() {
return delTopology(selectChange)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功")
}).catch(() => {});
break;
default:
}
}
}
}
}
</script>
<style scoped>
::v-deep .lastBtnSty .el-form-item__content{
margin-left: 10px!important;
}
::v-deep .el-table__expanded-cell {
background: #f2f2f2!important;
}
::v-deep .el-timeline .el-timeline-item:last-child .el-timeline-item__tail {
display: block!important;
}
</style>

View File

@@ -0,0 +1,133 @@
<template>
<div class="app-container mt20">
<Form :formList="formList" :ruleFormData="ruleForm" :config="paramsData && paramsData.readonly === 'true' ? {buttonGroup: []} : {}" @fnClick="callback"></Form>
<div v-if="paramsData && paramsData.readonly === 'true'" class="w100 mt50">
<p style="font-size: 1.2rem;font-weight: 500;border-bottom: 1px solid #e7e7e7;">{{netWorkCard.title}}</p>
<div v-for="item of netWorkCard.list" class="mt50">
<div v-for="(val,index) of item.data" style="width: 80%;margin: auto;" :class="index + 1 === item.data.length ? 'border' : 'borderType'">
<div style="width: 20%;border-right: 1px solid #e7e7e7;" class="ml10 disInlineBlock"><p>{{val.name}}</p></div>
<p style="width: 75%" class="ml10 disInlineBlock">{{val.content}}</p>
</div>
</div>
</div>
<el-button v-if="paramsData && paramsData.readonly === 'true'" class="mb20 mt20" style="float: right;" @click="callback({fnCode: 'cancle'})">返回</el-button>
</div>
</template>
<script setup name="Handle">
import Form from '@/components/form/index.vue';
import {addGroup, getGroup, updateGroup, resNameList} from "@/api/disRevenue/resource"
export default {
name: 'RemoteManageView',
components: {Form},
data() {
return {
ruleForm: {},
formList: [],
paramsData: {},
netWorkCard: {
title: '网卡信息',
list: [
{
data: [
{name: '接口名称', content: 'eno1(Intel Corporation Ethernet Connection X722 for 10GbE SFP+)'},
{name: 'MAC地址', content: '7c:c3:85:b6:61:bf'},
{name: '接口类型', content: 'Ethernet'},
{name: 'IPv4地址', content: '172.16.15.103'}
]
},
{
data: [
{name: '接口名称', content: 'eno1(Intel Corporation Ethernet Connection X722 for 10GbE SFP+)'},
{name: 'MAC地址', content: '7c:c3:85:b6:61:bf'},
{name: '接口类型', content: 'Ethernet'},
{name: 'IPv4地址', content: '172.16.15.103'}
]
},
]
}
}
},
created() {
this.paramsData = this.$route && this.$route.query;
if (this.paramsData && this.paramsData.id) {
this.getFormDataList(this.paramsData.id);
}
this.fnFormList();
this.getResNameList();
},
methods: {
// formList集合
fnFormList(objVal) {
this.formList = [{
config: {title: '', colSpan: 'disBlock', readonly: this.paramsData.readonly},
controls: {
id: {label: 'ID',hidden: true},
groupName: {label: '硬件SN', span: 12, type: 'input', disabled: true},
type: {label: '资源类型', span: 12, type: 'input', disabled: true},
name: {label: '资源名称', span: 12, type: 'input', disabled: true},
description: {label: '描述', span: 12, type: 'textarea'},
createTime: {label: '内网IP', span: 12, type: 'input'},
includedDevices: {label: '外网IP', span: 12, type: 'input'},
manage: {label: '管理端口', span: 12, type: 'input'},
num: {label: '在线状态', span: 12, type: 'select', disabled: true},
md5: {label: '连接方式', span: 12, type: 'select'},
}
}];
},
// 获取详情
getFormDataList(id) {
getGroup(id).then(val => {
if (val && val.data) {
this.ruleForm = val.data;
}
}).catch(() => {
this.$modal.msgError("操作失败")
});
},
// 包含设备
getResNameList() {
resNameList().then(val => {
this.formList[0].controls['includedDevices']['options']= val && val.map(item => {
return Object.assign({label: item.resourceName, key: item.resourceName});
});
}).catch(() => {
this.$modal.msgError("操作失败")
});
},
// 监听事件
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'submit':
let fnType = addGroup;
if (dataVal && dataVal.id) {
fnType = updateGroup;
}
fnType(dataVal).then(response => {
this.$modal.msgSuccess(response.msg);
this.$router.push("/resource/fileManage")
}).catch(() => {
this.$modal.msgError("操作失败")
});
break;
case 'cancle':
this.$router.push("/resource/fileManage");
break;
default:
}
}
}
}
}
</script>
<style scoped>
.borderType {
border-top: 1px solid #e7e7e7;
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
}
.border {
border: 1px solid #e7e7e7;
}
</style>

View File

@@ -0,0 +1,188 @@
<template>
<div class="app-container pageTopForm">
<el-form :model="queryParams" ref="queryRef" size="small" v-show="showSearch" label-width="auto">
<el-col :span="8">
<el-form-item label="策略名称" prop="switchName">
<el-input
v-model="queryParams.switchName"
placeholder="请输入策略名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="策略状态" prop="bandwidthType">
<el-select
v-model="queryParams.bandwidthType"
placeholder="请选择策略状态"
clearable>
<el-option
v-for="dict in dict.type.eps_bandwidth_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item class="lastBtnSty">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-col>
</el-form>
<TableList :columns="columns" :config="config" :queryParams="queryParams" :tableList="tableList" @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 {listMonitorTemp, delMonitorTemp} from "@/api/disRevenue/resource"
export default {
name: 'ServerScript',
components: {TableList},
dicts: ['rm_topology_type','eps_bandwidth_type'],
data() {
return {
loading: true,
showSearch: true,
tableList: [],
queryParams: {
total: 0,
pageNum: 1,
pageSize: 10
},
// 列显隐信息
columns: {
id: { label: `ID`,width: '50'},
switchName: { label: `策略名称`, minWidth: '250', visible: true },
state: { label: `执行方式`,minWidth: '200',visible: true},
interfaceName: { label: `关联资源组`,minWidth: '150', visible: true },
serverName: { label: `包含设备`,minWidth: '200', visible: true},
type: { label: `策略状态`, minWidth: '100', visible: true },
connectedDeviceType: { label: `源文件路径`,minWidth: '150'},
connected: { label: `目标目录`,minWidth: '200'},
content: { label: `命令内容`,minWidth: '200'},
time: { label: `定时时间`,minWidth: '200'},
conType: { label: `下发策略时间`,minWidth: '160'},
switchSn: { label: `描述`,minWidth: '200'},
createTime: { label: `创建时间`,minWidth: '160'},
updateTime:{ label: `修改时间`,minWidth: '160'}
},
config: {
searcherForm: [
{label: '模版名称', prop: 'roleName', type: 'selset', options: []}
],
tableButton: {
top: [
{content: '新增', fnCode: 'add', type: 'primary', icon: 'el-icon-plus', hasPermi: 'disRevenue:resource:monitorStategy:add'},
{content: '删除', fnCode: 'delete', type: 'danger', icon: 'el-icon-delete', hasPermi: 'disRevenue:resource:monitorStategy:detele'},
{content: '导出', fnCode: 'export', type: 'warning', icon: 'el-icon-download', hasPermi: 'disRevenue:resource:monitorStategy:export'},
],
line: [
{content: '修改', fnCode: 'edit', type: 'text', icon: 'el-icon-edit', hasPermi: 'disRevenue:resource:monitorStategy:edit'},
{content: '详情', fnCode: 'details', type: 'text', icon: 'el-icon-view', hasPermi: 'disRevenue:resource:monitorStategy:details'},
{content: '复制', fnCode: 'copy', type: 'text', icon: 'el-icon-document-copy', hasPermi: 'disRevenue:resource:monitorStategy:copy'},
{content: '下发策略', fnCode: 'strategy', type: 'text', icon: 'el-icon-sort-down', hasPermi: 'disRevenue:resource:monitorStategy:strategy'},
{content: '删除', fnCode: 'delete', type: 'text', icon: 'el-icon-delete', hasPermi: 'disRevenue:resource:monitorStategy:detele'},
]
}
}
}
},
created() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
listMonitorTemp(this.queryParams).then(response => {
this.tableList = 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:'/disRevenue/resource/serverScript/details'});
break;
case 'edit':
this.$router.push({
path:'/disRevenue/resource/serverScript/details',
query:{
id: rowData.id
}
});
break;
case 'details':
this.$router.push({
path:'/disRevenue/resource/serverScript/view',
query:{
id: rowData.id
}
});
break;
case 'delete':
let delList = [];
if (rowData && rowData.id) {
delList.push(rowData.id);
} else {
delList = selectChange;
}
this.$modal.confirm('是否确认删除该数据?').then(function() {
return delMonitorTemp(delList)
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功")
}).catch(() => {});
break;
case 'export':
// let dataList = [];
// Object.keys(this.columns).forEach(item => {
// if (item.visible) {
// dataList.push(item.prop);
// }
// });
// this.download("/system/monitorStategy/export", {properties: dataList,}, `拓扑管理_${new Date().getTime()}.xlsx`);
let paramsList = Object.assign({}, this.queryParams,rowData);
this.download("system/serverScript/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,221 @@
<template>
<div class="app-container">
<div>
<el-steps :active="active" finish-status="success">
<el-step title="基本信息"></el-step>
<el-step title="监控信息"></el-step>
<el-step title="信息确认"></el-step>
</el-steps>
<!-- 内容区 -->
<div style="margin-top: 30px;">
<!-- active:0 -->
<div v-show="active === 0">
<Form ref="formRef" style="text-align: center;" :formList="formList" :ruleFormData="ruleFormData" :config="config" @fnClick="callback"></Form>
</div>
<!-- active:2 -->
<div v-show="active === 1">
<Form v-for="item of formListTow" ref="formTowRef" :formList="[item]" :ruleFormData="item.ruleFormData" :config="item.config" @fnClick="callback">
<template v-slot:btnType="scope">
<el-button type="primary" @click="btnClick(scope)">{{scope.field.btnName}}</el-button>
</template>
</Form>
</div>
<!-- active:3 -->
<div v-show="active === 2">
<!-- <MonitorStategyView :ruleForm="ruleFormData" :otherList="synthesisList"></MonitorStategyView>-->
</div>
</div>
</div>
<el-button type="primary" v-show="active > 1" style="float: right;margin-top: 12px;margin-left: 10px;" @click="submit">提交</el-button>
<el-button type="primary" v-show="active < 2" style="float: right;margin-top: 12px;" @click="next('1')">下一步</el-button>
<el-button type="primary" v-show="active > 0" style="float: right;margin-top: 12px;" @click="next('-1')">上一步</el-button>
<el-button type="primary" style="float: right;margin-top: 12px;" @click="goBack">返回</el-button>
</div>
</template>
<script setup>
import Form from '@/components/form/index.vue';
import TableList from "@/components/table/index.vue"
// import MonitorStategyView from './view'
export default {
name: 'ServerScriptDetails',
components: {Form, TableList},
data() {
return {
active: 0,
synthesisList: {},
// 第一节点
ruleFormData: {
monitorTemp: 1,
},
config: {
buttonGroup: []
},
formList: [{
config: {title: '', colSpan: 'disBlock m0Auto'},
controls: {
id: {label: 'ID',hidden: true},
switchName: {label: '策略名称', span: 12, type: 'input', rules: [{required: true, message: '请输入模版名称', trigger: 'blur'}]},
serverPort: {label: '描述', span: 12, type: 'textarea'},
monitorTemp: {label: '关联资源组', span: 12, type: 'select'},
resourceGroup: {label: '包含设备', span: 12, type: 'select', multiple: true}
}
}],
// 第二节点 1栏
formListTow: [],
ruleFormDataTow: {},
addNum: 0
}
},
created() {
this.formRender();
},
methods: {
formRender(){
this.formListTow = [
{
config: {title: '', key: Math.floor(Math.random() * 9000),buttonGroup: []},
controls: {
id: {label: 'ID',hidden: true},
localAddress: {label: '源文件1地址格式', span: 12, type: 'radio', required: true,
warningTitle: '注意当文件大小超过100M时请选择【外网HTTP(S)】地址格式',
options: [{value: '1', label: '平台文件地址'}, {value: '2', label: '外网HTTP(s)'}]},
btn: {label: '', span: 12, slotName: 'btnType', btnName: '添加', btnType: 'add'},
serverPort: {label: '源文件1地址', span: 12, type: 'select'}
},
ruleFormData: {
id: '',
localAddress: '',
serverPort: ''
}
},{
config: {title: '', key: Math.floor(Math.random() * 9000),buttonGroup: []},
controls: {
id: {label: 'ID',hidden: true},
fileAddress: {label: '目标目录', span: 12, type: 'input'},
},
ruleFormData: {
id: '',
fileAddress: ''
}
},{
config: {title: '', key: Math.floor(Math.random() * 9000),buttonGroup: []},
controls: {
id: {label: 'ID',hidden: true},
content: {label: '命令内容1', span: 24, type: 'input'},
// btn: {label: '添加', span: 12, type: 'btn'},
},
ruleFormData: {
id: '',
content: ''
}
},
{
config: {title: '', key: Math.floor(Math.random() * 9000),buttonGroup: []},
controls: {
id: {label: 'ID',hidden: true},
type: {label: '执行方式', span: 24, type: 'select'},
date: {label: '定时时间', span: 12, type: 'date'},
time: {label: '', span: 12, type: 'time'},
},
ruleFormData: {
id: '',
type: '',
date: '',
time: ''
}
}
];
},
async next(num) {
if (num === '-1') {
this.active--;
} else {
if (this.active === 0) {
if (!await this.fnFormValid()) {
return;
}
}
this.active++;
}
},
// 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);
}
});
});
},
// 插槽按钮操作
btnClick(row){
const { field } = row;
// 找到当前点击项在 formListTow 中的索引
const currentIndex = this.formListTow.findIndex(
item => item.config.key === field.parentKey // 需在子组件传递当前项的key
);
console.log('field===',field,'currentIndex===',currentIndex);
if (field.btnType === 'add') {
this.addNum++;
const newKey = Math.floor(Math.random() * 9000);
let slotForm = {
config: {title: '', key: newKey,buttonGroup: []},
index: this.addNum,
controls: {
id: {label: 'ID',hidden: true},
localAddress: {label: `源文件${currentIndex + 1 + this.addNum}地址格式`, span: 12, type: 'radio', required: true, options: [{value: '1', label: '平台文件地址'}, {value: '2', label: '外网HTTP(s)'}]},
btn: {label: '', span: 12, slotName: 'btnType', btnName: '删除', btnType: 'delete', parentKey: newKey},
serverPort: {label: `源文件${currentIndex + 1 + this.addNum}地址`, span: 12, type: 'input'}
},
ruleFormData: {
localAddress: '',
serverPort: ''
}
};
this.formListTow.splice(currentIndex + 1 + this.addNum, 0, slotForm);
} else if (row && row.field.btnType === 'delete'){
// this.addNum--;
this.formListTow = this.formListTow.filter(
item => item.config.key !== field.parentKey
);
}
},
// 提交
submit() {
console.log('ruleFormData==',this.ruleFormData);
console.log('synthesisList==',this.synthesisList);
},
// 返回
goBack() {
this.$router.push({path:'/resource/monitorStategy'});
},
// 监听事件
callback(result, dataVal, formVal) {
if (result && result.fnCode) {
switch (result.fnCode) {
case 'submit':
console.log('dataVal===',dataVal);
break;
default:
}
}
}
}
}
</script>
<style scoped>
::v-deep .el-collapse-item__header {
background-color: #d4e3fc!important;
/*color: #fff!important;*/
padding-left: 20px;
font-size: 1rem;
}
</style>