web/frps: upgrade vue and element-plus (#3310)

This commit is contained in:
fatedier
2023-02-16 02:45:48 +08:00
committed by GitHub
parent 39941117b6
commit 24f0b3afa5
48 changed files with 3925 additions and 7309 deletions

View File

@@ -1,81 +1,85 @@
<template>
<div id="app">
<header class="grid-content header-color">
<el-row>
<a class="brand" href="#">frp</a>
</el-row>
</header>
<section>
<el-row>
<el-col id="side-nav" :xs="24" :md="4">
<el-menu default-active="1" mode="vertical" theme="light" router="false" @select="handleSelect">
<el-menu-item index="/">Overview</el-menu-item>
<el-submenu index="/proxies">
<template slot="title">Proxies</template>
<el-menu-item index="/proxies/tcp">TCP</el-menu-item>
<el-menu-item index="/proxies/udp">UDP</el-menu-item>
<el-menu-item index="/proxies/http">HTTP</el-menu-item>
<el-menu-item index="/proxies/https">HTTPS</el-menu-item>
<el-menu-item index="/proxies/stcp">STCP</el-menu-item>
<el-menu-item index="/proxies/sudp">SUDP</el-menu-item>
</el-submenu>
<el-menu-item index="">Help</el-menu-item>
</el-menu>
</el-col>
<div id="app">
<header class="grid-content header-color">
<el-row>
<a class="brand" href="#">frp</a>
</el-row>
</header>
<section>
<el-row>
<el-col id="side-nav" :xs="24" :md="4">
<el-menu
default-active="/"
mode="vertical"
theme="light"
router="false"
@select="handleSelect"
>
<el-menu-item index="/">Overview</el-menu-item>
<el-sub-menu index="/proxies">
<template #title>
<span>Proxies</span>
</template>
<el-menu-item index="/proxies/tcp">TCP</el-menu-item>
<el-menu-item index="/proxies/udp">UDP</el-menu-item>
<el-menu-item index="/proxies/http">HTTP</el-menu-item>
<el-menu-item index="/proxies/https">HTTPS</el-menu-item>
<el-menu-item index="/proxies/stcp">STCP</el-menu-item>
<el-menu-item index="/proxies/sudp">SUDP</el-menu-item>
</el-sub-menu>
<el-menu-item index="">Help</el-menu-item>
</el-menu>
</el-col>
<el-col :xs="24" :md="20">
<div id="content">
<router-view></router-view>
</div>
</el-col>
</el-row>
</section>
<footer></footer>
</div>
<el-col :xs="24" :md="20">
<div id="content">
<router-view></router-view>
</div>
</el-col>
</el-row>
</section>
<footer></footer>
</div>
</template>
<script>
export default {
methods: {
handleSelect(key, path) {
if (key == '') {
window.open("https://github.com/fatedier/frp")
}
}
}
}
<script setup lang="ts">
const handleSelect = (key: string) => {
if (key == '') {
window.open('https://github.com/fatedier/frp')
}
}
</script>
<style>
body {
background-color: #fafafa;
margin: 0px;
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,sans-serif;
}
header {
width: 100%;
height: 60px;
}
.header-color {
background: #58B7FF;
}
#content {
margin-top: 20px;
padding-right: 40px;
}
.brand {
color: #fff;
background-color: transparent;
margin-left: 20px;
float: left;
line-height: 25px;
font-size: 25px;
padding: 15px 15px;
height: 30px;
text-decoration: none;
}
body {
background-color: #fafafa;
margin: 0px;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif;
}
header {
width: 100%;
height: 60px;
}
.header-color {
background: #58b7ff;
}
#content {
margin-top: 20px;
padding-right: 40px;
}
.brand {
color: #fff;
background-color: transparent;
margin-left: 20px;
float: left;
line-height: 25px;
font-size: 25px;
padding: 15px 15px;
height: 30px;
text-decoration: none;
}
</style>

View File

@@ -0,0 +1,22 @@
.el-form-item span {
margin-left: 15px;
}
.proxy-table-expand {
font-size: 0;
}
.proxy-table-expand .el-form-item__label{
width: 90px;
color: #99a9bf;
}
.proxy-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
.el-table .el-table__expanded-cell {
padding: 20px 50px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -1,169 +0,0 @@
<template>
<div>
<el-row>
<el-col :md="12">
<div class="source">
<el-form label-position="left" class="server_info">
<el-form-item label="Version">
<span>{{ version }}</span>
</el-form-item>
<el-form-item label="BindPort">
<span>{{ bind_port }}</span>
</el-form-item>
<el-form-item label="BindUdpPort">
<span>{{ bind_udp_port }}</span>
</el-form-item>
<el-form-item label="Http Port">
<span>{{ vhost_http_port }}</span>
</el-form-item>
<el-form-item label="Https Port">
<span>{{ vhost_https_port }}</span>
</el-form-item>
<el-form-item label="Subdomain Host">
<span>{{ subdomain_host }}</span>
</el-form-item>
<el-form-item label="Max PoolCount">
<span>{{ max_pool_count }}</span>
</el-form-item>
<el-form-item label="Max Ports Per Client">
<span>{{ max_ports_per_client }}</span>
</el-form-item>
<el-form-item label="HeartBeat Timeout">
<span>{{ heart_beat_timeout }}</span>
</el-form-item>
<el-form-item label="Client Counts">
<span>{{ client_counts }}</span>
</el-form-item>
<el-form-item label="Current Connections">
<span>{{ cur_conns }}</span>
</el-form-item>
<el-form-item label="Proxy Counts">
<span>{{ proxy_counts }}</span>
</el-form-item>
</el-form>
</div>
</el-col>
<el-col :md="12">
<div id="traffic" style="width: 400px;height:250px;margin-bottom: 30px;"></div>
<div id="proxies" style="width: 400px;height:250px;"></div>
</el-col>
</el-row>
</div>
</template>
<script>
import {DrawTrafficChart, DrawProxyChart} from '../utils/chart.js'
export default {
data() {
return {
version: '',
bind_port: '',
bind_udp_port: '',
vhost_http_port: '',
vhost_https_port: '',
subdomain_host: '',
max_pool_count: '',
max_ports_per_client: '',
heart_beat_timeout: '',
client_counts: '',
cur_conns: '',
proxy_counts: ''
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
fetchData() {
fetch('../api/serverinfo', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.version = json.version
this.bind_port = json.bind_port
this.bind_udp_port = json.bind_udp_port
if (this.bind_udp_port == 0) {
this.bind_udp_port = "disable"
}
this.vhost_http_port = json.vhost_http_port
if (this.vhost_http_port == 0) {
this.vhost_http_port = "disable"
}
this.vhost_https_port = json.vhost_https_port
if (this.vhost_https_port == 0) {
this.vhost_https_port = "disable"
}
this.subdomain_host = json.subdomain_host
this.max_pool_count = json.max_pool_count
this.max_ports_per_client = json.max_ports_per_client
if (this.max_ports_per_client == 0) {
this.max_ports_per_client = "no limit"
}
this.heart_beat_timeout = json.heart_beat_timeout
this.client_counts = json.client_counts
this.cur_conns = json.cur_conns
this.proxy_counts = 0
if (json.proxy_type_count != null) {
if (json.proxy_type_count.tcp != null) {
this.proxy_counts += json.proxy_type_count.tcp
}
if (json.proxy_type_count.udp != null) {
this.proxy_counts += json.proxy_type_count.udp
}
if (json.proxy_type_count.http != null) {
this.proxy_counts += json.proxy_type_count.http
}
if (json.proxy_type_count.https != null) {
this.proxy_counts += json.proxy_type_count.https
}
if (json.proxy_type_count.stcp != null) {
this.proxy_counts += json.proxy_type_count.stcp
}
if (json.proxy_type_count.sudp != null) {
this.proxy_counts += json.proxy_type_count.sudp
}
if (json.proxy_type_count.xtcp != null) {
this.proxy_counts += json.proxy_type_count.xtcp
}
}
DrawTrafficChart('traffic', json.total_traffic_in, json.total_traffic_out)
DrawProxyChart('proxies', json)
}).catch( err => {
this.$message({
showClose: true,
message: 'Get server info from frps failed!',
type: 'warning'
})
})
}
}
}
</script>
<style>
.source {
border: 1px solid #eaeefb;
border-radius: 4px;
transition: .2s;
padding: 24px;
}
.server_info {
margin-left: 40px;
font-size: 0px;
}
.server_info label {
width: 150px;
color: #99a9bf;
}
.server_info .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 100%;
}
</style>

View File

@@ -1,148 +1,41 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" style="margin-bottom:10px">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Domains">
<span>{{ props.row.custom_domains }}</span>
</el-form-item>
<el-form-item label="SubDomain">
<span>{{ props.row.subdomain }}</span>
</el-form-item>
<el-form-item label="locations">
<span>{{ props.row.locations }}</span>
</el-form-item>
<el-form-item label="HostRewrite">
<span>{{ props.row.host_header_rewrite }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Port"
prop="port"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="http" />
</template>
<script>
import Humanize from 'humanize-plus';
import Traffic from './Traffic.vue'
import {
HttpProxy
} from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
vhost_http_port: "",
subdomain_host: ""
<script setup lang="ts">
import { ref } from 'vue'
import { HTTPProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<HTTPProxy[]>([])
const fetchData = () => {
let vhost_http_port: number
let subdomain_host: string
fetch('../api/serverinfo', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
vhost_http_port = json.vhost_http_port
subdomain_host = json.subdomain_host
if (vhost_http_port == null || vhost_http_port == 0) {
return
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/serverinfo', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.vhost_http_port = json.vhost_http_port
this.subdomain_host = json.subdomain_host
if (this.vhost_http_port == null || this.vhost_http_port == 0) {
return
} else {
fetch('../api/proxy/http', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new HttpProxy(proxyStats, this.vhost_http_port, this.subdomain_host))
}
})
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
fetch('../api/proxy/http', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(
new HTTPProxy(proxyStats, vhost_http_port, subdomain_host)
)
}
})
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -1,143 +1,41 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" style="margin-bottom:10px">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Domains">
<span>{{ props.row.custom_domains }}</span>
</el-form-item>
<el-form-item label="SubDomain">
<span>{{ props.row.subdomain }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Port"
prop="port"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="https" />
</template>
<script>
import Humanize from 'humanize-plus';
import Traffic from './Traffic.vue'
import {
HttpsProxy
} from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
vhost_https_port: '',
subdomain_host: ''
<script setup lang="ts">
import { ref } from 'vue'
import { HTTPSProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<HTTPSProxy[]>([])
const fetchData = () => {
let vhost_https_port: number
let subdomain_host: string
fetch('../api/serverinfo', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
vhost_https_port = json.vhost_https_port
subdomain_host = json.subdomain_host
if (vhost_https_port == null || vhost_https_port == 0) {
return
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/serverinfo', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.vhost_https_port = json.vhost_https_port
this.subdomain_host = json.subdomain_host
if (this.vhost_https_port == null || this.vhost_https_port == 0) {
return
} else {
fetch('../api/proxy/https', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new HttpsProxy(proxyStats, this.vhost_https_port, this.subdomain_host))
}
})
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
fetch('../api/proxy/https', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(
new HTTPSProxy(proxyStats, vhost_https_port, subdomain_host)
)
}
})
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -1,116 +1,26 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" :name="props.row.name" style="margin-bottom:10px" @click="fetchData2">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="stcp" />
</template>
<script>
import Humanize from 'humanize-plus'
import Traffic from './Traffic.vue'
import { StcpProxy } from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
<script setup lang="ts">
import { ref } from 'vue'
import { STCPProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<STCPProxy[]>([])
const fetchData = () => {
fetch('../api/proxy/stcp', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(new STCPProxy(proxyStats))
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/proxy/stcp', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new StcpProxy(proxyStats))
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -1,116 +1,26 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" :name="props.row.name" style="margin-bottom:10px" @click="fetchData2">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="sudp" />
</template>
<script>
import Humanize from 'humanize-plus'
import Traffic from './Traffic.vue'
import { SudpProxy } from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
<script setup lang="ts">
import { ref } from 'vue'
import { SUDPProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<SUDPProxy[]>([])
const fetchData = () => {
fetch('../api/proxy/sudp', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(new SUDPProxy(proxyStats))
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/proxy/sudp', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new SudpProxy(proxyStats))
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -1,124 +1,26 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" :name="props.row.name" style="margin-bottom:10px" @click="fetchData2">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Addr">
<span>{{ props.row.addr }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Port"
prop="port"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="tcp" />
</template>
<script>
import Humanize from 'humanize-plus'
import Traffic from './Traffic.vue'
import { TcpProxy } from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
<script setup lang="ts">
import { ref } from 'vue'
import { TCPProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<TCPProxy[]>([])
const fetchData = () => {
fetch('../api/proxy/tcp', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(new TCPProxy(proxyStats))
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/proxy/tcp', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new TcpProxy(proxyStats))
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -1,126 +1,27 @@
<template>
<div>
<el-table :data="proxies" :default-sort="{prop: 'name', order: 'ascending'}" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-popover
ref="popover4"
placement="right"
width="600"
style="margin-left:0px"
trigger="click">
<my-traffic-chart :proxy_name="props.row.name"></my-traffic-chart>
</el-popover>
<el-button v-popover:popover4 type="primary" size="small" icon="view" style="margin-bottom:10px">Traffic Statistics</el-button>
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="Name">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ props.row.type }}</span>
</el-form-item>
<el-form-item label="Addr">
<span>{{ props.row.addr }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ props.row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ props.row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ props.row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ props.row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="Name"
prop="name"
sortable>
</el-table-column>
<el-table-column
label="Port"
prop="port"
sortable>
</el-table-column>
<el-table-column
label="Connections"
prop="conns"
sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable>
</el-table-column>
<el-table-column
label="status"
prop="status"
sortable>
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.status === 'online'">{{ scope.row.status }}</el-tag>
<el-tag type="danger" v-else>{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<ProxyView :proxies="proxies" proxyType="udp" />
</template>
<script>
import Humanize from 'humanize-plus';
import Traffic from './Traffic.vue'
import {
UdpProxy
} from '../utils/proxy.js'
export default {
data() {
return {
proxies: new Array(),
<script setup lang="ts">
import { ref } from 'vue'
import { UDPProxy } from '../utils/proxy.js'
import ProxyView from './ProxyView.vue'
let proxies = ref<UDPProxy[]>([])
const fetchData = () => {
fetch('../api/proxy/udp', { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
for (let proxyStats of json.proxies) {
proxies.value.push(new UDPProxy(proxyStats))
}
},
created() {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
formatTrafficIn(row, column) {
return Humanize.fileSize(row.traffic_in)
},
formatTrafficOut(row, column) {
return Humanize.fileSize(row.traffic_out)
},
fetchData() {
fetch('../api/proxy/udp', {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
this.proxies = new Array()
for (let proxyStats of json.proxies) {
this.proxies.push(new UdpProxy(proxyStats))
}
})
}
},
components: {
'my-traffic-chart': Traffic
}
}
})
}
fetchData()
</script>
<style>
</style>
<style></style>

View File

@@ -0,0 +1,91 @@
<template>
<div>
<el-table
:data="proxies"
:default-sort="{ prop: 'name', order: 'ascending' }"
style="width: 100%"
>
<el-table-column type="expand">
<template #default="props">
<el-popover
ref="popoverTraffic"
:virtual-ref="buttonTraffic"
placement="right"
width="600"
style="margin-left: 0px"
trigger="click"
virtual-triggering
>
<Traffic :proxy_name="props.row.name" />
</el-popover>
<el-button
ref="buttonTraffic"
type="primary"
size="large"
:name="props.row.name"
style="margin-bottom: 10px"
v-click-outside="onClickTrafficStats"
>Traffic Statistics
</el-button>
<ProxyViewExpand :row="props.row" :proxyType="proxyType" />
</template>
</el-table-column>
<el-table-column label="Name" prop="name" sortable> </el-table-column>
<el-table-column label="Port" prop="port" sortable> </el-table-column>
<el-table-column label="Connections" prop="conns" sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="traffic_in"
:formatter="formatTrafficIn"
sortable
>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="traffic_out"
:formatter="formatTrafficOut"
sortable
>
</el-table-column>
<el-table-column label="status" prop="status" sortable>
<template #default="scope">
<el-tag v-if="scope.row.status === 'online'" type="success">{{
scope.row.status
}}</el-tag>
<el-tag v-else type="danger">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, unref } from 'vue'
import * as Humanize from 'humanize-plus'
import type { TableColumnCtx } from 'element-plus'
import type { BaseProxy } from '../utils/proxy.js'
import ProxyViewExpand from './ProxyViewExpand.vue'
defineProps<{
proxies: BaseProxy[]
proxyType: string
}>()
const formatTrafficIn = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
return Humanize.fileSize(row.traffic_in)
}
const formatTrafficOut = (row: BaseProxy, _: TableColumnCtx<BaseProxy>) => {
return Humanize.fileSize(row.traffic_out)
}
const buttonTraffic = ref()
const popoverTraffic = ref()
const onClickTrafficStats = () => {
unref(popoverTraffic).popoverTraffic?.delayHide?.()
}
</script>

View File

@@ -0,0 +1,70 @@
<template>
<el-form
label-position="left"
inline
class="proxy-table-expand"
v-if="proxyType === 'http' || proxyType === 'https'"
>
<el-form-item label="Name">
<span>{{ row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ row.type }}</span>
</el-form-item>
<el-form-item label="Domains">
<span>{{ row.custom_domains }}</span>
</el-form-item>
<el-form-item label="SubDomain">
<span>{{ row.subdomain }}</span>
</el-form-item>
<el-form-item label="locations">
<span>{{ row.locations }}</span>
</el-form-item>
<el-form-item label="HostRewrite">
<span>{{ row.host_header_rewrite }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ row.last_close_time }}</span>
</el-form-item>
</el-form>
<el-form label-position="left" inline class="proxy-table-expand" v-else>
<el-form-item label="Name">
<span>{{ row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<span>{{ row.type }}</span>
</el-form-item>
<el-form-item label="Addr">
<span>{{ row.addr }}</span>
</el-form-item>
<el-form-item label="Encryption">
<span>{{ row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<span>{{ row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<span>{{ row.last_start_time }}</span>
</el-form-item>
<el-form-item label="Last Close">
<span>{{ row.last_close_time }}</span>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
defineProps<{
row: any
proxyType: string
}>()
</script>

View File

@@ -0,0 +1,177 @@
<template>
<div>
<el-row>
<el-col :md="12">
<div class="source">
<el-form
label-position="left"
label-width="160px"
class="server_info"
>
<el-form-item label="Version">
<span>{{ data.version }}</span>
</el-form-item>
<el-form-item label="BindPort">
<span>{{ data.bind_port }}</span>
</el-form-item>
<el-form-item label="BindUdpPort">
<span>{{ data.bind_udp_port }}</span>
</el-form-item>
<el-form-item label="Http Port">
<span>{{ data.vhost_http_port }}</span>
</el-form-item>
<el-form-item label="Https Port">
<span>{{ data.vhost_https_port }}</span>
</el-form-item>
<el-form-item label="Subdomain Host">
<span>{{ data.subdomain_host }}</span>
</el-form-item>
<el-form-item label="Max PoolCount">
<span>{{ data.max_pool_count }}</span>
</el-form-item>
<el-form-item label="Max Ports Per Client">
<span>{{ data.max_ports_per_client }}</span>
</el-form-item>
<el-form-item label="HeartBeat Timeout">
<span>{{ data.heart_beat_timeout }}</span>
</el-form-item>
<el-form-item label="Client Counts">
<span>{{ data.client_counts }}</span>
</el-form-item>
<el-form-item label="Current Connections">
<span>{{ data.cur_conns }}</span>
</el-form-item>
<el-form-item label="Proxy Counts">
<span>{{ data.proxy_counts }}</span>
</el-form-item>
</el-form>
</div>
</el-col>
<el-col :md="12">
<div
id="traffic"
style="width: 400px; height: 250px; margin-bottom: 30px"
></div>
<div id="proxies" style="width: 400px; height: 250px"></div>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { DrawTrafficChart, DrawProxyChart } from '../utils/chart'
let data = ref({
version: '',
bind_port: '',
bind_udp_port: '',
vhost_http_port: '',
vhost_https_port: '',
subdomain_host: '',
max_pool_count: '',
max_ports_per_client: '',
heart_beat_timeout: '',
client_counts: '',
cur_conns: '',
proxy_counts: 0,
})
const fetchData = () => {
fetch('../api/serverinfo', { credentials: 'include' })
.then((res) => res.json())
.then((json) => {
data.value.version = json.version
data.value.bind_port = json.bind_port
data.value.bind_udp_port = json.bind_udp_port
if (data.value.bind_udp_port == '0') {
data.value.bind_udp_port = 'disable'
}
data.value.vhost_http_port = json.vhost_http_port
if (data.value.vhost_http_port == '0') {
data.value.vhost_http_port = 'disable'
}
data.value.vhost_https_port = json.vhost_https_port
if (data.value.vhost_https_port == '0') {
data.value.vhost_https_port = 'disable'
}
data.value.subdomain_host = json.subdomain_host
data.value.max_pool_count = json.max_pool_count
data.value.max_ports_per_client = json.max_ports_per_client
if (data.value.max_ports_per_client == '0') {
data.value.max_ports_per_client = 'no limit'
}
data.value.heart_beat_timeout = json.heart_beat_timeout
data.value.client_counts = json.client_counts
data.value.cur_conns = json.cur_conns
data.value.proxy_counts = 0
if (json.proxy_type_count != null) {
if (json.proxy_type_count.tcp != null) {
data.value.proxy_counts += json.proxy_type_count.tcp
}
if (json.proxy_type_count.udp != null) {
data.value.proxy_counts += json.proxy_type_count.udp
}
if (json.proxy_type_count.http != null) {
data.value.proxy_counts += json.proxy_type_count.http
}
if (json.proxy_type_count.https != null) {
data.value.proxy_counts += json.proxy_type_count.https
}
if (json.proxy_type_count.stcp != null) {
data.value.proxy_counts += json.proxy_type_count.stcp
}
if (json.proxy_type_count.sudp != null) {
data.value.proxy_counts += json.proxy_type_count.sudp
}
if (json.proxy_type_count.xtcp != null) {
data.value.proxy_counts += json.proxy_type_count.xtcp
}
}
// draw chart
DrawTrafficChart('traffic', json.total_traffic_in, json.total_traffic_out)
DrawProxyChart('proxies', json)
})
.catch(() => {
ElMessage({
showClose: true,
message: 'Get server info from frps failed!',
type: 'warning',
})
})
}
fetchData()
</script>
<style>
.source {
border: 1px solid #eaeefb;
border-radius: 4px;
transition: 0.2s;
padding: 24px;
}
.server_info {
margin-left: 40px;
font-size: 0px;
}
.server_info .el-form-item__label {
color: #99a9bf;
height: 40px;
line-height: 40px;
}
.server_info .el-form-item__content {
height: 40px;
line-height: 40px;
}
.server_info .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 100%;
}
</style>

View File

@@ -1,36 +1,32 @@
<template>
<div :id="proxy_name" style="width: 600px;height:400px;"></div>
<div :id="proxy_name" style="width: 600px; height: 400px"></div>
</template>
<script>
import {DrawProxyTrafficChart} from '../utils/chart.js'
export default {
props: ['proxy_name'],
created() {
this.fetchData()
},
//watch: {
//'$route': 'fetchData'
//},
methods: {
fetchData() {
let url = '../api/traffic/' + this.proxy_name
fetch(url, {credentials: 'include'})
.then(res => {
return res.json()
}).then(json => {
DrawProxyTrafficChart(this.proxy_name, json.traffic_in, json.traffic_out)
}).catch( err => {
this.$message({
showClose: true,
message: 'Get server info from frps failed!' + err,
type: 'warning'
})
})
}
}
}
</script>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { DrawProxyTrafficChart } from '../utils/chart.js'
<style>
</style>
const props = defineProps<{
proxy_name: string
}>()
const fetchData = () => {
let url = '../api/traffic/' + props.proxy_name
fetch(url, { credentials: 'include' })
.then((res) => {
return res.json()
})
.then((json) => {
DrawProxyTrafficChart(props.proxy_name, json.traffic_in, json.traffic_out)
})
.catch((err) => {
ElMessage({
showClose: true,
message: 'Get traffic info failed!' + err,
type: 'warning',
})
})
}
fetchData()
</script>
<style></style>

View File

@@ -1,15 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>frps dashboard</title>
</head>
<body>
<div id="app"></div>
<!--<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>-->
<!--<script src="//cdn.bootcss.com/echarts/3.4.0/echarts.min.js"></script>-->
</body>
</html>

View File

@@ -1,48 +0,0 @@
import Vue from 'vue'
//import ElementUI from 'element-ui'
import {
Button,
Form,
FormItem,
Row,
Col,
Table,
TableColumn,
Popover,
Menu,
Submenu,
MenuItem,
Tag
} from 'element-ui'
import lang from 'element-ui/lib/locale/lang/en'
import locale from 'element-ui/lib/locale'
import 'element-ui/lib/theme-chalk/index.css'
import './utils/less/custom.less'
import App from './App.vue'
import router from './router'
import 'whatwg-fetch'
locale.use(lang)
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Row)
Vue.use(Col)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Popover)
Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem)
Vue.use(Tag)
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})

12
web/frps/src/main.ts Normal file
View File

@@ -0,0 +1,12 @@
import { createApp } from 'vue'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import './assets/custom.css'
const app = createApp(App)
app.use(router)
app.mount('#app')

View File

@@ -1,43 +0,0 @@
import Vue from 'vue'
import Router from 'vue-router'
import Overview from '../components/Overview.vue'
import ProxiesTcp from '../components/ProxiesTcp.vue'
import ProxiesUdp from '../components/ProxiesUdp.vue'
import ProxiesHttp from '../components/ProxiesHttp.vue'
import ProxiesHttps from '../components/ProxiesHttps.vue'
import ProxiesStcp from '../components/ProxiesStcp.vue'
import ProxiesSudp from '../components/ProxiesSudp.vue'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'Overview',
component: Overview
}, {
path: '/proxies/tcp',
name: 'ProxiesTcp',
component: ProxiesTcp
}, {
path: '/proxies/udp',
name: 'ProxiesUdp',
component: ProxiesUdp
}, {
path: '/proxies/http',
name: 'ProxiesHttp',
component: ProxiesHttp
}, {
path: '/proxies/https',
name: 'ProxiesHttps',
component: ProxiesHttps
}, {
path: '/proxies/stcp',
name: 'ProxiesStcp',
component: ProxiesStcp
}, {
path: '/proxies/sudp',
name: 'ProxiesSudp',
component: ProxiesSudp
}]
})

View File

@@ -0,0 +1,51 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import ServerOverview from '../components/ServerOverview.vue'
import ProxiesTCP from '../components/ProxiesTCP.vue'
import ProxiesUDP from '../components/ProxiesUDP.vue'
import ProxiesHTTP from '../components/ProxiesHTTP.vue'
import ProxiesHTTPS from '../components/ProxiesHTTPS.vue'
import ProxiesSTCP from '../components/ProxiesSTCP.vue'
import ProxiesSUDP from '../components/ProxiesSUDP.vue'
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
name: 'ServerOverview',
component: ServerOverview,
},
{
path: '/proxies/tcp',
name: 'ProxiesTCP',
component: ProxiesTCP,
},
{
path: '/proxies/udp',
name: 'ProxiesUDP',
component: ProxiesUDP,
},
{
path: '/proxies/http',
name: 'ProxiesHTTP',
component: ProxiesHTTP,
},
{
path: '/proxies/https',
name: 'ProxiesHTTPS',
component: ProxiesHTTPS,
},
{
path: '/proxies/stcp',
name: 'ProxiesSTCP',
component: ProxiesSTCP,
},
{
path: '/proxies/sudp',
name: 'ProxiesSUDP',
component: ProxiesSUDP,
},
],
})
export default router

View File

@@ -1,186 +0,0 @@
import Humanize from "humanize-plus"
import echarts from "echarts/lib/echarts"
import "echarts/theme/macarons"
import "echarts/lib/chart/bar"
import "echarts/lib/chart/pie"
import "echarts/lib/component/tooltip"
import "echarts/lib/component/title"
function DrawTrafficChart(elementId, trafficIn, trafficOut) {
let myChart = echarts.init(document.getElementById(elementId), 'macarons');
myChart.showLoading()
let option = {
title: {
text: 'Network Traffic',
subtext: 'today',
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: function(v) {
return Humanize.fileSize(v.data.value) + " (" + v.percent + "%)"
}
},
series: [{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [{
value: trafficIn,
name: 'Traffic In'
}, {
value: trafficOut,
name: 'Traffic Out'
}, ],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
};
myChart.setOption(option);
myChart.hideLoading()
}
function DrawProxyChart(elementId, serverInfo) {
let myChart = echarts.init(document.getElementById(elementId), 'macarons')
myChart.showLoading()
let option = {
title: {
text: 'Proxies',
subtext: 'now',
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: function(v) {
return v.data.value
}
},
series: [{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
};
if (serverInfo.proxy_type_count.tcp != null && serverInfo.proxy_type_count.tcp != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.tcp, name: 'TCP'})
}
if (serverInfo.proxy_type_count.udp != null && serverInfo.proxy_type_count.udp != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.udp, name: 'UDP'})
}
if (serverInfo.proxy_type_count.http != null && serverInfo.proxy_type_count.http != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.http, name: 'HTTP'})
}
if (serverInfo.proxy_type_count.https != null && serverInfo.proxy_type_count.https != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.https, name: 'HTTPS'})
}
if (serverInfo.proxy_type_count.stcp != null && serverInfo.proxy_type_count.stcp != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.stcp, name: 'STCP'})
}
if (serverInfo.proxy_type_count.sudp != null && serverInfo.proxy_type_count.sudp != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.sudp, name: 'SUDP'})
}
if (serverInfo.proxy_type_count.xtcp != null && serverInfo.proxy_type_count.xtcp != 0) {
option.series[0].data.push({value: serverInfo.proxy_type_count.xtcp, name: 'XTCP'})
}
myChart.setOption(option);
myChart.hideLoading()
}
// 7 days
function DrawProxyTrafficChart(elementId, trafficInArr, trafficOutArr) {
let params = {
width: '600px',
height: '400px'
}
let myChart = echarts.init(document.getElementById(elementId), 'macarons', params);
myChart.showLoading()
trafficInArr = trafficInArr.reverse()
trafficOutArr = trafficOutArr.reverse()
let now = new Date()
now = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6)
let dates = new Array()
for (let i = 0; i < 7; i++) {
dates.push(now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate())
now = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1)
}
let option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function(data) {
let html = ''
if (data.length > 0) {
html += data[0].name + '<br/>'
}
for (let v of data) {
let colorEl = '<span style="display:inline-block;margin-right:5px;' +
'border-radius:10px;width:9px;height:9px;background-color:' + v.color + '"></span>';
html += colorEl + v.seriesName + ': ' + Humanize.fileSize(v.value) + '<br/>'
}
return html
}
},
legend: {
data: ['Traffic In', 'Traffic Out']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
data: dates
}],
yAxis: [{
type: 'value',
axisLabel: {
formatter: function(value) {
return Humanize.fileSize(value)
}
}
}],
series: [{
name: 'Traffic In',
type: 'bar',
data: trafficInArr
}, {
name: 'Traffic Out',
type: 'bar',
data: trafficOutArr
}]
};
myChart.setOption(option);
myChart.hideLoading()
}
export {
DrawTrafficChart,
DrawProxyChart,
DrawProxyTrafficChart
}

293
web/frps/src/utils/chart.ts Normal file
View File

@@ -0,0 +1,293 @@
import * as Humanize from 'humanize-plus'
import * as echarts from 'echarts/core'
import { PieChart, BarChart } from 'echarts/charts'
import { CanvasRenderer } from 'echarts/renderers'
import { LabelLayout } from 'echarts/features'
import {
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
} from 'echarts/components'
echarts.use([
PieChart,
BarChart,
CanvasRenderer,
LabelLayout,
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
])
function DrawTrafficChart(
elementId: string,
trafficIn: number,
trafficOut: number
) {
const myChart = echarts.init(
document.getElementById(elementId) as HTMLElement,
'macarons'
)
myChart.showLoading()
const option = {
title: {
text: 'Network Traffic',
subtext: 'today',
left: 'center',
},
tooltip: {
trigger: 'item',
formatter: function (v: any) {
return Humanize.fileSize(v.data.value) + ' (' + v.percent + '%)'
},
},
legend: {
orient: 'vertical',
left: 'left',
data: ['Traffic In', 'Traffic Out'],
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [
{
value: trafficIn,
name: 'Traffic In',
},
{
value: trafficOut,
name: 'Traffic Out',
},
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
}
myChart.setOption(option)
myChart.hideLoading()
}
function DrawProxyChart(elementId: string, serverInfo: any) {
const myChart = echarts.init(
document.getElementById(elementId) as HTMLElement,
'macarons'
)
myChart.showLoading()
const option = {
title: {
text: 'Proxies',
subtext: 'now',
left: 'center',
},
tooltip: {
trigger: 'item',
formatter: function (v: any) {
return String(v.data.value)
},
},
legend: {
orient: 'vertical',
left: 'left',
data: <string[]>[],
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: <any[]>[],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
}
if (
serverInfo.proxy_type_count.tcp != null &&
serverInfo.proxy_type_count.tcp != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.tcp,
name: 'TCP',
})
option.legend.data.push('TCP')
}
if (
serverInfo.proxy_type_count.udp != null &&
serverInfo.proxy_type_count.udp != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.udp,
name: 'UDP',
})
option.legend.data.push('UDP')
}
if (
serverInfo.proxy_type_count.http != null &&
serverInfo.proxy_type_count.http != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.http,
name: 'HTTP',
})
option.legend.data.push('HTTP')
}
if (
serverInfo.proxy_type_count.https != null &&
serverInfo.proxy_type_count.https != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.https,
name: 'HTTPS',
})
option.legend.data.push('HTTPS')
}
if (
serverInfo.proxy_type_count.stcp != null &&
serverInfo.proxy_type_count.stcp != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.stcp,
name: 'STCP',
})
option.legend.data.push('STCP')
}
if (
serverInfo.proxy_type_count.sudp != null &&
serverInfo.proxy_type_count.sudp != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.sudp,
name: 'SUDP',
})
option.legend.data.push('SUDP')
}
if (
serverInfo.proxy_type_count.xtcp != null &&
serverInfo.proxy_type_count.xtcp != 0
) {
option.series[0].data.push({
value: serverInfo.proxy_type_count.xtcp,
name: 'XTCP',
})
option.legend.data.push('XTCP')
}
myChart.setOption(option)
myChart.hideLoading()
}
// 7 days
function DrawProxyTrafficChart(
elementId: string,
trafficInArr: number[],
trafficOutArr: number[]
) {
const params = {
width: '600px',
height: '400px',
}
const myChart = echarts.init(
document.getElementById(elementId) as HTMLElement,
'macarons',
params
)
myChart.showLoading()
trafficInArr = trafficInArr.reverse()
trafficOutArr = trafficOutArr.reverse()
let now = new Date()
now = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6)
const dates: Array<string> = []
for (let i = 0; i < 7; i++) {
dates.push(
now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate()
)
now = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1)
}
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
formatter: function (data: any) {
let html = ''
if (data.length > 0) {
html += data[0].name + '<br/>'
}
for (const v of data) {
const colorEl =
'<span style="display:inline-block;margin-right:5px;' +
'border-radius:10px;width:9px;height:9px;background-color:' +
v.color +
'"></span>'
html +=
colorEl + v.seriesName + ': ' + Humanize.fileSize(v.value) + '<br/>'
}
return html
},
},
legend: {
data: ['Traffic In', 'Traffic Out'],
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: dates,
},
],
yAxis: [
{
type: 'value',
axisLabel: {
formatter: function (value: number) {
return Humanize.fileSize(value)
},
},
},
],
series: [
{
name: 'Traffic In',
type: 'bar',
data: trafficInArr,
},
{
name: 'Traffic Out',
type: 'bar',
data: trafficOutArr,
},
],
}
myChart.setOption(option)
myChart.hideLoading()
}
export { DrawTrafficChart, DrawProxyChart, DrawProxyTrafficChart }

View File

@@ -1,22 +0,0 @@
@color: red;
.el-form-item {
span {
margin-left: 15px;
}
}
.demo-table-expand {
font-size: 0;
label {
width: 90px;
color: #99a9bf;
}
.el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
}

View File

@@ -1,104 +0,0 @@
class BaseProxy {
constructor(proxyStats) {
this.name = proxyStats.name
if (proxyStats.conf != null) {
this.encryption = proxyStats.conf.use_encryption
this.compression = proxyStats.conf.use_compression
} else {
this.encryption = ""
this.compression = ""
}
this.conns = proxyStats.cur_conns
this.traffic_in = proxyStats.today_traffic_in
this.traffic_out = proxyStats.today_traffic_out
this.last_start_time = proxyStats.last_start_time
this.last_close_time = proxyStats.last_close_time
this.status = proxyStats.status
}
}
class TcpProxy extends BaseProxy {
constructor(proxyStats) {
super(proxyStats)
this.type = "tcp"
if (proxyStats.conf != null) {
this.addr = ":" + proxyStats.conf.remote_port
this.port = proxyStats.conf.remote_port
} else {
this.addr = ""
this.port = ""
}
}
}
class UdpProxy extends BaseProxy {
constructor(proxyStats) {
super(proxyStats)
this.type = "udp"
if (proxyStats.conf != null) {
this.addr = ":" + proxyStats.conf.remote_port
this.port = proxyStats.conf.remote_port
} else {
this.addr = ""
this.port = ""
}
}
}
class HttpProxy extends BaseProxy {
constructor(proxyStats, port, subdomain_host) {
super(proxyStats)
this.type = "http"
this.port = port
if (proxyStats.conf != null) {
this.custom_domains = proxyStats.conf.custom_domains
this.host_header_rewrite = proxyStats.conf.host_header_rewrite
this.locations = proxyStats.conf.locations
if (proxyStats.conf.subdomain != "") {
this.subdomain = proxyStats.conf.subdomain + "." + subdomain_host
} else {
this.subdomain = ""
}
} else {
this.custom_domains = ""
this.host_header_rewrite = ""
this.subdomain = ""
this.locations = ""
}
}
}
class HttpsProxy extends BaseProxy {
constructor(proxyStats, port, subdomain_host) {
super(proxyStats)
this.type = "https"
this.port = port
if (proxyStats.conf != null) {
this.custom_domains = proxyStats.conf.custom_domains
if (proxyStats.conf.subdomain != "") {
this.subdomain = proxyStats.conf.subdomain + "." + subdomain_host
} else {
this.subdomain = ""
}
} else {
this.custom_domains = ""
this.subdomain = ""
}
}
}
class StcpProxy extends BaseProxy {
constructor(proxyStats) {
super(proxyStats)
this.type = "stcp"
}
}
class SudpProxy extends BaseProxy {
constructor(proxyStats) {
super(proxyStats)
this.type = "sudp"
}
}
export {BaseProxy, TcpProxy, UdpProxy, HttpProxy, HttpsProxy, StcpProxy, SudpProxy}

