mirror of https://github.com/fatedier/frp
web/frpc: upgrade vue and element-plus (#3322)
parent
24f0b3afa5
commit
fe8374e99b
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>frp client admin UI</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?5d5774096cf5c1b4d5af"></script><script type="text/javascript" src="vendor.js?dc42700731a508d39009"></script></body> </html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>frp client admin UI</title>
|
||||
<script type="module" crossorigin src="./index-fec891f3.js"></script>
|
||||
<link rel="stylesheet" href="./index-26827c97.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,c,u){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 c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=n(n.s=u[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 c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var u=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:"dc42700731a508d39009"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,u.appendChild(i),c},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: ["Overview"],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
|
@ -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 @@
|
|||
{}
|
|
@ -1,6 +1,13 @@
|
|||
.PHONY: dist build
|
||||
.PHONY: dist build preview lint
|
||||
|
||||
build:
|
||||
@npm run build
|
||||
|
||||
dev:
|
||||
@npm run dev
|
||||
|
||||
preview:
|
||||
@npm run preview
|
||||
|
||||
lint:
|
||||
@npm run lint
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# frpc-dashboard
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
make dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
make lint
|
||||
```
|
|
@ -0,0 +1,8 @@
|
|||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
ClientConfigure: typeof import('./src/components/ClientConfigure.vue')['default']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
Overview: typeof import('./src/components/Overview.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
<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>-->
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,46 +1,35 @@
|
|||
{
|
||||
"name": "frpc-web",
|
||||
"description": "An admin web ui for frp client.",
|
||||
"author": "fatedier",
|
||||
"name": "-frpc-dashboard",
|
||||
"version": "0.0.0",
|
||||
"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": {
|
||||
"element-ui": "^2.5.3",
|
||||
"vue": "^2.5.22",
|
||||
"vue-resource": "^1.5.1",
|
||||
"vue-router": "^3.0.2",
|
||||
"whatwg-fetch": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"element-plus": "^2.2.28",
|
||||
"vue": "^3.2.45",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^9.4.7",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"css-loader": "^2.1.0",
|
||||
"eslint": "^5.12.1",
|
||||
"eslint-config-enough": "^0.3.4",
|
||||
"eslint-loader": "^2.1.1",
|
||||
"file-loader": "^3.0.1",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^2.24.1",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^4.1.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue-loader": "^15.6.2",
|
||||
"vue-template-compiler": "^2.5.22",
|
||||
"webpack": "^2.7.0",
|
||||
"webpack-cli": "^3.2.1",
|
||||
"webpack-dev-server": "^3.1.14"
|
||||
"@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.14.3",
|
||||
"unplugin-vue-components": "^0.24.0",
|
||||
"vite": "^4.0.0",
|
||||
"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 |
|
@ -8,7 +8,13 @@
|
|||
<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
|
||||
default-active="1"
|
||||
mode="vertical"
|
||||
theme="light"
|
||||
router="false"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item index="/">Overview</el-menu-item>
|
||||
<el-menu-item index="/configure">Configure</el-menu-item>
|
||||
<el-menu-item index="">Help</el-menu-item>
|
||||
|
@ -23,43 +29,39 @@
|
|||
</el-row>
|
||||
</section>
|
||||
<footer></footer>
|
||||
</div>
|
||||
</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 {
|
||||
body {
|
||||
background-color: #fafafa;
|
||||
margin: 0px;
|
||||
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,sans-serif;
|
||||
}
|
||||
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
header {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-color {
|
||||
background: #58B7FF;
|
||||
}
|
||||
.header-color {
|
||||
background: #58b7ff;
|
||||
}
|
||||
|
||||
#content {
|
||||
#content {
|
||||
margin-top: 20px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.brand {
|
||||
.brand {
|
||||
color: #fff;
|
||||
background-color: transparent;
|
||||
margin-left: 20px;
|
||||
|
@ -69,5 +71,5 @@
|
|||
padding: 15px 15px;
|
||||
height: 30px;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row id="head">
|
||||
<el-button type="primary" @click="fetchData">Refresh</el-button>
|
||||
<el-button type="primary" @click="uploadConfig">Upload</el-button>
|
||||
</el-row>
|
||||
<el-input
|
||||
type="textarea"
|
||||
autosize
|
||||
v-model="textarea"
|
||||
placeholder="frpc configrue file, can not be empty..."
|
||||
></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
let textarea = ref("");
|
||||
|
||||
const fetchData = () => {
|
||||
fetch("/api/config", { credentials: "include" })
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((text) => {
|
||||
textarea.value = text;
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: "Get configure content from frpc failed!",
|
||||
type: "warning",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const uploadConfig = () => {
|
||||
ElMessageBox.confirm(
|
||||
"This operation will upload your frpc configure file content and hot reload it, do you want to continue?",
|
||||
"Notice",
|
||||
{
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No",
|
||||
type: "warning",
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
if (textarea.value == "") {
|
||||
ElMessage({
|
||||
message: "Configure content can not be empty!",
|
||||
type: "warning",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("/api/config", {
|
||||
credentials: "include",
|
||||
method: "PUT",
|
||||
body: textarea.value,
|
||||
})
|
||||
.then(() => {
|
||||
fetch("/api/reload", { credentials: "include" })
|
||||
.then(() => {
|
||||
ElMessage({
|
||||
type: "success",
|
||||
message: "Success",
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: "Reload frpc configure file error, " + err,
|
||||
type: "warning",
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: "Put config to frpc and hot reload failed!",
|
||||
type: "warning",
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
message: "Canceled",
|
||||
type: "info",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
fetchData();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#head {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
|
@ -1,93 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row id="head">
|
||||
<el-button type="primary" @click="fetchData">Refresh</el-button>
|
||||
<el-button type="primary" @click="uploadConfig">Upload</el-button>
|
||||
</el-row>
|
||||
<el-input type="textarea" autosize v-model="textarea" placeholder="frpc configrue file, can not be empty..."></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
textarea: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
watch: {
|
||||
'$route': 'fetchData'
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
fetch('/api/config', {credentials: 'include'})
|
||||
.then(res => {
|
||||
return res.text()
|
||||
}).then(text => {
|
||||
this.textarea= text
|
||||
}).catch( err => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: 'Get configure content from frpc failed!',
|
||||
type: 'warning'
|
||||
})
|
||||
})
|
||||
},
|
||||
uploadConfig() {
|
||||
this.$confirm('This operation will upload your frpc configure file content and hot reload it, do you want to continue?', 'Notice', {
|
||||
confirmButtonText: 'Yes',
|
||||
cancelButtonText: 'No',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
if (this.textarea == "") {
|
||||
this.$message({
|
||||
type: 'warning',
|
||||
message: 'Configure content can not be empty!'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
fetch('/api/config', {
|
||||
credentials: 'include',
|
||||
method: 'PUT',
|
||||
body: this.textarea,
|
||||
}).then(() => {
|
||||
fetch('/api/reload', {credentials: 'include'})
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: 'Success'
|
||||
})
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: 'Reload frpc configure file error, ' + err,
|
||||
type: 'warning'
|
||||
})
|
||||
})
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: 'Put config to frpc and hot reload failed!',
|
||||
type: 'warning'
|
||||
})
|
||||
})
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: 'Canceled'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#head {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
|
@ -3,13 +3,37 @@
|
|||
<el-row>
|
||||
<el-col :md="24">
|
||||
<div>
|
||||
<el-table :data="status" stripe style="width: 100%" :default-sort="{prop: 'type', order: 'ascending'}">
|
||||
<el-table
|
||||
:data="status"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
:default-sort="{ prop: 'type', order: 'ascending' }"
|
||||
>
|
||||
<el-table-column prop="name" label="name"></el-table-column>
|
||||
<el-table-column prop="type" label="type" width="150"></el-table-column>
|
||||
<el-table-column prop="local_addr" label="local address" width="200"></el-table-column>
|
||||
<el-table-column prop="plugin" label="plugin" width="200"></el-table-column>
|
||||
<el-table-column prop="remote_addr" label="remote address"></el-table-column>
|
||||
<el-table-column prop="status" label="status" width="150"></el-table-column>
|
||||
<el-table-column
|
||||
prop="type"
|
||||
label="type"
|
||||
width="150"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="local_addr"
|
||||
label="local address"
|
||||
width="200"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="plugin"
|
||||
label="plugin"
|
||||
width="200"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="remote_addr"
|
||||
label="remote address"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="status"
|
||||
width="150"
|
||||
></el-table-column>
|
||||
<el-table-column prop="err" label="info"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
@ -18,58 +42,50 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
status: new Array(),
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
watch: {
|
||||
'$route': 'fetchData'
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
fetch('/api/status', {credentials: 'include'})
|
||||
.then(res => {
|
||||
return res.json()
|
||||
}).then(json => {
|
||||
this.status = new Array()
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
let status = ref<any[]>([]);
|
||||
|
||||
const fetchData = () => {
|
||||
fetch("/api/status", { credentials: "include" })
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
.then((json) => {
|
||||
status.value = new Array();
|
||||
for (let s of json.tcp) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.udp) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.http) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.https) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.stcp) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.sudp) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
for (let s of json.xtcp) {
|
||||
this.status.push(s)
|
||||
status.value.push(s);
|
||||
}
|
||||
}).catch( err => {
|
||||
this.$message({
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: 'Get status info from frpc failed!',
|
||||
type: 'warning'
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
message: "Get status info from frpc failed!",
|
||||
type: "warning",
|
||||
});
|
||||
});
|
||||
};
|
||||
fetchData();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style></style>
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
// import ElementUI from 'element-ui'
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
FormItem,
|
||||
Row,
|
||||
Col,
|
||||
Table,
|
||||
TableColumn,
|
||||
Menu,
|
||||
MenuItem,
|
||||
MessageBox,
|
||||
Message,
|
||||
Input
|
||||
} 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(Menu)
|
||||
Vue.use(MenuItem)
|
||||
Vue.use(Input)
|
||||
|
||||
Vue.prototype.$msgbox = MessageBox;
|
||||
Vue.prototype.$confirm = MessageBox.confirm
|
||||
Vue.prototype.$message = Message
|
||||
|
||||
//Vue.use(ElementUI)
|
||||
|
||||
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,18 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Overview from '../components/Overview.vue'
|
||||
import Configure from '../components/Configure.vue'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [{
|
||||
path: '/',
|
||||
name: 'Overview',
|
||||
component: Overview
|
||||
},{
|
||||
path: '/configure',
|
||||
name: 'Configure',
|
||||
component: Configure,
|
||||
}]
|
||||
})
|
|
@ -0,0 +1,21 @@
|
|||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import Overview from "../components/Overview.vue";
|
||||
import ClientConfigure from "../components/ClientConfigure.vue";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: "/",
|
||||
name: "Overview",
|
||||
component: Overview,
|
||||
},
|
||||
{
|
||||
path: "/configure",
|
||||
name: "ClientConfigure",
|
||||
component: ClientConfigure,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export default router;
|
|
@ -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,13 +0,0 @@
|
|||
class ProxyStatus {
|
||||
constructor(status) {
|
||||
this.name = status.name
|
||||
this.type = status.type
|
||||
this.status = status.status
|
||||
this.err = status.err
|
||||
this.local_addr = status.local_addr
|
||||
this.plugin = status.plugin
|
||||
this.remote_addr = status.remote_addr
|
||||
}
|
||||
}
|
||||
|
||||
export {ProxyStatus}
|
|
@ -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'
|
||||
})
|
7633
web/frpc/yarn.lock
7633
web/frpc/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -1,46 +1,25 @@
|
|||
# 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
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
make dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
make build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
make lint
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue