mirror of
https://github.com/fatedier/frp.git
synced 2025-04-20 00:24:21 +00:00
frps多语言设计完成
This commit is contained in:
parent
ff0676a3b1
commit
aadb2a8953
3
web/frps/components.d.ts
vendored
3
web/frps/components.d.ts
vendored
@ -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']
|
||||
|
@ -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": {
|
||||
|
@ -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>
|
||||
|
1
web/frps/src/assets/lang.svg
Normal file
1
web/frps/src/assets/lang.svg
Normal 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 |
79
web/frps/src/assets/locales/en.json
Normal file
79
web/frps/src/assets/locales/en.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
88
web/frps/src/assets/locales/zh.json
Normal file
88
web/frps/src/assets/locales/zh.json
Normal 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": "信息"
|
||||
}
|
||||
}
|
@ -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[]
|
||||
|
@ -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
|
||||
|
@ -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: '',
|
||||
|
@ -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')
|
||||
|
@ -3,7 +3,7 @@ import * as echarts from 'echarts/core'
|
||||
import { PieChart, BarChart } from 'echarts/charts'
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { LabelLayout } from 'echarts/features'
|
||||
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
@ -27,6 +27,7 @@ function DrawTrafficChart(
|
||||
trafficIn: number,
|
||||
trafficOut: number
|
||||
) {
|
||||
const { t } = useI18n();
|
||||
const myChart = echarts.init(
|
||||
document.getElementById(elementId) as HTMLElement,
|
||||
'macarons'
|
||||
@ -35,8 +36,8 @@ function DrawTrafficChart(
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: 'Network Traffic',
|
||||
subtext: 'today',
|
||||
text: t("OverView.Chart.Traffic.title"),
|
||||
subtext: t("OverView.Chart.Traffic.subTitle"),
|
||||
left: 'center',
|
||||
},
|
||||
tooltip: {
|
||||
@ -48,7 +49,7 @@ function DrawTrafficChart(
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['Traffic In', 'Traffic Out'],
|
||||
data: [t("OverView.Chart.Traffic.TrafficIn"), t("OverView.Chart.Traffic.TrafficOut")],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@ -58,11 +59,11 @@ function DrawTrafficChart(
|
||||
data: [
|
||||
{
|
||||
value: trafficIn,
|
||||
name: 'Traffic In',
|
||||
name: t("OverView.Chart.Traffic.TrafficIn"),
|
||||
},
|
||||
{
|
||||
value: trafficOut,
|
||||
name: 'Traffic Out',
|
||||
name: t("OverView.Chart.Traffic.TrafficOut"),
|
||||
},
|
||||
],
|
||||
emphasis: {
|
||||
@ -80,6 +81,7 @@ function DrawTrafficChart(
|
||||
}
|
||||
|
||||
function DrawProxyChart(elementId: string, serverInfo: any) {
|
||||
const { t } = useI18n();
|
||||
const myChart = echarts.init(
|
||||
document.getElementById(elementId) as HTMLElement,
|
||||
'macarons'
|
||||
@ -88,8 +90,8 @@ function DrawProxyChart(elementId: string, serverInfo: any) {
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: 'Proxies',
|
||||
subtext: 'now',
|
||||
text: t("OverView.Chart.Proxies.title"),
|
||||
subtext: t("OverView.Chart.Proxies.subTitle"),
|
||||
left: 'center',
|
||||
},
|
||||
tooltip: {
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user