Commit da238fc6 authored by wangdong's avatar wangdong

5.6

parent 96e4d1ef
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# front
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn serve
```
### Compiles and minifies for production
```
yarn build
```
### Lints and fixes files
```
yarn lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
{
"name": "front",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"element-ui": "^2.15.1",
"fs": "^0.0.1-security",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"lint-staged": "^9.5.0",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
]
}
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
</style>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div id="first">
<div id="wrapper">
<main>
<div id="left" class="left-side">
<img
src="~@/assets/ustb-oai.com.png"
alt="electron-vue"
width="350px"
/>
<slice-information></slice-information>
</div>
<div class="right-side">
<base-station-info></base-station-info>
</div>
</main>
</div>
</div>
</template>
<script>
import SystemInformation from "./LandingPage/SystemInformation";
import SliceInformation from "./sliceInfos/SliceInformation";
import BaseStationInfo from "./sliceInfos/BaseStationInfo";
import SshPage from "./SshPage/SshPage";
import UeLists from "./sliceInfos/UeLists";
import * as flexranAPI from "../../utils/flexranAPI";
export default {
name: "landing-page",
components: {
SystemInformation,
"slice-information": SliceInformation,
"ue-lists": UeLists,
"base-station-info": BaseStationInfo,
"ssh-page": SshPage,
},
async mounted() {
let res = await flexranAPI.DETECT({});
try {
let returnCitySN = JSON.parse(res.split("= ")[1].split(";")[0]);
let local = await flexranAPI.DETECT_LOCAL({}, returnCitySN["cip"]);
if (local.area == "北京科技大学") {
console.log("在校园网内");
flexranAPI.SET_URL({});
} else {
console.log("不在校园网");
}
} catch (error) {
console.log("在校园网内");
flexranAPI.SET_URL({});
}
this.timeInterval1 = setInterval(() => {
flexranAPI.GET_MAC_STATS().then((result) => {
let dataList =
result.eNB_config[0].eNB.cellConfig[0].sliceConfig.dl.slices;
let ue_list = result.mac_stats[0].ue_list
this.$store.commit("updateSlices", {
slice_info: dataList,
});
this.$store.commit("updateUes", {
ue_list: ue_list,
});
dataList.forEach(e => {
e = e.ddqn
});
this.$store.commit("updatePrbs", {
prb_info: dataList,
});
// console.log(dataList)
});
}, 500);
},
methods: {
open(link) {
this.$electron.shell.openExternal(link);
},
openFlexran() {
},
closeFlexran() {
},
},
};
</script>
<style>
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro");
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body,
#app {
height: 100%;
}
body {
font-family: "Source Sans Pro", sans-serif;
}
img {
filter: grayscale(70%);
display: fixed;
bottom: 2px;
}
header {
margin-top: 15px;
}
#wrapper {
background: radial-gradient(
ellipse at top left,
rgba(255, 255, 255, 1) 40%,
rgba(229, 229, 229, 0.9) 100%
);
height: 100vh;
padding: 15px 20px;
width: 100vw;
}
#left {
padding-right: 10px;
}
.right-side {
margin-top: 76.39px;
}
main {
display: flex;
justify-content: space-between;
margin-right: 56px;
}
main > div {
flex-basis: 50%;
}
.left-side {
display: flex;
flex-direction: column;
}
#first {
height: 100%;
}
.doc button {
font-size: 0.8em;
cursor: pointer;
outline: none;
padding: 0.75em 2em;
border-radius: 2em;
display: inline-block;
color: #fff;
background-color: #4fc08d;
transition: all 0.15s ease;
box-sizing: border-box;
border: 1px solid #4fc08d;
}
.doc button.alt {
color: #42b983;
background-color: transparent;
}
</style>
<template>
<div>
<div class="title">Information</div>
<div class="items">
<div class="item">
<div class="name">Path:</div>
<div class="value">{{ path }}</div>
</div>
<div class="item">
<div class="name">Route Name:</div>
<div class="value">{{ name }}</div>
</div>
<div class="item">
<div class="name">Vue.js:</div>
<div class="value">{{ vue }}</div>
</div>
<div class="item">
<div class="name">Electron:</div>
<div class="value">{{ electron }}</div>
</div>
<div class="item">
<div class="name">Node:</div>
<div class="value">{{ node }}</div>
</div>
<div class="item">
<div class="name">Platform:</div>
<div class="value">{{ platform }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
electron: process.versions.electron,
name: this.$route.name,
node: process.versions.node,
path: this.$route.path,
platform: require('os').platform(),
vue: require('vue/package.json').version
}
}
}
</script>
<style scoped>
.title {
color: #888;
font-size: 18px;
font-weight: initial;
letter-spacing: .25px;
margin-top: 10px;
}
.items { margin-top: 8px; }
.item {
display: flex;
margin-bottom: 6px;
}
.item .name {
color: #6a6a6a;
margin-right: 6px;
}
.item .value {
color: #35495e;
font-weight: bold;
}
</style>
<template>
<div style="height: 100%">
<div
v-for="(item1, index1) in srcs"
:key="index1"
v-bind="item1"
v-show="item1.active">
<iframe
:id="index1"
style="height: 500px; width: 100%"
frameborder="0"
:name="index1"
scrolling="auto"
:src="item1.url"
></iframe>
</div>
<div class="flex" >
<div
v-for="(item1, index1) in srcs"
:key="index1"
v-bind="item1"
@click="handleCommand1(index1)"
:class="item1.active?'activate':'s'"
class="tags"
>
<el-dropdown >
<el-tag v-if="item1.name=='FlexRan'" :type="item1.active?'success':'info'">
{{ item1.name }}
</el-tag>
<el-tag v-else closable @close="handleClose(index1)" :type="item1.active?'success':'info'" >
{{ item1.name }}
</el-tag>
<el-dropdown-menu slot="dropdown" >
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,0)"> 查看OAI基站LOG</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,3)"> 查看OAI UELOG</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,5)"> 查看空口协议</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='CoreNet'" @click="handleCommand2(index1,4)"> 查看GTP流量</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='FlexRan'" @click="refresh"> 刷新</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='AI-Engine'" @click="handleCommand2(index1,1)"> 启动DRL切片智能分配</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='CoreNet'" @click="handleCommand2(index1,2)"> 查看MME LOG</div></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<el-dropdown @command="handleCommand">
<el-tag type="primary">
NewSSH<i class="el-icon-plus el-icon--right"></i>
</el-tag>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="0">OAI_ENB</el-dropdown-item>
<el-dropdown-item command="1">DroneFront</el-dropdown-item>
<el-dropdown-item command="2">AI-Engine</el-dropdown-item>
<el-dropdown-item command="3">CoreNet</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- <img src="~@/assets/ustb-oai.com.png" alt="electron-vue" height="4%" > -->
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import * as flexranAPI from "../../../utils/flexranAPI";
import _ from 'lodash'
Vue.use(vueJsonTreeView);
export default {
data() {
return {
dataList: [],
host: "",
action: "",
view: true,
commands:['tail -f ~/log/enb.log','cd /root/dqn_zoo/Dueling\\ DDQN/ && python dueling_ddqn.py','tail -f /root/log/mme.log','tail -f ~/log/ue.log',"tshark -i gtp0 ","tshark -i lo -f 'udp dst port 9999' --enable-heuristic mac_lte_udp "],
ssh_srcs:[ {
name: "OAI_ENB",
active: false,
url:
"http://10.25.20.227:2222/ssh/host/192.168.1.193?autologin=1&user=root&pass=199710",
},
{
name: "DroneFront",
active: false,
url:
"http://10.25.20.227:2222/ssh/host/192.168.1.36?autologin=1&user=root&pass=199710",
},
{
name: "AI-Engine",
active: false,
url:
"http://10.25.20.227:2222/ssh/host/192.168.1.80?autologin=1&user=root&pass=199710",
},
{
name: "CoreNet",
active: false,
url:
"http://10.25.20.227:2222/ssh/host/192.168.1.12?autologin=1&user=root&pass=199710",
},],
srcs: [
{ name: "FlexRan", active: true, url: "http://10.25.20.227:2224" },
],
menus: [
{ name: "FlexRan", active: true },
{ name: "OAI_ENB", active: true },
{ name: "DroneFront", active: true },
{ name: "AI-Engine", active: true },
{ name: "CoreNet", active: true },
],
};
},
async mounted() {
this.host = this.$route.params.host;
this.action = this.$route.params.action;
this.user = this.$route.params.user;
this.pass = this.$route.params.pass;
let res = await flexranAPI.DETECT({});
try {
let returnCitySN = JSON.parse(res.split("= ")[1].split(";")[0]);
let local = await flexranAPI.DETECT_LOCAL({}, returnCitySN["cip"]);
if (local.area == "北京科技大学") {
this.src = `http://10.25.20.227:2224`;
} else {
this.src = `http://ustb-oai.com:2224`;
}
} catch (error) {
this.src = `http://10.25.20.227:2224`;
}
},
methods: {
getJS(id,str) {
var child = document
.getElementById(String(id))
.contentWindow.socket.emit("control", str);
},
refresh() {
location.reload()
},
handleCommand(command) {
this.$message("NewSSH to " + this.ssh_srcs[Number(command)].url.split('?')[0]);
this.srcs.push( _.cloneDeep(this.ssh_srcs[Number(command)]))
this.handleCommand1(this.srcs.length-1)
},
handleCommand2(id,command) {
this.getJS(id,this.commands[command])
},
handleCommand1(command) {
for(let i =0;i<this.srcs.length;i++){
if(i==command){
this.srcs[i].active=true
}
else{
this.srcs[i].active=false
}
}
},
handleClose(index){
_.pullAt(this.srcs, index)
this.handleCommand1(index-1)
}
},
};
</script>
<style>
html,
body,
#app {
height: 100%;
}
.flex {
display: flex;
width: 100%;
margin-right: 10px;
padding-right: 10px;
}
.tags{
margin-right: 1px;
}
#icon {
position: fixed;
margin-top: 470px;
margin-left: 10px;
z-index: 9999;
}
.activate{
background-color: #aaa;
}
</style>
<template>
<div style="height:100%">
<iframe id="show-iframe" style="height:95%;width:100%" frameborder=0 name="showHere" scrolling=auto :src="src"></iframe>
<img src="~@/assets/ustb-oai.com.png" alt="electron-vue" height="4%" >
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import * as flexranAPI from "../../../utils/flexranAPI";
Vue.use(vueJsonTreeView);
export default {
data() {
return {
dataList:[],
host:'',
action:'',
src:'http://10.25.20.227:2222/ssh/host/192.168.1.210?autologin=1&user=root&pass=199710'
};
},
async mounted() {
this.host=this.$route.params.host
this.action=this.$route.params.action
this.user=this.$route.params.user
this.pass=this.$route.params.pass
let res = await flexranAPI.DETECT({})
try {
let returnCitySN = JSON.parse(res.split("= ")[1].split(";")[0])
let local = await flexranAPI.DETECT_LOCAL({},returnCitySN['cip'])
if(local.area=="北京科技大学"){
this.src=`http://10.25.20.227:2222/ssh/host/${this.host}?autologin=1&user=${this.user}&pass=${this.pass}`
}
else{
this.src=`http://ustb-oai.com:2222/ssh/host/${this.host}?autologin=1&user=${this.user}&pass=${this.pass}`
}
} catch (error) {
this.src=`http://10.25.20.227:2222/ssh/host/${this.host}?autologin=1&user=${this.user}&pass=${this.pass}`
}
},
methods:{
getJS (){
var child = document.getElementById("show-iframe").contentWindow;
let a= child.document.getElementById("menu");
console.log(a)
}
},
};
</script>
<style>
html,body,#app{
height: 100%;
}
.left{}
</style>
function dataHandler (newData, oldData) {
if (oldData) {
let chart = this.$data._chart
// Get new and old DataSet Labels
let newDatasetLabels = newData.datasets.map((dataset) => {
return dataset.label
})
let oldDatasetLabels = oldData.datasets.map((dataset) => {
return dataset.label
})
// Stringify 'em for easier compare
const oldLabels = JSON.stringify(oldDatasetLabels)
const newLabels = JSON.stringify(newDatasetLabels)
// Check if Labels are equal and if dataset length is equal
if (newLabels === oldLabels && oldData.datasets.length === newData.datasets.length) {
newData.datasets.forEach((dataset, i) => {
// Get new and old dataset keys
const oldDatasetKeys = Object.keys(oldData.datasets[i])
const newDatasetKeys = Object.keys(dataset)
// Get keys that aren't present in the new data
const deletionKeys = oldDatasetKeys.filter((key) => {
return key !== '_meta' && newDatasetKeys.indexOf(key) === -1
})
// Remove outdated key-value pairs
deletionKeys.forEach((deletionKey) => {
delete chart.data.datasets[i][deletionKey]
})
// Update attributes individually to avoid re-rendering the entire chart
for (const attribute in dataset) {
if (dataset.hasOwnProperty(attribute)) {
chart.data.datasets[i][attribute] = dataset[attribute]
}
}
})
if (newData.hasOwnProperty('labels')) {
chart.data.labels = newData.labels
this.$emit('labels:update')
}
if (newData.hasOwnProperty('xLabels')) {
chart.data.xLabels = newData.xLabels
this.$emit('xlabels:update')
}
if (newData.hasOwnProperty('yLabels')) {
chart.data.yLabels = newData.yLabels
this.$emit('ylabels:update')
}
chart.update()
this.$emit('chart:update')
} else {
if (chart) {
chart.destroy()
this.$emit('chart:destroy')
}
this.renderChart(this.chartData, this.options)
this.$emit('chart:render')
}
} else {
if (this.$data._chart) {
this.$data._chart.destroy()
this.$emit('chart:destroy')
}
this.renderChart(this.chartData, this.options)
this.$emit('chart:render')
}
}
export const reactiveData = {
data () {
return {
chartData: null
}
},
watch: {
'chartData': dataHandler
}
}
export const reactiveProp = {
props: {
chartData: {
type: Object,
required: true,
default: () => {}
}
},
watch: {
'chartData': dataHandler
}
}
export default {
reactiveData,
reactiveProp
}
<template>
<div>
<el-card>
<el-table :data="littleDate" border stripe>
<el-table-column type="index" label="UE"></el-table-column>
<el-table-column prop="rnti" label="RNTI" width="100">
</el-table-column>
<el-table-column label="速度">
<template slot-scope="scope">
<el-popover
placement="right"
width="400"
trigger="hover"
>
<div v-html="pingInfo"></div>
<div
style="margin: 10px"
@mouseover="hover = scope.row.imsi"
@mouseleave="hover = false"
slot="reference"
>
<el-button >{{ scope.row.Mbs }}</el-button></div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="切片">
<template slot-scope="scope">
<el-dropdown>
<el-button type="primary">
{{ scope.row.label }}
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="(item1, index1) in slices"
:key="index1"
v-bind="item1"
>分配至:切片{{ item1.id }}
<el-tag
effect="dark"
@click="changeslice(scope.row.imsi, item1.id)"
>
{{ item1.label }}
</el-tag></el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
<el-table-column prop="imsi" label="IMSI"> </el-table-column>
</el-table>
<el-pagination
layout="prev, pager, next"
:total="dataList.length"
style="margin-top:5px"
:page-size="4"
background
@current-change="handleCurrentChange"
:current-page="currentPage"
>
</el-pagination>
</el-card>
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import * as flexranAPI from "../../../utils/flexranAPI";
export default {
data() {
return {
currentPage:1,
hover: false,
littleDate:[],
pingInfo:
"PING 172.16.0.x (172.16.0.x) 56(84) bytes of data.<br/>64 bytes from 172.16.0.6: icmp_seq=1 ttl=64 time=39.5 ms<br/>64 bytes from 172.16.0.6: icmp_seq=2 ttl=64 time=39.1 ms<br/>64 bytes from 172.16.0.6: icmp_seq=3 ttl=64 time=28.7 ms<br/>64 bytes from 172.16.0.6: icmp_seq=4 ttl=64 time=45.6 ms<br/><br/>--- 172.16.0.6 ping statistics ---<br/>4 packets transmitted, 4 received, 0% packet loss, time 242ms<br/>rtt min/avg/max/mdev = 28.799/38.307/45.687/6.068 ms<br/>",
};
},
created() {
this.getDataList();
},
computed: {
slices() {
return this.$store.state.slice_info;
},
dataList() {
return this.$store.state.ue_list;
},
},
watch: {
hover: {
handler(newValue, oldValue) {
console.log(this.hover);
if (this.hover !== false) {
this.getping(this.hover);
}
if (this.hover == false) {
clearInterval(this.timer);
}
},
deep: true,
},
dataList: {
handler(newValue, oldValue) {
this.littleDate=newValue.slice((this.currentPage-1)*4,(this.currentPage-1)*4+4)
},
deep: true,
},
},
mounted(){
this.littleDate=this.dataList.slice(0*4,+4)
},
methods: {
handleCurrentChange(val){
console.log(val)
this.currentPage=val
val=val-1
console.log(this.currentPage)
this.littleDate=this.dataList.slice(val*4,val*4+4)
},
async getping(imsi) {
this.timer = setInterval(() => {
flexranAPI.SEND_PING({ imsi: imsi }).then((result) => {
this.pingInfo = result.output.split("\n").join("<br/>");
});
}, 1000);
},
getDataList() {},
changeslice(imsi, to) {
this.$confirm(`是否将${imsi}切换到切片${to}`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info",
})
.then(() => {
flexranAPI
.CHANGE_SLICE_ASSOC(
{
ueConfig: [
{
imsi: imsi,
dlSliceId: to,
},
],
},
-1
)
.then((res) => {
console.log(res);
if (res.status == "Ok") {
this.$message({
type: "success",
message: "切换成功!",
});
} else {
this.$message({
type: "error",
message: res.status,
});
}
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消切换",
});
});
},
},
};
</script>
<style lang="less" scoped>
</style>
<template>
<div>
<canvas
id="mycanvas"
width="1000"
height="1000"
style="text-align: center"
></canvas>
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import * as flexranAPI from "../../../utils/flexranAPI";
import Tooltip from "element-ui";
Vue.use(vueJsonTreeView);
Vue.use(Tooltip);
export default {
data() {
return {
hover: false,
ue_list: [],
slice_conf: [],
color_arrs:["#909399","#F56C6C","#E6A23C","#67C23A"],
pingInfo:
"PING 172.16.0.x (172.16.0.x) 56(84) bytes of data.<br/>64 bytes from 172.16.0.6: icmp_seq=1 ttl=64 time=39.5 ms<br/>64 bytes from 172.16.0.6: icmp_seq=2 ttl=64 time=39.1 ms<br/>64 bytes from 172.16.0.6: icmp_seq=3 ttl=64 time=28.7 ms<br/>64 bytes from 172.16.0.6: icmp_seq=4 ttl=64 time=45.6 ms<br/><br/>--- 172.16.0.6 ping statistics ---<br/>4 packets transmitted, 4 received, 0% packet loss, time 242ms<br/>rtt min/avg/max/mdev = 28.799/38.307/45.687/6.068 ms<br/>",
visible: false,
};
},
computed: {
slices(){
return this.$store.state.slice_info
},
dataList(){
return this.$store.state.ue_list
},
prb_info(){
return this.$store.state.prb_info
}
},
mounted() {
console.log(this.$store.state.prb_info)
let canvas = document.getElementById("mycanvas");
let ctx = canvas.getContext("2d");
canvas.width = 600;
canvas.height = 500;
let width = 600;
let height = 500;
let rectH = 20;
let rectW = 20;
ctx.lineWidth = 0.5;
  ctx.font="25px 宋体";
//绘制表格
// 第一步: 绘制横线
for(let i=0;i<=width/20;i++){
ctx.moveTo(rectW*i,0);
//如果不设置moveTo,当前画笔没有位置
ctx.lineTo(rectW*i,height);
if(i==0){
ctx.lineTo((rectW+1)*i,height);
}
}
//第二步:绘制竖线:如果绘制的格子的宽高相等,可以将for循环放到一个里面;
for(let i=0;i<=height/20;i++){
ctx.moveTo(0,rectH*i);
ctx.lineTo(width,rectH*i);
}
  //strokeText(text: String, x: Number, y: Number, maxWidth: Number): none
ctx.stroke();
},
methods: {
async getping(imsi) {
this.timer = setInterval(() => {
flexranAPI.SEND_PING({ imsi: imsi }).then((result) => {
this.pingInfo = result.output.split("\n").join("<br/>");
});
}, 1000);
},
drawCell(x,y){
let canvas=document.getElementById("mycanvas");
let ctx=canvas.getContext('2d');
ctx.fillStyle="#aaa"
ctx.fillRect(x,y,19,19);
ctx.font="700";
ctx.stroke();
return ctx
},
clearClomnCell(x){
for(let i=0;i<25;i++){
let canvas=document.getElementById("mycanvas");
let ctx=canvas.getContext('2d');
ctx.clearRect(x,i*20,19,19);
ctx.stroke();
}
},
drawClomnCell(x,data){
let count=0
this.clearClomnCell(x)
for(let i =0;i<data.length;i++){
let prb
if(data[i].id!="0"){
if(count<24 && data[i].ddqn.mrb>0){
prb = (data[i].ddqn.mrb+1)*2>25?25:(data[i].ddqn.mrb)*2
}
else{
prb = (data[i].ddqn.mrb+1)*2>25?25:((data[i].ddqn.mrb)*2)
}
}
else{
prb = (data[i].ddqn.mrb)*2>25?25:data[i].ddqn.mrb*2
}
for(let j=count;j<prb+count;j++){
let canvas=document.getElementById("mycanvas");
let ctx=canvas.getContext('2d');
ctx.fillStyle=this.color_arrs[data[i].id]
ctx.fillRect(x,j*20,19,19);
ctx.stroke();
}
count+=prb
}
}
},
watch: {
prb_info: {
handler(newValue, oldValue) {
newValue.forEach((v,i)=>{
this.drawClomnCell(i*20,v)
})
},
deep: true,
},
hover: {
handler(newValue, oldValue) {
console.log(this.hover);
if (this.hover !== false) {
this.getping(this.hover);
}
if (this.hover == false) {
clearInterval(this.timer);
}
},
deep: true,
},
},
};
</script>
<style scoped>
.title {
color: #888;
font-size: 18px;
font-weight: initial;
letter-spacing: 0.25px;
margin-top: 10px;
}
.items {
margin-top: 8px;
}
.item {
display: flex;
margin-bottom: 6px;
}
.item .name {
color: #6a6a6a;
margin-right: 6px;
}
.item .value {
color: #35495e;
font-weight: bold;
}
</style>
<template>
<div>
<el-card>
<el-popover
placement="right"
width="620"
trigger="hover">
<prb-info></prb-info>
<el-button slot="reference">时频图</el-button>
</el-popover>
<el-table :data="slice_info" border stripe>
<el-table-column label="网络切片ID">
<template slot-scope="scope">
<el-button :type="color_arrs[scope.row.id]" circle> {{ scope.row.id }}</el-button>
</template>
</el-table-column>
<el-table-column prop="label" label="业务类型" width="100">
</el-table-column>
<el-table-column label="吞吐量(Mps)">
<template slot-scope="scope">
{{ scope.row.ddqn.thrpt }}
</template>
</el-table-column>
<el-table-column label="时延(ms)">
<template slot-scope="scope">
{{ scope.row.ddqn.delay }}
</template>
</el-table-column>
<el-table-column label="PRB(x2)">
<template slot-scope="scope">
{{ scope.row.id==0?'*':scope.row.ddqn.mrb }}
</template>
</el-table-column>
<el-table-column label="RB使用情况">
<template slot-scope="scope">
{{ scope.row.ddqn.arb }}
</template>
</el-table-column>
</el-table>
</el-card>
<flex-ran></flex-ran>
<!-- <iframe id="show-iframe" style="height:500px;width:100%" frameborder=0 name="showHere" scrolling=auto :src="src"></iframe> -->
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import PRBInfo from "./PRBInfo";
import * as flexranAPI from "../../../utils/flexranAPI";
import FlexRan from '../SshPage/FlexRan.vue';
// 渲染进程接收主进程的传参
Vue.use(vueJsonTreeView);
export default {
data() {
return {
dataList: [],
color_arrs:["info","danger","warning","success"],
slices_getter: "a",
};
},
components: { "prb-info": PRBInfo,"flex-ran":FlexRan },
computed: {
slice_info(){
return this.$store.state.slice_info
},
getterSlice(){
return this.$store.getters.getterSlice
}
},
watch:{
// slice_info:{
// function(val, oldVal) {console.log(val,oldVal)},
// deep: true
// }
}
,
mounted() {
let a = {
dl: {
algorithm: "DDQN",
slices: [
{
id: 0,
label: "Besteffort",
ddqn: {
typeid: 0,
arb: 0,
mrb: 0,
},
},
],
},
};
// ipcRenderer.on("eNB", (event, arg) => {
// if (arg) {
// flexranAPI.START_ENB({});
// const loading = this.$loading({
// lock: true,
// text: "Loading",
// spinner: "el-icon-loading",
// background: "rgba(0, 0, 0, 0.7)",
// });
// setTimeout(() => {
// flexranAPI.ADD_SLICE(a, -1);
// loading.close();
// this.$message({
// message: "成功启动OAI基站",
// type: "success",
// });
// }, 4000);
// }
// });
// ipcRenderer.on("eNBl2", (event, arg) => {
// if (arg) {
// flexranAPI.START_ENB_L2({});
// const loading = this.$loading({
// lock: true,
// text: "Loading",
// spinner: "el-icon-loading",
// background: "rgba(0, 0, 0, 0.7)",
// });
// setTimeout(() => {
// flexranAPI.ADD_SLICE(a, -1);
// loading.close();
// this.$message({
// message: "成功启动OAI基站",
// type: "success",
// });
// }, 2000);
// }
// });
// ipcRenderer.on("addUE", (event, arg) => {
// if (arg) {
// this.$prompt('请输入激活UE数目', 'L2-nFAPI', {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// inputPattern: /^[0-9]$|^[0-2][0-9]$|^3[0-2]$/,
// inputErrorMessage: 'MAX_UE=32'
// }).then(({ value }) => {
// flexranAPI.START_ENB_L2({ues:value});
// const loading = this.$loading({
// lock: true,
// text: "Loading",
// spinner: "el-icon-loading",
// background: "rgba(0, 0, 0, 0.7)",
// });
// setTimeout(() => {
// loading.close();
// this.$message({
// message: "成功启动OAI基站",
// type: "success",
// });
// }, 2000);
// setTimeout(()=>{
// flexranAPI.ADD_SLICE(a, -1);
// },4000)
// }).catch(() => {
// this.$message({
// type: 'info',
// message: '取消输入'
// });
// });
// // flexranAPI.ADD_UE({ueid:this.$store.state.ue_nums});
// // console.log(arg)
// // this.$store.commit("addUes", {});
// }
// });
},
};
</script>
<style scoped>
html,
body,
#app {
height: 100%;
}
.title {
color: #888;
font-size: 18px;
font-weight: initial;
letter-spacing: 0.25px;
margin-top: 10px;
}
.items {
margin-top: 8px;
}
.item {
display: flex;
margin-bottom: 6px;
}
.item .name {
color: #6a6a6a;
margin-right: 6px;
}
.item .value {
color: #35495e;
font-weight: bold;
}
</style>
<template>
<div>
<div v-for="(item1, index1) in ue_list" :key="index1" v-bind="item1">
<el-popover
placement="right"
trigger="hover"
>
<div v-html="pingInfo"></div>
<div
style="margin: 10px"
@mouseover="hover = item1.imsi"
@mouseleave="hover = false"
slot="reference"
>
<span>
<tree-view
:data="{
rnti: item1.rnti,
imsi: item1.imsi,
sliceID: item1.dlSliceId,
label: item1.label,
Rate: item1.Mbs,
}"
:options="{
maxDepth: 2,
rootObjectKey: 'UE ' + index1,
modifiable: false,
slice_num: 1,
}"
/>
</span>
</div>
</el-popover>
</div>
</div>
</template>
<script>
import Vue from "vue";
import vueJsonTreeView from "vue-json-tree-view";
import * as flexranAPI from "../../../utils/flexranAPI";
import Tooltip from "element-ui";
Vue.use(vueJsonTreeView);
Vue.use(Tooltip);
export default {
data() {
return {
hover: false,
ue_list: [],
slice_conf: [],
pingInfo: "PING 172.16.0.x (172.16.0.x) 56(84) bytes of data.<br/>64 bytes from 172.16.0.6: icmp_seq=1 ttl=64 time=39.5 ms<br/>64 bytes from 172.16.0.6: icmp_seq=2 ttl=64 time=39.1 ms<br/>64 bytes from 172.16.0.6: icmp_seq=3 ttl=64 time=28.7 ms<br/>64 bytes from 172.16.0.6: icmp_seq=4 ttl=64 time=45.6 ms<br/><br/>--- 172.16.0.6 ping statistics ---<br/>4 packets transmitted, 4 received, 0% packet loss, time 242ms<br/>rtt min/avg/max/mdev = 28.799/38.307/45.687/6.068 ms<br/>",
visible:false
};
},
mounted() {
this.timeInterval = setInterval(() => {
console.log(result.eNB_config[0].eNB.cellConfig[0].sliceConfig.dl)
flexranAPI.GET_MAC_STATS().then((result) => {
this.slice_conf =
result.eNB_config[0].eNB.cellConfig[0].sliceConfig.dl;
this.ue_list = result.mac_stats[0].ue_list;
for (let i = 0; i < this.ue_list.length; i++) {
let slice_type = this.slice_conf.slices.filter(
(_item) => _item.id === this.ue_list[i].dlSliceId
);
this.ue_list[i].label = slice_type[0].label;
}
});
}, 1000);
},
methods: {
async getping(imsi) {
this.timer = setInterval(() => {
flexranAPI.SEND_PING({ imsi: imsi }).then((result) => {
this.pingInfo = result.output.split("\n").join("<br/>");
});
}, 1000);
},
},
watch: {
hover: {
handler(newValue, oldValue) {
console.log(this.hover);
if (this.hover !== false) {
this.getping(this.hover);
}
if (this.hover == false) {
clearInterval(this.timer);
}
},
deep: true,
},
},
};
</script>
<style scoped>
.title {
color: #888;
font-size: 18px;
font-weight: initial;
letter-spacing: 0.25px;
margin-top: 10px;
}
.items {
margin-top: 8px;
}
.item {
display: flex;
margin-bottom: 6px;
}
.item .name {
color: #6a6a6a;
margin-right: 6px;
}
.item .value {
color: #35495e;
font-weight: bold;
}
</style>
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App'
import router from './router'
import {Table} from 'element-ui'
import store from './store/index';
Vue.http = Vue.prototype.$http = axios
Vue.config.productionTip = false
Vue.use(Table);
Vue.use(ElementUI);
Vue.use(Vuex);
/* eslint-disable no-new */
new Vue({
components: { App },
router,
store,
template: '<App/>'
}).$mount('#app')
import Vue from 'vue'
import Router from 'vue-router'
import SshPage from '@/components/SshPage/SshPage'
import FlexRan from '@/components/SshPage/FlexRan'
Vue.use(Router)
let router =[
{
path: '/',
name: 'landing-page',
component: require('@/components/LandingPage').default
},
{
path: '/ssh/:host/:action/:user/:pass',
name: 'ssh-page',
component: SshPage
},
{
path: '/flexran',
name: 'flex-ran',
component: FlexRan
}
]
export default new Router({
routes:router
})
const actions = {
updateSlcie(context) {
context.commit('updateSlices', {
num: 2
})
}
}
export default actions;
\ No newline at end of file
const getters = {
getterSlice(state) {
console.log(state);
return state.slice_info;
}
}
export default getters;
\ No newline at end of file
import Vue from 'vue';
import Vuex from 'vuex';
import state from './rootState.js';
import getters from './getters.js';
import mutations from './mutations.js';
import actions from './actions.js';
Vue.use(Vuex);
const store = new Vuex.Store({
state,
getters,
actions,
mutations
});
export default store;
const mutations = {
updateSlices(state, obj) {
return state.slice_info = obj.slice_info;
},
updateUes(state, obj) {
return state.ue_list = obj.ue_list;
} ,
addUes(state, obj) {
return state.ue_nums += 1;
} ,
updatePrbs(state, obj) {
obj.prb_info=resize_(obj.prb_info)
if(state.prb_info.length==30){
state.prb_info.shift();
}
return state.prb_info.push(obj.prb_info);
}
}
const resize_ = (arr)=>{
for(let i=0;i<3;i++){
arr.unshift(arr.pop());
}
return arr
}
export default mutations;
\ No newline at end of file
const state = {
slice_info:[],
ue_list:[],
prb_info:[],
ue_nums:0
}
export default state;
\ No newline at end of file
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
import { service, request } from './network_services'
let url = `ustb-oai.com`
export function SET_URL (data = {}) {
// 接口请求
url="10.25.20.227"
}
export function GET_URL (data = {}) {
// 接口请求
return url
}
/**
* @description 获取MAC_Stats
* @param {Object} data NONE
*/
export function GET_MAC_STATS (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/stats`,
method: `get`,
data
})
}
/**
* @description 启动eNB
* @param {Object} data NONE
*/
export function START_ENB (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/startenb`,
method: `get`,
data
})
}
/**
* @description 启动eNBl2
* @param {Object} data NONE
*/
export function START_ENB_L2 (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/startenbl2`,
method: `post`,
data
})
}
/**
* @description Add_UE
* @param {Object} data NONE
*/
export function ADD_UE (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/startue`,
method: `post`,
data
})
}
/**
* @description 获取IPV4
* @param {Object} data {"imsi":"208920100001105"}
*/
export function GET_IPV4_IMSI (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/getip`,
method: `post`,
data
})
}
/**
* @description 获取IPV4
* @param {Object} data {"host":"172.16.0.8"}
*/
export function SEND_PING (data = {}) {
// 接口请求
return request({
url: `http://${url}:8110/api/pingapp`,
method: `post`,
data
})
}
/**
* @description Enables the ElasticMon logging framework. Note that this might notably fail because the endpoint is not configured properly or because logging is already active.
* @param {Object} data NONE
*/
export function ENABLE_ELASTIC (data = {}) {
// 接口请求
return request({
url: `/elasticmon/enable`,
method: `post`,
data
})
}
/**
* @description This API endpoint changes the cell configuration of the eNodeB in the underlying agent, effectively resulting in soft-restart of the base station (only L1/L2/L3 will be restarted). The parameters are specified as a JSON file with the format of the cellConfig as contained in the agent configuration, but only the parametrs dlBandwidth, ulBandwidth, dlFreq, ulFreq end eutraBand are accepted.
* @param {Object} data {"dlBandwidth": 50,"ulBandwidth": 50, "dlFreq": 2650,"ulFreq": 2530, "eutraBand": 7};
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function CHANGE_CELL_CONF (data = {}, ENB_ID) {
// 接口请求
return request({
url: `/conf/enb/` + ENB_ID,
method: `post`,
data
})
}
/**
* @description This API endpoint triggers the base station to connect to a new MME (and therefore, to a new core network). The list of PLMNs should be configured such that the PLMN(s) served by this new CN are present in the RAN (either through eNB configuration, or dynamically through the corresponding north-bound call). Note that a registration with a subset of the PLMNs (e.g., to hide a PLMN from the CN) is not possible.
* @param {Object} data {
"mme": [
{
"s1Ip": "192.168.12.4"
}
]
}
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function ADD_NEW_MME (data = {}, ENB_ID) {
// 接口请求
return request({
url: `/mme/enb/` + ENB_ID,
method: `post`,
data
})
}
/**
* @description This API saves a list of IMSIs or regular expressions matching on IMSIs in order to auto-associate those to a particular slice when they connect. It is checked that the base station has a slice with the given slice ID. Whenever a UE whose IMSI is known (this might not always be the case, go to flight mode and exit to get it reliably) is not in the slice it was associated to, it will automatically be associated to this slice. When associating a new list to a slice which already has an association list, that list will be removed.
* @param {Object} data [
"^20895"
]
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function AUTO_SLICE_ASSOC (data = {}, ENB_ID, SLICE_ID) {
// 接口请求
return request({
url: `/auto_ue_slice_assoc/enb/` + ENB_ID + ` /slice/` + SLICE_ID + `/dl`,
method: `post`,
data
})
}
/**
* @description This API endpoint changes the association of a UE in an underlying agent, specified as a JSON file with the format of the ueConfig as contained in the agent configuration. It can be used to changed the association of UEs using their current RNTI or IMSI. In the request, a slice ID and RNTI or IMSI must be present. The stats call should always be used after triggering this endpoint and sufficient time to verify the actions have been taken.
* @param {Object} data {
"ueConfig": [
{
"imsi": 208940100001115,
"dlSliceId": 3,
"ulSliceId": 3
}
]
}
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function CHANGE_SLICE_ASSOC (data = {}, ENB_ID) {
// 接口请求
return request({
url: `http://${url}:9999/ue_slice_assoc/enb/` + ENB_ID,
method: `post`,
data
})
}
/**
* @description This API endpoint deletes slices as specified in the JSON data in the body specified as a JSON file with the format of the sliceConfig as contained in the cellConfig of a agent configuration for a given agent. A valid slice ID must present. Slice 0 can not be removed. To remove the slice algorithm, consider posting the None slice algorithm instead.
* @param {Object} data {
"dl": {
"slices": [
{
"id": 3,
}
]
}
}
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function DELETE_SLICE (data = {}, ENB_ID) {
// 接口请求
return request({
url: `/slice/enb/` + ENB_ID,
method: `delete`,
data
})
}
/**
* @description This API endpoint posts a new slice configuration to an underlying agent, specified as a JSON file with the format of the sliceConfig as contained in the cellConfig of an agent configuration (for a description of the parameters, see below), or the scheduler to use if no slicing algorithm is chosen (None). It can be used to create arbitrary slices with an arbitrary ID or to change slices by specifying an ID for an existing slice. In the request, a slice ID must be present, as well as the slice parameters. The label is optional, and if no scheduler is given, the scheduler that was active when enabling slicing will be used. The stats call should always be used after triggering this endpoint and sufficient time to verify the actions have been taken. Note that the scheduler (within dl/ul) and the slices parameters are mutually exclusive, since the first only applies for no slicing algorithm (None), whereas the latter only applies if a slicing algorithm has been chosen.This API call has changed as of July 2020. For a description of how the old parameters can be reproduced in the new call, see Deprecated Slice ConfigurationRemarks on the Static slicing algorithm: this algorithm does not provide any sharing. Note that posLow/posHigh are in terms of resource block groups (RBG) in DL and resource blocks (RB) in UL. Furthermore, it is not checked that the channel bandwidth can actually accommodate this slice (posLow=100 and posHigh=110 are a valid entry, but they will never work, since LTE has a maximum bandwidth of 100RBs). Please refer to the stats call to check the amount of resource blocks as well as the resource block group size which will tell the applicable RB/RBG settings. Please also note that OAI reserves the first and last 1, 2, or 3 RBs (for bandwidths 25, 50, or 100RBs, respectively) for PUCCH, meaning that these first/last RBs should be spared out/they won`t be given to the slice. Also, the minimum RB size in UL is 3!
* @param {Object} data {"dl":{"algorithm":"SCN19","slices":[
{"id":0,"scn19":{"typeid":1,"type":"static","posLow":0,"posHigh":8}},
{"id":2,"scn19":{"typeid":2,"type":"dynamic","kpsRequired":100,"kpsReference":1200}},
{"id":3,"scn19":{"typeid":2,"type":"dynamic","kpsRequired":1200,"kpsReference":1200}},
{"id":4,"scn19":{"typeid":2,"type":"dynamic","kpsRequired":500,"kpsReference":1200}}]}}
* @param {Object} ENB_ID Default -1 for eNB 0
*/
export function ADD_SLICE (data = {}, ENB_ID) {
// 接口请求
return request({
url: `http://${url}:9999/slice/enb/` + ENB_ID,
method: `post`,
data
})
}
/**
* @description 探测网络环境
*/
export function DETECT (data = {}) {
// 接口请求
return request({
url: `http://pv.sohu.com/cityjson?ie=utf-8`,
method: `get`,
data
})
}
/**
* @description 获取归属地
*/
export function DETECT_LOCAL (data = {},ip) {
// 接口请求
return request({
url: `https://www.svlik.com/t/ipapi/ip.php?ip=${ip}&type=0`,
method: `get`,
data
})
}
\ No newline at end of file
import axios from 'axios'
import qs from 'qs'
import { get, isEmpty } from 'lodash'
axios.defaults.adapter = require('axios/lib/adapters/http');
function handleError (error) {
// 添加到日志
// 打印到控制台
// console.log(error)
}
/**
* @description 创建请求实例
*/
function createService () {
// 创建一个 axios 实例
const service = axios.create()
// 请求拦截
service.interceptors.request.use(
config => config,
error => {
// 发送失败
console.log(error)
return Promise.reject(error)
}
)
// 响应拦截
service.interceptors.response.use(
response => {
// http 状态码 200 情况
// 根据 前后端约定的 response.data.code 判断接口是否请求成功
// 例如 接口返回数据为
// {
// code: 0,
// msg: 'success',
// data: {
// list: [],
// count: 0
// }
// }
// 此时
// response.data.code :
// 0
// response.data.msg :
// 'success'
// response.data.data : (在调用接口)
// {
// list: [],
// count: 0
// }
// 默认约定 code 为 0 时代表成功
// 你也可以不使用这种方法,改为在下面的 http 错误拦截器里做处理
// 没有 code 视为非项目接口不作处理
if (response.data.code === undefined) {
return response.data
}
// 有 code 判断为项目接口请求
switch (response.data.code) {
// 返回响应内容
case 0: return response.data.data
// 例如在 code 401 情况下退回到登录页面
case 401: throw new Error('请重新登录')
// 根据需要添加其它判断
default: throw new Error(`${response.data.msg}: ${response.config.url}`)
}
},
error => {
const status = get(error, 'response.status')
switch (status) {
case 400: error.message = '请求错误'; break
case 401: error.message = '未授权,请登录'; break
case 403: error.message = '拒绝访问'; break
case 404: error.message = `请求地址出错: ${error.response.config.url}`; break
case 408: error.message = '请求超时'; break
case 500: error.message = '服务器内部错误'; break
case 501: error.message = '服务未实现'; break
case 502: error.message = '网关错误'; break
case 503: error.message = '服务不可用'; break
case 504: error.message = '网关超时'; break
case 505: error.message = 'HTTP版本不受支持'; break
case 204: error.message = 'Content-Type'; break
default: break
}
handleError(error)
//throw error
}
)
return service
}
function stringify (data) {
return qs.stringify(data, { allowDots: true, encode: false })
}
/**
* @description 创建请求方法
* @param {Object} service axios 实例
*/
function createRequest (service) {
return function (config) {
const token = ''
const configDefault = {
headers: {
'Content-Type': get(config, 'headers.Content-Type', 'application/json')
},
timeout: 5000,
baseURL: process.env.VUE_APP_API,
data: {}
}
const option = Object.assign(configDefault, config)
// 处理 get 请求的参数
// 请根据实际需要修改
if (!isEmpty(option.params)) {
option.url = option.url + '?' + stringify(option.params)
option.params = {}
}
// 当需要以 form 形式发送时 处理发送的数据
// 请根据实际需要修改
if (!isEmpty(option.data) && option.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
option.data = stringify(option.data)
}
return service(option)
}
}
// 用于真实网络请求的实例和请求方法
export const service = createService()
export const request = createRequest(service)
\ No newline at end of file
<template>
<remote-js :src="src"></remote-js>
</template>
<script>
export default {
name: 'OuterIp',
data() {
return {
src: ''
}
},
components: {
'remote-js': {
render(createElement) {
return createElement('script', {
attrs: { type: 'text/javascript', src: this.src || 'http://pv.sohu.com/cityjson?ie=utf-8' }
})
},
props: {
src: { type: String, required: true }
}
}
}
}
</script>
\ No newline at end of file
module.exports = {
lintOnSave: false
}
This diff is collapsed.
<template>
<div style="height: 100%">
<div
v-for="(item1, index1) in srcs"
:key="index1"
v-bind="item1"
v-show="item1.active">
<iframe
:id="index1"
style="height: 500px; width: 100%"
frameborder="0"
:name="index1"
scrolling="auto"
:src="item1.url"
></iframe>
</div>
<div class="flex" >
<div class="flex" >
<div
v-for="(item1, index1) in srcs"
:key="index1"
......@@ -35,9 +20,12 @@
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,0)"> 查看OAI基站LOG</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,3)"> 查看OAI UELOG</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,5)"> 查看空口协议</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,6)"> 开始下载</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='OAI_ENB'" @click="handleCommand2(index1,7)"> 停止下载</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='CoreNet'" @click="handleCommand2(index1,4)"> 查看GTP流量</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='FlexRan'" @click="refresh"> 刷新</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='AI-Engine'" @click="handleCommand2(index1,1)"> 启动DRL切片智能分配</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='AI-Engine'" @click="handleCommand2(index1,8)"> Categorical DQN</div></el-dropdown-item>
<el-dropdown-item ><div v-if="item1.name=='CoreNet'" @click="handleCommand2(index1,2)"> 查看MME LOG</div></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
......@@ -55,6 +43,22 @@
</el-dropdown-menu>
</el-dropdown>
</div>
<div
v-for="(item1, index1) in srcs"
:key="index1"
v-bind="item1"
v-show="item1.active">
<iframe
:id="index1"
style="height: 700px; width: 100%"
frameborder="0"
:name="index1"
scrolling="auto"
:src="item1.url"
></iframe>
</div>
<!-- <img src="~@/assets/ustb-oai.com.png" alt="electron-vue" height="4%" > -->
</div>
......@@ -73,7 +77,7 @@ export default {
host: "",
action: "",
view: true,
commands:['tail -f ~/log/enb.log','cd /root/dqn_zoo/Dueling\\ DDQN/ && python dueling_ddqn.py','tail -f /root/log/mme.log','tail -f ~/log/ue.log',"tshark -i gtp0 ","tshark -i lo -f 'udp dst port 9999' --enable-heuristic mac_lte_udp "],
commands:['tail -f ~/log/enb.log','unset http_proxy&&cd /root/dqn_zoo/Dueling\\ DDQN/ && python dueling_ddqn.py','tail -f /root/log/mme.log','tail -f ~/log/ue.log',"tshark -i gtp0 ","tshark -i lo -f 'udp dst port 9999' --enable-heuristic mac_lte_udp ","/usr/bin/download_video","/usr/bin/stop_wget",'unset http_proxy&&cd /root/dqn_zoo/Categorical\\ DQN/ && python categorical_dqn.py',],
ssh_srcs:[ {
name: "OAI_ENB",
active: false,
......
......@@ -9,14 +9,16 @@
<el-button slot="reference">时频图</el-button>
</el-popover>
<el-table :data="slice_info" border stripe>
<el-table-column label="网络切片ID">
<el-table-column label="网络切片ID" width="75px">
<template slot-scope="scope">
<el-button :type="color_arrs[scope.row.id]" circle> {{ scope.row.id }}</el-button>
</template>
</el-table-column>
<el-table-column prop="label" label="业务类型" width="100">
<el-table-column prop="label" label="业务类型" width="150px">
<template slot-scope="scope">
{{ scope.row.label }}
</template>
</el-table-column>
<el-table-column label="吞吐量(Mps)">
<template slot-scope="scope">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment