Compare commits

...

6 Commits

Author SHA1 Message Date
nkdns
905e862d0e
Merge 3208c975bb9f7d55e96c326e3f910aafa26b61c2 into c73096f2bf6e8b0341bc0cc2c45d8d54f5946ff3 2024-12-12 15:03:54 +08:00
Roy Reznik
c73096f2bf
Upgrade packages to resolve CVE-2024-53259 (#4577) 2024-12-10 20:07:38 +08:00
nkdns
3208c975bb
图表修改异常,暂时挂起 2024-11-29 17:10:46 +08:00
nkdns
c9e5b60aa0
vue编译后文件变更 2024-11-29 16:46:03 +08:00
nkdns
aadb2a8953
frps多语言设计完成 2024-11-29 16:44:30 +08:00
nkdns
ff0676a3b1
frpc多语言设计完成 2024-11-29 16:36:59 +08:00
33 changed files with 722 additions and 420 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>frp client admin UI</title>
<script type="module" crossorigin src="./index-bLBhaJo8.js"></script>
<link rel="stylesheet" crossorigin href="./index-iuf46MlF.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>frp client admin UI</title>
<script type="module" crossorigin src="./index-Cgx39LXC.js"></script>
<link rel="stylesheet" crossorigin href="./index-N4E3zN8T.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,15 +1,15 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8">
<title>frps dashboard</title>
<script type="module" crossorigin src="./index-82-40HIG.js"></script>
<link rel="stylesheet" crossorigin href="./index-rzPDshRD.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8">
<title>frps dashboard</title>
<script type="module" crossorigin src="./index-yOnBcT7d.js"></script>
<link rel="stylesheet" crossorigin href="./index-5A9aPAsI.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

36
go.mod
View File

@ -1,6 +1,6 @@
module github.com/fatedier/frp
go 1.22
go 1.22.0
require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
@ -10,13 +10,13 @@ require (
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.0
github.com/hashicorp/yamux v0.1.1
github.com/onsi/ginkgo/v2 v2.17.1
github.com/onsi/gomega v1.32.0
github.com/onsi/ginkgo/v2 v2.22.0
github.com/onsi/gomega v1.34.2
github.com/pelletier/go-toml/v2 v2.2.0
github.com/pion/stun/v2 v2.0.0
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.19.0
github.com/quic-go/quic-go v0.42.0
github.com/prometheus/client_golang v1.19.1
github.com/quic-go/quic-go v0.48.2
github.com/rodaine/table v1.2.0
github.com/samber/lo v1.47.0
github.com/spf13/cobra v1.8.0
@ -24,10 +24,10 @@ require (
github.com/stretchr/testify v1.9.0
github.com/tidwall/gjson v1.17.1
github.com/xtaci/kcp-go/v5 v5.6.13
golang.org/x/crypto v0.23.0
golang.org/x/net v0.25.0
golang.org/x/crypto v0.30.0
golang.org/x/net v0.32.0
golang.org/x/oauth2 v0.16.0
golang.org/x/sync v0.7.0
golang.org/x/sync v0.10.0
golang.org/x/time v0.5.0
gopkg.in/ini.v1 v1.67.0
k8s.io/apimachinery v0.28.8
@ -40,12 +40,12 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/pprof v0.0.0-20241206021119-61a79c692802 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/klauspost/reedsolomon v1.12.0 // indirect
@ -64,14 +64,14 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect

78
go.sum
View File

@ -9,9 +9,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
@ -30,10 +27,10 @@ github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d h1:ynk1ra0RUqDWQfvF
github.com/fatedier/yamux v0.0.0-20230628132301-7aca4898904d/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -58,15 +55,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20241206021119-61a79c692802 h1:US08AXzP0bLurpzFUV3Poa9ZijrRdd1zAIOVtoHEiS8=
github.com/google/pprof v0.0.0-20241206021119-61a79c692802/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
@ -79,10 +75,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8=
@ -101,8 +97,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
@ -110,8 +106,8 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rodaine/table v1.2.0 h1:38HEnwK4mKSHQJIkavVj+bst1TEY7j9zhLMWu4QJrMA=
@ -129,7 +125,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@ -153,26 +148,26 @@ github.com/xtaci/kcp-go/v5 v5.6.13/go.mod h1:75S1AKYYzNUSXIv30h+jPKJYZUwqpfvLshu
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d h1:0olWaB5pg3+oychR51GUVCEsGkeCU/2JxjBgIo4f3M0=
golang.org/x/exp v0.0.0-20241204233417-43b7b7cde48d/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -186,8 +181,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
@ -196,12 +191,11 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -211,16 +205,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@ -228,8 +222,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -240,8 +234,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@ -262,8 +256,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@ -10,6 +10,9 @@ declare module 'vue' {
ClientConfigure: typeof import('./src/components/ClientConfigure.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCol: typeof import('element-plus/es')['ElCol']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElInput: typeof import('element-plus/es')['ElInput']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']

View File

@ -13,6 +13,7 @@
"dependencies": {
"element-plus": "^2.5.3",
"vue": "^3.4.15",
"vue-i18n": "^10.0.5",
"vue-router": "^4.2.5"
},
"devDependencies": {

View File

@ -3,36 +3,39 @@
<header class="grid-content header-color">
<div class="header-content">
<div class="brand">
<a href="#">frp client</a>
<a href="#">{{ t("main.title") }}</a>
</div>
<div class="dark-switch">
<el-switch
v-model="darkmodeSwitch"
inline-prompt
active-text="Dark"
inactive-text="Light"
@change="toggleDark"
style="
<div class="right-ability">
<div class="lang-switch">
<el-dropdown>
<img src="./assets/lang.svg" alt="lang">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :disabled="locale == 'en' ? true : false"
@click="switchLanguage('en')">English</el-dropdown-item>
<el-dropdown-item :disabled="locale == 'zh' ? true : false"
@click="switchLanguage('zh')">简体中文</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="dark-switch">
<el-switch v-model="darkmodeSwitch" inline-prompt :active-text="t('main.dark.Dark')"
:inactive-text="t('main.dark.Light')" @change="toggleDark" style="
--el-switch-on-color: #444452;
--el-switch-off-color: #589ef8;
"
/>
" />
</div>
</div>
</div>
</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-menu-item index="/configure">Configure</el-menu-item>
<el-menu-item index="">Help</el-menu-item>
<el-menu default-active="1" mode="vertical" theme="light" router="false" @select="handleSelect">
<el-menu-item index="/">{{ t("main.Overview") }}</el-menu-item>
<el-menu-item index="/configure">{{ t("main.Configure") }}</el-menu-item>
<el-menu-item index="">{{ t("main.Help") }}</el-menu-item>
</el-menu>
</el-col>
@ -50,11 +53,16 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useDark, useToggle } from '@vueuse/core'
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
const isDark = useDark()
const darkmodeSwitch = ref(isDark)
const toggleDark = useToggle(isDark)
const switchLanguage = (lang: string) => {
locale.value = lang;
localStorage.setItem('i18n', lang);
}
const handleSelect = (key: string) => {
if (key == '') {
window.open('https://github.com/fatedier/frp')
@ -107,10 +115,20 @@ html.dark .header-color {
text-decoration: none;
}
.dark-switch {
.right-ability {
display: flex;
justify-content: flex-end;
flex-grow: 1;
padding-right: 40px;
}
.lang-switch {
width: 30px;
margin-right: 10px;
}
.lang-switch img {
width: 100%;
height: auto;
}
</style>

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1732765556989" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1552" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M864 64a96 96 0 0 1 96 96v704a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V160a96 96 0 0 1 96-96h704z m0 64H160a32 32 0 0 0-32 32v704a32 32 0 0 0 32 32h704a32 32 0 0 0 32-32V160a32 32 0 0 0-32-32z m-322.4 256c0-31.456 40.64-44.032 58.4-18.08l133.6 195.168V384a32 32 0 0 1 64 0v280.48c0 31.456-40.64 44.032-58.4 18.08l-133.6-195.168v177.088a32 32 0 1 1-64 0z" fill="#ffffff" p-id="1553"></path><path d="M448 352a32 32 0 0 1 0 64H288v80h160a32 32 0 0 1 31.776 28.256L480 528a32 32 0 0 1-32 32H288v72.48h160a32 32 0 1 1 0 64H256a32 32 0 0 1-32-32V384a32 32 0 0 1 32-32z" fill="#ffffff" p-id="1554"></path></svg>

After

Width:  |  Height:  |  Size: 936 B

View File

@ -0,0 +1,25 @@
{
"main": {
"title": "frp client",
"Overview": "Overview",
"Configure": "Configure",
"Help": "Help",
"dark": {
"Dark": "Dark",
"Light": "Light"
}
},
"OverView": {
"name": "name",
"type": "type",
"local_addr": "local address",
"plugin": "plugin",
"remote_addr": "remote address",
"status": "status",
"err": "info"
},
"Configure": {
"Refresh": "Refresh",
"Upload": "Upload"
}
}

View File

@ -0,0 +1,25 @@
{
"main": {
"title": "frp 客户端",
"Overview": "总览",
"Configure": "配置",
"Help": "帮助",
"dark": {
"Dark": "暗",
"Light": "明"
}
},
"OverView": {
"name": "通道名称",
"type": "协议类型",
"local_addr": "本地地址",
"plugin": "插件",
"remote_addr": "远程地址",
"status": "状态",
"err": "信息"
},
"Configure": {
"Refresh": "读取配置",
"Upload": "保存配置"
}
}

View File

@ -1,21 +1,19 @@
<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-button type="primary" @click="fetchData">{{ t("Configure.Refresh") }}</el-button>
<el-button type="primary" @click="uploadConfig">{{ t("Configure.Upload") }}</el-button>
</el-row>
<el-input
type="textarea"
autosize
v-model="textarea"
placeholder="frpc configrue file, can not be empty..."
></el-input>
<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'
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
let textarea = ref('')

View File

@ -3,47 +3,14 @@
<el-row>
<el-col :md="24">
<div>
<el-table
:data="status"
stripe
style="width: 100%"
:default-sort="{ prop: 'type', order: 'ascending' }"
>
<el-table-column
prop="name"
label="name"
sortable
></el-table-column>
<el-table-column
prop="type"
label="type"
width="150"
sortable
></el-table-column>
<el-table-column
prop="local_addr"
label="local address"
width="200"
sortable
></el-table-column>
<el-table-column
prop="plugin"
label="plugin"
width="200"
sortable
></el-table-column>
<el-table-column
prop="remote_addr"
label="remote address"
sortable
></el-table-column>
<el-table-column
prop="status"
label="status"
width="150"
sortable
></el-table-column>
<el-table-column prop="err" label="info"></el-table-column>
<el-table :data="status" stripe style="width: 100%" :default-sort="{ prop: 'type', order: 'ascending' }">
<el-table-column prop="name" :label="t('OverView.name')" sortable></el-table-column>
<el-table-column prop="type" :label="t('OverView.type')" width="150" sortable></el-table-column>
<el-table-column prop="local_addr" :label="t('OverView.local_addr')" width="200" sortable></el-table-column>
<el-table-column prop="plugin" :label="t('OverView.plugin')" width="200" sortable></el-table-column>
<el-table-column prop="remote_addr" :label="t('OverView.remote_addr')" sortable></el-table-column>
<el-table-column prop="status" :label="t('OverView.status')" width="150" sortable></el-table-column>
<el-table-column prop="err" :label="t('OverView.err')"></el-table-column>
</el-table>
</div>
</el-col>
@ -54,6 +21,8 @@
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
let status = ref<any[]>([])

View File

@ -1,13 +1,24 @@
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n';
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import App from './App.vue'
import router from './router'
import './assets/dark.css'
import en from './assets/locales/en.json';
import zh from './assets/locales/zh.json';
const storedLocale = localStorage.getItem('i18n') || 'en';
const i18n = createI18n({
locale: storedLocale, // 默认语言
messages: {
en,
zh,
},
});
const app = createApp(App)
app.use(router)
app.use(i18n);
app.mount('#app')

View File

@ -205,6 +205,27 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917"
integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==
"@intlify/core-base@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/core-base/-/core-base-10.0.5.tgz#c4d992381f8c3a50c79faf67be3404b399c3be28"
integrity sha512-F3snDTQs0MdvnnyzTDTVkOYVAZOE/MHwRvF7mn7Jw1yuih4NrFYLNYIymGlLmq4HU2iIdzYsZ7f47bOcwY73XQ==
dependencies:
"@intlify/message-compiler" "10.0.5"
"@intlify/shared" "10.0.5"
"@intlify/message-compiler@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-10.0.5.tgz#4eeace9f4560020d5e5d77f32bed7755e71d8efd"
integrity sha512-6GT1BJ852gZ0gItNZN2krX5QAmea+cmdjMvsWohArAZ3GmHdnNANEcF9JjPXAMRtQ6Ux5E269ymamg/+WU6tQA==
dependencies:
"@intlify/shared" "10.0.5"
source-map-js "^1.0.2"
"@intlify/shared@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-10.0.5.tgz#1b46ca8b541f03508fe28da8f34e4bb85506d6bc"
integrity sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==
"@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
@ -2500,6 +2521,15 @@ vue-eslint-parser@^9.3.1, vue-eslint-parser@^9.4.2:
lodash "^4.17.21"
semver "^7.3.6"
vue-i18n@^10.0.5:
version "10.0.5"
resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-10.0.5.tgz#fdf4e6c7b669e80cfa3a12ed9625e2b46671cdf0"
integrity sha512-9/gmDlCblz3i8ypu/afiIc/SUIfTTE1mr0mZhb9pk70xo2csHAM9mp2gdQ3KD2O0AM3Hz/5ypb+FycTj/lHlPQ==
dependencies:
"@intlify/core-base" "10.0.5"
"@intlify/shared" "10.0.5"
"@vue/devtools-api" "^6.5.0"
vue-router@^4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.2.5.tgz#b9e3e08f1bd9ea363fdd173032620bc50cf0e98a"

View File

@ -11,6 +11,9 @@ declare module 'vue' {
ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElMenu: typeof import('element-plus/es')['ElMenu']

View File

@ -16,6 +16,7 @@
"element-plus": "^2.5.3",
"humanize-plus": "^1.8.2",
"vue": "^3.4.15",
"vue-i18n": "^10.0.5",
"vue-router": "^4.2.5"
},
"devDependencies": {

View File

@ -3,37 +3,40 @@
<header class="grid-content header-color">
<div class="header-content">
<div class="brand">
<a href="#">frp</a>
<a href="#">{{ t("main.title") }}</a>
</div>
<div class="dark-switch">
<el-switch
v-model="darkmodeSwitch"
inline-prompt
active-text="Dark"
inactive-text="Light"
@change="toggleDark"
style="
<div class="right-ability">
<div class="lang-switch">
<el-dropdown>
<img src="./assets/lang.svg" alt="lang">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :disabled="locale == 'en' ? true : false"
@click="switchLanguage('en')">English</el-dropdown-item>
<el-dropdown-item :disabled="locale == 'zh' ? true : false"
@click="switchLanguage('zh')">简体中文</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="dark-switch">
<el-switch v-model="darkmodeSwitch" inline-prompt :active-text="t('main.dark.Dark')"
:inactive-text="t('main.dark.Light')" @change="toggleDark" style="
--el-switch-on-color: #444452;
--el-switch-off-color: #589ef8;
"
/>
" />
</div>
</div>
</div>
</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-menu default-active="/" mode="vertical" theme="light" router="false" @select="handleSelect">
<el-menu-item index="/">{{ t("main.Overview") }}</el-menu-item>
<el-sub-menu index="/proxies">
<template #title>
<span>Proxies</span>
<span>{{ t("main.Proxies.title") }}</span>
</template>
<el-menu-item index="/proxies/tcp">TCP</el-menu-item>
<el-menu-item index="/proxies/udp">UDP</el-menu-item>
@ -43,7 +46,7 @@
<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-item index="">{{ t("main.Help") }}</el-menu-item>
</el-menu>
</el-col>
@ -61,11 +64,16 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useDark, useToggle } from '@vueuse/core'
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
const isDark = useDark()
const darkmodeSwitch = ref(isDark)
const toggleDark = useToggle(isDark)
const switchLanguage = (lang: string) => {
locale.value = lang;
localStorage.setItem('i18n', lang);
}
const handleSelect = (key: string) => {
if (key == '') {
window.open('https://github.com/fatedier/frp')
@ -118,10 +126,20 @@ html.dark .header-color {
text-decoration: none;
}
.dark-switch {
.right-ability {
display: flex;
justify-content: flex-end;
flex-grow: 1;
padding-right: 40px;
}
.lang-switch {
width: 30px;
margin-right: 10px;
}
.lang-switch img {
width: 100%;
height: auto;
}
</style>

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1732765556989" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1552" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M864 64a96 96 0 0 1 96 96v704a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V160a96 96 0 0 1 96-96h704z m0 64H160a32 32 0 0 0-32 32v704a32 32 0 0 0 32 32h704a32 32 0 0 0 32-32V160a32 32 0 0 0-32-32z m-322.4 256c0-31.456 40.64-44.032 58.4-18.08l133.6 195.168V384a32 32 0 0 1 64 0v280.48c0 31.456-40.64 44.032-58.4 18.08l-133.6-195.168v177.088a32 32 0 1 1-64 0z" fill="#ffffff" p-id="1553"></path><path d="M448 352a32 32 0 0 1 0 64H288v80h160a32 32 0 0 1 31.776 28.256L480 528a32 32 0 0 1-32 32H288v72.48h160a32 32 0 1 1 0 64H256a32 32 0 0 1-32-32V384a32 32 0 0 1 32-32z" fill="#ffffff" p-id="1554"></path></svg>

After

Width:  |  Height:  |  Size: 936 B

View File

@ -0,0 +1,79 @@
{
"main": {
"title": "frp",
"Overview": "Overview",
"Proxies": {
"title": "Proxies"
},
"Help": "Help",
"dark": {
"Dark": "Dark",
"Light": "Light"
}
},
"OverView": {
"Version": "Version",
"BindPort": "BindPort",
"KPC_Port": "KCP Bind Port",
"QUIC_Port": "QUIC Bind Port",
"HTTP_Port": "HTTP Port",
"HTTPS_Port": "HTTPS Port",
"TCPMux": "TCPMux HTTPConnect Port",
"Subdomain": "Subdomain Host",
"MaxPoolCount": "Max PoolCount",
"MaxPortsPerClient": "Max Ports Per Client",
"AllowPorts": "Allow Ports",
"TLSForce": "TLS Force",
"HeartBeatTimeout": "HeartBeat Timeout",
"ClientCounts": "Client Counts",
"curConns": "Current Connections",
"ProxyCounts": "Proxy Counts",
"Chart": {
"Traffic": {
"title": "Network Traffic",
"subTitle": "today",
"TrafficIn": "Traffic In",
"TrafficOut": "Traffic Out"
},
"Proxies": {
"title": "Proxies",
"subTitle": "now"
}
}
},
"ProxiesView": {
"Expand": {
"Name": "Name",
"Type": "Type",
"Encryption": "Encryption",
"Compression": "Compression",
"LastStart": "Last Start",
"LastClose": "Last Close",
"Domains": "Domains",
"SubDomain": "SubDomain",
"locations": "locations",
"HostRewrite": "HostRewrite",
"Multiplexer": "Multiplexer",
"RouteByHTTPUser": "RouteByHTTPUser",
"Addr": "Addr",
"Annotations": "Annotations"
},
"ClearOffLine": "ClearOfflineProxies",
"Refresh": "Refresh",
"ClearOffLineInfo": "Are you sure to clear all data of offline proxies?",
"name": "Name",
"Port": "Port",
"Connections": "Connections",
"Traffic_In": "Traffic In",
"Traffic_Out": "Traffic Out",
"ClientVersion": "ClientVersion",
"Status": {
"title": "Status",
"Successinfo": "online"
},
"Operations": {
"title": "Operations",
"Traffic": "Traffic"
}
}
}

View File

@ -0,0 +1,88 @@
{
"main": {
"title": "frp 服务端",
"Overview": "总览",
"Proxies": {
"title": "代理"
},
"Help": "帮助",
"dark": {
"Dark": "暗",
"Light": "明"
}
},
"OverView": {
"Expand": {
"Name": "通道名称",
"Type": "协议类型",
"Encryption": "加密",
"Compression": "压缩",
"LastStart": "最后一次启用时间",
"LastClose": "最后一次关闭时间",
"Domains": "域名",
"SubDomain": "二级域名后缀",
"locations": "URL 路由配置",
"HostRewrite": "替换 Host Header",
"Multiplexer": "复用器类型",
"RouteByHTTPUser": "根据 HTTP Basic Auth user 路由",
"Addr": "代理端口",
"Annotations": "注释"
},
"Version": "版本",
"BindPort": "frp 绑定端口",
"KPC_Port": "KCP 绑定端口",
"QUIC_Port": "QUIC 绑定端口",
"HTTP_Port": "HTTP 代理监听端口",
"HTTPS_Port": "HTTPS 代理监听端口",
"TCPMux": "TCPMux HTTPConnect 代理监听的端口",
"Subdomain": "二级域名后缀",
"MaxPoolCount": "最大连接池数量",
"MaxPortsPerClient": "单客户端最大代理数",
"AllowPorts": "允许代理的服务端端口",
"TLSForce": "TLS协议版本",
"HeartBeatTimeout": "心跳超时时间",
"ClientCounts": "客户端数量",
"curConns": "当前连接数",
"ProxyCounts": "代理数量",
"Chart": {
"Traffic": {
"title": "网络流量",
"subTitle": "今日",
"TrafficIn": "进站流量",
"TrafficOut": "出站流量"
},
"Proxies": {
"title": "代理占比",
"subTitle": "当前"
}
}
},
"ProxiesView": {
"ClearOffLine": "清理离线链接",
"Refresh": "刷新",
"ClearOffLineInfo": "确定清理所有离线数据?",
"name": "代理名称",
"Port": "代理端口",
"Connections": "连接数",
"Traffic_In": "入站流量",
"Traffic_Out": "出站流量",
"ClientVersion": "frp客户端版本",
"Status": {
"title": "状态",
"Successinfo": "在线"
},
"Operations": {
"title": "操作",
"Traffic": "流量"
}
},
"ProxiesViews": {
"name": "通道名称",
"type": "协议类型",
"local_addr": "本地地址",
"plugin": "插件",
"remote_addr": "远程地址",
"status": "状态",
"err": "信息"
}
}

View File

@ -1,85 +1,57 @@
<template>
<div>
<el-page-header
:icon="null"
style="width: 100%; margin-left: 30px; margin-bottom: 20px"
>
<el-page-header :icon="null" style="width: 100%; margin-left: 30px; margin-bottom: 20px">
<template #title>
<span>{{ proxyType }}</span>
</template>
<template #content> </template>
<template #extra>
<div class="flex items-center" style="margin-right: 30px">
<el-popconfirm
title="Are you sure to clear all data of offline proxies?"
@confirm="clearOfflineProxies"
>
<el-popconfirm :title="t('ProxiesView.ClearOffLineInfo')" @confirm="clearOfflineProxies">
<template #reference>
<el-button>ClearOfflineProxies</el-button>
<el-button>{{ t("ProxiesView.ClearOffLine") }}</el-button>
</template>
</el-popconfirm>
<el-button @click="$emit('refresh')">Refresh</el-button>
<el-button @click="$emit('refresh')">{{ t("ProxiesView.Refresh") }}</el-button>
</div>
</template>
</el-page-header>
<el-table
:data="proxies"
:default-sort="{ prop: 'name', order: 'ascending' }"
style="width: 100%"
>
<el-table :data="proxies" :default-sort="{ prop: 'name', order: 'ascending' }" style="width: 100%">
<el-table-column type="expand">
<template #default="props">
<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 :label="t('ProxiesView.name')" prop="name" sortable> </el-table-column>
<el-table-column :label="t('ProxiesView.Port')" prop="port" sortable> </el-table-column>
<el-table-column :label="t('ProxiesView.Connections')" prop="conns" sortable>
</el-table-column>
<el-table-column
label="Traffic In"
prop="trafficIn"
:formatter="formatTrafficIn"
sortable
>
<el-table-column :label="t('ProxiesView.Traffic_In')" prop="trafficIn" :formatter="formatTrafficIn" sortable>
</el-table-column>
<el-table-column
label="Traffic Out"
prop="trafficOut"
:formatter="formatTrafficOut"
sortable
>
<el-table-column :label="t('ProxiesView.Traffic_Out')" prop="trafficOut" :formatter="formatTrafficOut" sortable>
</el-table-column>
<el-table-column label="ClientVersion" prop="clientVersion" sortable>
<el-table-column :label="t('ProxiesView.ClientVersion')" prop="clientVersion" sortable>
</el-table-column>
<el-table-column label="Status" prop="status" sortable>
<el-table-column :label="t('ProxiesView.Status.title')" prop="status" sortable>
<template #default="scope">
<el-tag v-if="scope.row.status === 'online'" type="success">{{
scope.row.status
t("ProxiesView.Status.Successinfo")
}}</el-tag>
<el-tag v-else type="danger">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column label="Operations">
<el-table-column :label="t('ProxiesView.Operations.title')">
<template #default="scope">
<el-button
type="primary"
:name="scope.row.name"
style="margin-bottom: 10px"
@click="dialogVisibleName = scope.row.name; dialogVisible = true"
>Traffic
<el-button type="primary" :name="scope.row.name" style="margin-bottom: 10px"
@click="dialogVisibleName = scope.row.name; dialogVisible = true">{{ t("ProxiesView.Operations.Traffic") }}
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<el-dialog
v-model="dialogVisible"
destroy-on-close="true"
:title="dialogVisibleName"
width="700px">
<el-dialog v-model="dialogVisible" destroy-on-close="true" :title="dialogVisibleName" width="700px">
<Traffic :proxyName="dialogVisibleName" />
</el-dialog>
</template>
@ -91,6 +63,8 @@ import type { BaseProxy } from '../utils/proxy.js'
import { ElMessage } from 'element-plus'
import ProxyViewExpand from './ProxyViewExpand.vue'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
defineProps<{
proxies: BaseProxy[]

View File

@ -1,77 +1,74 @@
<template>
<el-form
label-position="left"
label-width="auto"
inline
class="proxy-table-expand"
>
<el-form-item label="Name">
<el-form label-position="left" label-width="auto" inline class="proxy-table-expand">
<el-form-item :label="t('OverView.Expand.Name')">
<span>{{ row.name }}</span>
</el-form-item>
<el-form-item label="Type">
<el-form-item :label="t('OverView.Expand.Type')">
<span>{{ row.type }}</span>
</el-form-item>
<el-form-item label="Encryption">
<el-form-item :label="t('OverView.Expand.Encryption')">
<span>{{ row.encryption }}</span>
</el-form-item>
<el-form-item label="Compression">
<el-form-item :label="t('OverView.Expand.Compression')">
<span>{{ row.compression }}</span>
</el-form-item>
<el-form-item label="Last Start">
<el-form-item :label="t('OverView.Expand.LastStart')">
<span>{{ row.lastStartTime }}</span>
</el-form-item>
<el-form-item label="Last Close">
<el-form-item :label="t('OverView.Expand.LastClose')">
<span>{{ row.lastCloseTime }}</span>
</el-form-item>
<div v-if="proxyType === 'http' || proxyType === 'https'">
<el-form-item label="Domains">
<el-form-item :label="t('OverView.Expand.Domains')">
<span>{{ row.customDomains }}</span>
</el-form-item>
<el-form-item label="SubDomain">
<el-form-item :label="t('OverView.Expand.SubDomain')">
<span>{{ row.subdomain }}</span>
</el-form-item>
<el-form-item label="locations">
<el-form-item :label="t('OverView.Expand.locations')">
<span>{{ row.locations }}</span>
</el-form-item>
<el-form-item label="HostRewrite">
<el-form-item :label="t('OverView.Expand.HostRewrite')">
<span>{{ row.hostHeaderRewrite }}</span>
</el-form-item>
</div>
<div v-else-if="proxyType === 'tcpmux'">
<el-form-item label="Multiplexer">
<el-form-item :label="t('OverView.Expand.Multiplexer')">
<span>{{ row.multiplexer }}</span>
</el-form-item>
<el-form-item label="RouteByHTTPUser">
<el-form-item :label="t('OverView.Expand.RouteByHTTPUser')">
<span>{{ row.routeByHTTPUser }}</span>
</el-form-item>
<el-form-item label="Domains">
<el-form-item :label="t('OverView.Expand.Domains')">
<span>{{ row.customDomains }}</span>
</el-form-item>
<el-form-item label="SubDomain">
<el-form-item :label="t('OverView.Expand.SubDomain')">
<span>{{ row.subdomain }}</span>
</el-form-item>
</div>
<div v-else>
<el-form-item label="Addr">
<el-form-item :label="t('OverView.Expand.Addr')">
<span>{{ row.addr }}</span>
</el-form-item>
</div>
</el-form>
<div v-if="row.annotations && row.annotations.size > 0">
<el-divider />
<el-text class="title-text" size="large">Annotations</el-text>
<ul>
<li v-for="item in annotationsArray()">
<span class="annotation-key">{{ item.key }}</span>
<span>{{ item.value }}</span>
</li>
</ul>
<el-divider />
<el-text class="title-text" size="large">{{ t("OverView.Expand.Annotations") }}</el-text>
<ul>
<li v-for="item in annotationsArray()">
<span class="annotation-key">{{ item.key }}</span>
<span>{{ item.value }}</span>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const props = defineProps<{
row: any

View File

@ -3,73 +3,60 @@
<el-row>
<el-col :md="12">
<div class="source">
<el-form
label-position="left"
label-width="220px"
class="server_info"
>
<el-form-item label="Version">
<el-form label-position="left" label-width="220px" class="server_info">
<el-form-item :label="t('OverView.Version')">
<span>{{ data.version }}</span>
</el-form-item>
<el-form-item label="BindPort">
<el-form-item :label="t('OverView.BindPort')">
<span>{{ data.bindPort }}</span>
</el-form-item>
<el-form-item label="KCP Bind Port" v-if="data.kcpBindPort != 0">
<el-form-item :label="t('OverView.KPC_Port')" v-if="data.kcpBindPort != 0">
<span>{{ data.kcpBindPort }}</span>
</el-form-item>
<el-form-item label="QUIC Bind Port" v-if="data.quicBindPort != 0">
<el-form-item :label="t('OverView.QUIC_Port')" v-if="data.quicBindPort != 0">
<span>{{ data.quicBindPort }}</span>
</el-form-item>
<el-form-item label="HTTP Port" v-if="data.vhostHTTPPort != 0">
<el-form-item :label="t('OverView.HTTP_Port')" v-if="data.vhostHTTPPort != 0">
<span>{{ data.vhostHTTPPort }}</span>
</el-form-item>
<el-form-item label="HTTPS Port" v-if="data.vhostHTTPSPort != 0">
<el-form-item :label="t('OverView.HTTPS_Port')" v-if="data.vhostHTTPSPort != 0">
<span>{{ data.vhostHTTPSPort }}</span>
</el-form-item>
<el-form-item
label="TCPMux HTTPConnect Port"
v-if="data.tcpmuxHTTPConnectPort != 0"
>
<el-form-item :label="t('OverView.TCPMux')" v-if="data.tcpmuxHTTPConnectPort != 0">
<span>{{ data.tcpmuxHTTPConnectPort }}</span>
</el-form-item>
<el-form-item
label="Subdomain Host"
v-if="data.subdomainHost != ''"
>
<el-form-item :label="t('OverView.Subdomain')" v-if="data.subdomainHost != ''">
<LongSpan :content="data.subdomainHost" :length="30"></LongSpan>
</el-form-item>
<el-form-item label="Max PoolCount">
<el-form-item :label="t('OverView.MaxPoolCount')">
<span>{{ data.maxPoolCount }}</span>
</el-form-item>
<el-form-item label="Max Ports Per Client">
<el-form-item :label="t('OverView.MaxPortsPerClient')">
<span>{{ data.maxPortsPerClient }}</span>
</el-form-item>
<el-form-item label="Allow Ports" v-if="data.allowPortsStr != ''">
<el-form-item :label="t('OverView.AllowPorts')" v-if="data.allowPortsStr != ''">
<LongSpan :content="data.allowPortsStr" :length="30"></LongSpan>
</el-form-item>
<el-form-item label="TLS Force" v-if="data.tlsForce === true">
<el-form-item :label="t('OverView.TLSForce')" v-if="data.tlsForce === true">
<span>{{ data.tlsForce }}</span>
</el-form-item>
<el-form-item label="HeartBeat Timeout">
<el-form-item :label="t('OverView.HeartBeatTimeout')">
<span>{{ data.heartbeatTimeout }}</span>
</el-form-item>
<el-form-item label="Client Counts">
<el-form-item :label="t('OverView.ClientCounts')">
<span>{{ data.clientCounts }}</span>
</el-form-item>
<el-form-item label="Current Connections">
<el-form-item :label="t('OverView.curConns')">
<span>{{ data.curConns }}</span>
</el-form-item>
<el-form-item label="Proxy Counts">
<el-form-item :label="t('OverView.ProxyCounts')">
<span>{{ data.proxyCounts }}</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="traffic" style="width: 400px; height: 250px; margin-bottom: 30px"></div>
<div id="proxies" style="width: 400px; height: 250px"></div>
</el-col>
</el-row>
@ -81,6 +68,8 @@ import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { DrawTrafficChart, DrawProxyChart } from '../utils/chart'
import LongSpan from './LongSpan.vue'
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
let data = ref({
version: '',

View File

@ -1,4 +1,5 @@
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n';
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import App from './App.vue'
@ -6,9 +7,19 @@ import router from './router'
import './assets/custom.css'
import './assets/dark.css'
import en from './assets/locales/en.json';
import zh from './assets/locales/zh.json';
const storedLocale = localStorage.getItem('i18n') || 'en';
const i18n = createI18n({
locale: storedLocale, // 默认语言
messages: {
en,
zh,
},
});
const app = createApp(App)
app.use(router)
app.use(i18n);
app.mount('#app')

View File

@ -205,6 +205,27 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917"
integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==
"@intlify/core-base@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/core-base/-/core-base-10.0.5.tgz#c4d992381f8c3a50c79faf67be3404b399c3be28"
integrity sha512-F3snDTQs0MdvnnyzTDTVkOYVAZOE/MHwRvF7mn7Jw1yuih4NrFYLNYIymGlLmq4HU2iIdzYsZ7f47bOcwY73XQ==
dependencies:
"@intlify/message-compiler" "10.0.5"
"@intlify/shared" "10.0.5"
"@intlify/message-compiler@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-10.0.5.tgz#4eeace9f4560020d5e5d77f32bed7755e71d8efd"
integrity sha512-6GT1BJ852gZ0gItNZN2krX5QAmea+cmdjMvsWohArAZ3GmHdnNANEcF9JjPXAMRtQ6Ux5E269ymamg/+WU6tQA==
dependencies:
"@intlify/shared" "10.0.5"
source-map-js "^1.0.2"
"@intlify/shared@10.0.5":
version "10.0.5"
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-10.0.5.tgz#1b46ca8b541f03508fe28da8f34e4bb85506d6bc"
integrity sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==
"@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
@ -2523,6 +2544,15 @@ vue-eslint-parser@^9.3.1, vue-eslint-parser@^9.4.2:
lodash "^4.17.21"
semver "^7.3.6"
vue-i18n@^10.0.5:
version "10.0.5"
resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-10.0.5.tgz#fdf4e6c7b669e80cfa3a12ed9625e2b46671cdf0"
integrity sha512-9/gmDlCblz3i8ypu/afiIc/SUIfTTE1mr0mZhb9pk70xo2csHAM9mp2gdQ3KD2O0AM3Hz/5ypb+FycTj/lHlPQ==
dependencies:
"@intlify/core-base" "10.0.5"
"@intlify/shared" "10.0.5"
"@vue/devtools-api" "^6.5.0"
vue-router@^4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.2.5.tgz#b9e3e08f1bd9ea363fdd173032620bc50cf0e98a"