mirror of https://github.com/fatedier/frp
fatedier
2 years ago
committed by
GitHub
48 changed files with 4024 additions and 7408 deletions
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1,16 @@
|
||||
<!doctype html> <html lang=en> <head> <meta charset=utf-8> <title>frps dashboard</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?5d154ba4c6b342d8c0c3"></script><script type="text/javascript" src="vendor.js?ddbd1f69fb6e67be4b78"></script></body> </html> |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>frps dashboard</title> |
||||
<script type="module" crossorigin src="./index-cd02d3b4.js"></script> |
||||
<link rel="stylesheet" href="./index-4ce77078.css"> |
||||
</head> |
||||
|
||||
<body> |
||||
<div id="app"></div> |
||||
|
||||
</body> |
||||
|
||||
</html> |
||||
|
@ -1 +0,0 @@
|
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,u,c){for(var i,a,f,l=0,s=[];l<t.length;l++)a=t[l],o[a]&&s.push(o[a][0]),o[a]=0;for(i in u)Object.prototype.hasOwnProperty.call(u,i)&&(e[i]=u[i]);for(r&&r(t,u,c);s.length;)s.shift()();if(c)for(l=0;l<c.length;l++)f=n(n.s=c[l]);return f};var t={},o={1:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var u=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=u;var c=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+""+e+".js?"+{0:"ddbd1f69fb6e67be4b78"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,c.appendChild(i),u},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]); |
File diff suppressed because one or more lines are too long
@ -1,14 +0,0 @@
|
||||
{ |
||||
"presets": [ |
||||
["es2015", { "modules": false }] |
||||
], |
||||
"plugins": [ |
||||
[ |
||||
"component", |
||||
{ |
||||
"libraryName": "element-ui", |
||||
"styleLibraryName": "theme-chalk" |
||||
} |
||||
] |
||||
] |
||||
} |
@ -0,0 +1,30 @@
|
||||
/* eslint-env node */ |
||||
require('@rushstack/eslint-patch/modern-module-resolution') |
||||
|
||||
module.exports = { |
||||
root: true, |
||||
extends: [ |
||||
'plugin:vue/vue3-essential', |
||||
'eslint:recommended', |
||||
'@vue/eslint-config-typescript', |
||||
'@vue/eslint-config-prettier', |
||||
], |
||||
parserOptions: { |
||||
ecmaVersion: 'latest', |
||||
}, |
||||
rules: { |
||||
'@typescript-eslint/no-unused-vars': [ |
||||
'warn', |
||||
{ |
||||
argsIgnorePattern: '^_', |
||||
varsIgnorePattern: '^_', |
||||
}, |
||||
], |
||||
'vue/multi-word-component-names': [ |
||||
'error', |
||||
{ |
||||
ignores: ['Traffic'], |
||||
}, |
||||
], |
||||
}, |
||||
} |
@ -1,6 +1,28 @@
|
||||
# Logs |
||||
logs |
||||
*.log |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
pnpm-debug.log* |
||||
lerna-debug.log* |
||||
|
||||
node_modules |
||||
.DS_Store |
||||
node_modules/ |
||||
dist/ |
||||
npm-debug.log |
||||
dist |
||||
dist-ssr |
||||
coverage |
||||
*.local |
||||
|
||||
/cypress/videos/ |
||||
/cypress/screenshots/ |
||||
|
||||
# Editor directories and files |
||||
.vscode/* |
||||
!.vscode/extensions.json |
||||
.idea |
||||
.vscode/settings.json |
||||
*.suo |
||||
*.ntvs* |
||||
*.njsproj |
||||
*.sln |
||||
*.sw? |
||||
|
@ -0,0 +1,5 @@
|
||||
{ |
||||
"tabWidth": 2, |
||||
"semi": false, |
||||
"singleQuote": true |
||||
} |
@ -1,7 +1,13 @@
|
||||
.PHONY: dist build |
||||
.PHONY: dist build preview lint |
||||
|
||||
build: |
||||
@npm run build
|
||||
|
||||
dev: install |
||||
dev: |
||||
@npm run dev
|
||||
|
||||
preview: |
||||
@npm run preview
|
||||
|
||||
lint: |
||||
@npm run lint
|
||||
|
@ -0,0 +1,46 @@
|
||||
# frps-dashboard |
||||
|
||||
This template should help get you started developing with Vue 3 in Vite. |
||||
|
||||
## Recommended IDE Setup |
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). |
||||
|
||||
## Type Support for `.vue` Imports in TS |
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. |
||||
|
||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: |
||||
|
||||
1. Disable the built-in TypeScript Extension |
||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette |
||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` |
||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. |
||||
|
||||
## Customize configuration |
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/). |
||||
|
||||
## Project Setup |
||||
|
||||
```sh |
||||
npm install |
||||
``` |
||||
|
||||
### Compile and Hot-Reload for Development |
||||
|
||||
```sh |
||||
npm run dev |
||||
``` |
||||
|
||||
### Type-Check, Compile and Minify for Production |
||||
|
||||
```sh |
||||
npm run build |
||||
``` |
||||
|
||||
### Lint with [ESLint](https://eslint.org/) |
||||
|
||||
```sh |
||||
npm run lint |
||||
``` |
@ -0,0 +1,5 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {} |
||||
declare global { |
||||
|
||||
} |
@ -0,0 +1,35 @@
|
||||
// generated by unplugin-vue-components
|
||||
// We suggest you to commit this file into source control
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core' |
||||
|
||||
export {} |
||||
|
||||
declare module '@vue/runtime-core' { |
||||
export interface GlobalComponents { |
||||
ElButton: typeof import('element-plus/es')['ElButton'] |
||||
ElCol: typeof import('element-plus/es')['ElCol'] |
||||
ElForm: typeof import('element-plus/es')['ElForm'] |
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem'] |
||||
ElMenu: typeof import('element-plus/es')['ElMenu'] |
||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] |
||||
ElPopover: typeof import('element-plus/es')['ElPopover'] |
||||
ElRow: typeof import('element-plus/es')['ElRow'] |
||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] |
||||
ElTable: typeof import('element-plus/es')['ElTable'] |
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] |
||||
ElTag: typeof import('element-plus/es')['ElTag'] |
||||
ProxiesHTTP: typeof import('./src/components/ProxiesHTTP.vue')['default'] |
||||
ProxiesHTTPS: typeof import('./src/components/ProxiesHTTPS.vue')['default'] |
||||
ProxiesSTCP: typeof import('./src/components/ProxiesSTCP.vue')['default'] |
||||
ProxiesSUDP: typeof import('./src/components/ProxiesSUDP.vue')['default'] |
||||
ProxiesTCP: typeof import('./src/components/ProxiesTCP.vue')['default'] |
||||
ProxiesUDP: typeof import('./src/components/ProxiesUDP.vue')['default'] |
||||
ProxyView: typeof import('./src/components/ProxyView.vue')['default'] |
||||
ProxyViewExpand: typeof import('./src/components/ProxyViewExpand.vue')['default'] |
||||
RouterLink: typeof import('vue-router')['RouterLink'] |
||||
RouterView: typeof import('vue-router')['RouterView'] |
||||
ServerOverview: typeof import('./src/components/ServerOverview.vue')['default'] |
||||
Traffic: typeof import('./src/components/Traffic.vue')['default'] |
||||
} |
||||
} |
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>frps dashboard</title> |
||||
</head> |
||||
|
||||
<body> |
||||
<div id="app"></div> |
||||
<script type="module" src="/src/main.ts"></script> |
||||
</body> |
||||
|
||||
</html> |
@ -1,48 +1,38 @@
|
||||
{ |
||||
"name": "frps-dashboard", |
||||
"description": "A dashboard for frp server.", |
||||
"author": "fatedier", |
||||
"version": "0.0.1", |
||||
"private": true, |
||||
"scripts": { |
||||
"dev": "webpack-dev-server -d --inline --hot --env.dev", |
||||
"build": "rimraf dist && webpack -p --progress --hide-modules" |
||||
"dev": "vite", |
||||
"build": "run-p type-check build-only", |
||||
"preview": "vite preview", |
||||
"build-only": "vite build", |
||||
"type-check": "vue-tsc --noEmit", |
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" |
||||
}, |
||||
"dependencies": { |
||||
"bootstrap": "^3.3.7", |
||||
"echarts": "^3.5.0", |
||||
"element-ui": "^2.3.8", |
||||
"@types/humanize-plus": "^1.8.0", |
||||
"echarts": "^5.4.1", |
||||
"element-plus": "^2.2.28", |
||||
"humanize-plus": "^1.8.2", |
||||
"vue": "^2.5.16", |
||||
"vue-resource": "^1.2.1", |
||||
"vue-router": "^2.3.0", |
||||
"whatwg-fetch": "^2.0.3" |
||||
}, |
||||
"engines": { |
||||
"node": ">=6" |
||||
"vue": "^3.2.45", |
||||
"vue-router": "^4.1.6" |
||||
}, |
||||
"devDependencies": { |
||||
"autoprefixer": "^6.6.0", |
||||
"babel-core": "^6.21.0", |
||||
"babel-eslint": "^7.1.1", |
||||
"babel-loader": "^6.4.0", |
||||
"babel-plugin-component": "^1.1.1", |
||||
"babel-preset-es2015": "^6.13.2", |
||||
"css-loader": "^0.27.0", |
||||
"eslint": "^3.12.2", |
||||
"eslint-config-enough": "^0.2.2", |
||||
"eslint-loader": "^1.6.3", |
||||
"file-loader": "^0.10.1", |
||||
"html-loader": "^0.4.5", |
||||
"html-webpack-plugin": "^2.24.1", |
||||
"less": "^3.0.4", |
||||
"less-loader": "^4.1.0", |
||||
"postcss-loader": "^1.3.3", |
||||
"rimraf": "^2.5.4", |
||||
"style-loader": "^0.13.2", |
||||
"url-loader": "^1.0.1", |
||||
"vue-loader": "^15.0.10", |
||||
"vue-template-compiler": "^2.1.8", |
||||
"webpack": "^2.2.0-rc.4", |
||||
"webpack-dev-server": "^3.1.4" |
||||
"@rushstack/eslint-patch": "^1.1.4", |
||||
"@types/node": "^18.11.12", |
||||
"@vitejs/plugin-vue": "^4.0.0", |
||||
"@vue/eslint-config-prettier": "^7.0.0", |
||||
"@vue/eslint-config-typescript": "^11.0.0", |
||||
"@vue/tsconfig": "^0.1.3", |
||||
"eslint": "^8.22.0", |
||||
"eslint-plugin-vue": "^9.3.0", |
||||
"npm-run-all": "^4.1.5", |
||||
"prettier": "^2.7.1", |
||||
"typescript": "~4.7.4", |
||||
"unplugin-auto-import": "^0.13.0", |
||||
"unplugin-vue-components": "^0.23.0", |
||||
"vite": "^4.0.4", |
||||
"vue-tsc": "^1.0.12" |
||||
} |
||||
} |
||||
|
@ -1,5 +0,0 @@
|
||||
module.exports = { |
||||
plugins: [ |
||||
require('autoprefixer')() |
||||
] |
||||
} |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
@ -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> |
||||
|
@ -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; |
||||
} |
@ -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> |
@ -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: "" |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
<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 |
||||
} |
||||
}, |
||||
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> |
||||
|
@ -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: '' |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
<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 |
||||
} |
||||
}, |
||||
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> |
||||
|
@ -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(), |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
<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)) |
||||
} |
||||
}, |
||||
components: { |
||||
'my-traffic-chart': Traffic |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
fetchData() |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
||||
<style></style> |
||||
|
@ -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(), |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
<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)) |
||||
} |
||||
}, |
||||
components: { |
||||
'my-traffic-chart': Traffic |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
fetchData() |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
||||
<style></style> |
||||
|
@ -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(), |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
<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)) |
||||
} |
||||
}, |
||||
components: { |
||||
'my-traffic-chart': Traffic |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
fetchData() |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
||||
<style></style> |
||||
|
@ -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(), |
||||
} |
||||
}, |
||||
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)) |
||||
} |
||||
}) |
||||
<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)) |
||||
} |
||||
}, |
||||
components: { |
||||
'my-traffic-chart': Traffic |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
|
||||
fetchData() |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
||||
<style></style> |
||||
|
@ -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> |
@ -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> |
@ -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> |
@ -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 setup lang="ts"> |
||||
import { ElMessage } from 'element-plus' |
||||
import { DrawProxyTrafficChart } from '../utils/chart.js' |
||||
|
||||
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> |
||||
<style></style> |
||||
|
@ -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> |
@ -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 } |
||||
}) |
@ -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') |
@ -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 |
||||
}] |
||||
}) |
@ -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 |
@ -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 |
||||
} |
@ -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 } |
@ -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%; |
||||
} |
||||
} |
@ -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} |
@ -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, |
||||
} |
@ -0,0 +1,8 @@
|
||||
{ |
||||
"extends": "@vue/tsconfig/tsconfig.node.json", |
||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], |
||||
"compilerOptions": { |
||||
"composite": true, |
||||
"types": ["node"] |
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
{ |
||||
"extends": "@vue/tsconfig/tsconfig.web.json", |
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"], |
||||
"compilerOptions": { |
||||
"baseUrl": ".", |
||||
"paths": { |
||||
"@/*": ["./src/*"] |
||||
} |
||||
}, |
||||
|
||||
"references": [ |
||||
{ |
||||
"path": "./tsconfig.config.json" |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,29 @@
|
||||
import { fileURLToPath, URL } from 'node:url' |
||||
|
||||
import { defineConfig } from 'vite' |
||||
import vue from '@vitejs/plugin-vue' |
||||
import AutoImport from 'unplugin-auto-import/vite' |
||||
import Components from 'unplugin-vue-components/vite' |
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' |
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({ |
||||
base: '', |
||||
plugins: [ |
||||
vue(), |
||||
AutoImport({ |
||||
resolvers: [ElementPlusResolver()], |
||||
}), |
||||
Components({ |
||||
resolvers: [ElementPlusResolver()], |
||||
}), |
||||
], |
||||
resolve: { |
||||
alias: { |
||||
'@': fileURLToPath(new URL('./src', import.meta.url)), |
||||
}, |
||||
}, |
||||
build: { |
||||
assetsDir: '', |
||||
}, |
||||
}) |
@ -1,107 +0,0 @@
|
||||
const path = require('path') |
||||
var webpack = require('webpack') |
||||
var HtmlWebpackPlugin = require('html-webpack-plugin') |
||||
var VueLoaderPlugin = require('vue-loader/lib/plugin') |
||||
var url = require('url') |
||||
var publicPath = '' |
||||
|
||||
module.exports = (options = {}) => ({ |
||||
entry: { |
||||
vendor: './src/main' |
||||
}, |
||||
output: { |
||||
path: path.resolve(__dirname, 'dist'), |
||||
filename: options.dev ? '[name].js' : '[name].js?[chunkhash]', |
||||
chunkFilename: '[id].js?[chunkhash]', |
||||
publicPath: options.dev ? '/assets/' : publicPath |
||||
}, |
||||
resolve: { |
||||
extensions: ['.js', '.vue', '.json'], |
||||
alias: { |
||||
'vue$': 'vue/dist/vue.esm.js', |
||||
'@': path.resolve(__dirname, 'src'), |
||||
} |
||||
}, |
||||
module: { |
||||
rules: [{ |
||||
test: /\.vue$/, |
||||
loader: 'vue-loader' |
||||
}, { |
||||
test: /\.js$/, |
||||
use: ['babel-loader'], |
||||
exclude: /node_modules/ |
||||
}, { |
||||
test: /\.html$/, |
||||
use: [{ |
||||
loader: 'html-loader', |
||||
options: { |
||||
root: path.resolve(__dirname, 'src'), |
||||
attrs: ['img:src', 'link:href'] |
||||
} |
||||
}] |
||||
}, { |
||||
test: /\.less$/, |
||||
loader: 'style-loader!css-loader!postcss-loader!less-loader' |
||||
}, { |
||||
test: /\.css$/, |
||||
use: ['style-loader', 'css-loader', 'postcss-loader'] |
||||
}, { |
||||
test: /favicon\.png$/, |
||||
use: [{ |
||||
loader: 'file-loader', |
||||
options: { |
||||
name: '[name].[ext]?[hash]' |
||||
} |
||||
}] |
||||
}, { |
||||
test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/, |
||||
exclude: /favicon\.png$/, |
||||
use: [{ |
||||
loader: 'url-loader', |
||||
options: { |
||||
limit: 10000 |
||||
} |
||||
}] |
||||
}] |
||||
}, |
||||
plugins: [ |
||||
new webpack.optimize.CommonsChunkPlugin({ |
||||
names: ['vendor', 'manifest'] |
||||
}), |
||||
new HtmlWebpackPlugin({ |
||||
favicon: 'src/assets/favicon.ico', |
||||
template: 'src/index.html' |
||||
}), |
||||
new webpack.NormalModuleReplacementPlugin(/element-ui[\/\\]lib[\/\\]locale[\/\\]lang[\/\\]zh-CN/, 'element-ui/lib/locale/lang/en'), |
||||
new webpack.DefinePlugin({ |
||||
'process.env': { |
||||
NODE_ENV: '"production"' |
||||
} |
||||
}), |
||||
new webpack.optimize.UglifyJsPlugin({ |
||||
sourceMap: false, |
||||
comments: false, |
||||
compress: { |
||||
warnings: false |
||||
} |
||||
}), |
||||
new VueLoaderPlugin() |
||||
], |
||||
devServer: { |
||||
host: '127.0.0.1', |
||||
port: 8010, |
||||
proxy: { |
||||
'/api/': { |
||||
target: 'http://127.0.0.1:8080', |
||||
changeOrigin: true, |
||||
pathRewrite: { |
||||
'^/api': '' |
||||
} |
||||
} |
||||
}, |
||||
historyApiFallback: { |
||||
index: url.parse(options.dev ? '/assets/' : publicPath).pathname |
||||
} |
||||
}//,
|
||||
//devtool: options.dev ? '#eval-source-map' : '#source-map'
|
||||
}) |
Loading…
Reference in new issue