frps多语言设计完成

This commit is contained in:
nkdns 2024-11-29 16:44:30 +08:00
parent ff0676a3b1
commit aadb2a8953
No known key found for this signature in database
12 changed files with 330 additions and 137 deletions

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

@ -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: {

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"