138
web/frps/src/utils/proxy.ts Normal file
View File

@@ -0,0 +1,138 @@
class BaseProxy {
name: string
type: string
encryption: boolean
compression: boolean
conns: number
traffic_in: number
traffic_out: number
last_start_time: string
last_close_time: string
status: string
addr: string
port: number
custom_domains: string
host_header_rewrite: string
locations: string
subdomain: string
constructor(proxyStats: any) {
this.name = proxyStats.name
this.type = ''
if (proxyStats.conf != null) {
this.encryption = proxyStats.conf.use_encryption
this.compression = proxyStats.conf.use_compression
} else {
this.encryption = false
this.compression = false
}
this.conns = proxyStats.cur_conns
this.traffic_in = proxyStats.today_traffic_in
this.traffic_out = proxyStats.today_traffic_out
this.last_start_time = proxyStats.last_start_time
this.last_close_time = proxyStats.last_close_time
this.status = proxyStats.status
this.addr = ''
this.port = 0
this.custom_domains = ''
this.host_header_rewrite = ''
this.locations = ''
this.subdomain = ''
}
}
class TCPProxy extends BaseProxy {
constructor(proxyStats: any) {
super(proxyStats)
this.type = 'tcp'
if (proxyStats.conf != null) {
this.addr = ':' + proxyStats.conf.remote_port
this.port = proxyStats.conf.remote_port
} else {
this.addr = ''
this.port = 0
}
}
}
class UDPProxy extends BaseProxy {
constructor(proxyStats: any) {
super(proxyStats)
this.type = 'udp'
if (proxyStats.conf != null) {
this.addr = ':' + proxyStats.conf.remote_port
this.port = proxyStats.conf.remote_port
} else {
this.addr = ''
this.port = 0
}
}
}
class HTTPProxy extends BaseProxy {
constructor(proxyStats: any, port: number, subdomain_host: string) {
super(proxyStats)
this.type = 'http'
this.port = port
if (proxyStats.conf != null) {
this.custom_domains = proxyStats.conf.custom_domains
this.host_header_rewrite = proxyStats.conf.host_header_rewrite
this.locations = proxyStats.conf.locations
if (proxyStats.conf.subdomain != '') {
this.subdomain = proxyStats.conf.subdomain + '.' + subdomain_host
} else {
this.subdomain = ''
}
} else {
this.custom_domains = ''
this.host_header_rewrite = ''
this.subdomain = ''
this.locations = ''
}
}
}
class HTTPSProxy extends BaseProxy {
constructor(proxyStats: any, port: number, subdomain_host: string) {
super(proxyStats)
this.type = 'https'
this.port = port
if (proxyStats.conf != null) {
this.custom_domains = proxyStats.conf.custom_domains
if (proxyStats.conf.subdomain != '') {
this.subdomain = proxyStats.conf.subdomain + '.' + subdomain_host
} else {
this.subdomain = ''
}
} else {
this.custom_domains = ''
this.subdomain = ''
}
}
}
class STCPProxy extends BaseProxy {
constructor(proxyStats: any) {
super(proxyStats)
this.type = 'stcp'
}
}
class SUDPProxy extends BaseProxy {
constructor(proxyStats: any) {
super(proxyStats)
this.type = 'sudp'
}
}
export {
BaseProxy,
TCPProxy,
UDPProxy,
HTTPProxy,
HTTPSProxy,
STCPProxy,
SUDPProxy,
}