仪表盘和订阅详情的操作按钮改 text-button,公网 IP 带旗帜

检测公网 IP、重启内核、订阅详情右上三个按钮都去掉边框,hover 出浅底。
检测结果由国家代码换成旗帜 emoji 加 IP;Windows 的系统字体没有旗帜
字形,浏览器会退回显示两个字母,和原来的效果一致。
This commit is contained in:
2026-08-12 13:17:21 +08:00
parent a40bd6a01b
commit 129a76696b
4 changed files with 62 additions and 22 deletions
+31 -15
View File
@@ -10,7 +10,7 @@
*/
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { collectInbounds, inboundStatKey } from '@shared/inbounds.ts'
import { formatBytes, formatUptime } from '@shared/format.ts'
import { flagEmoji, formatBytes, formatUptime } from '@shared/format.ts'
import { ACTIVE_BYTES, ROUTE_WINDOW_MS, bucketRates, lastRate, windowBytes } from '@shared/telemetry.ts'
import type { RouteSample } from '@shared/telemetry.ts'
import type { HostInfo } from '@shared/host-info.ts'
@@ -41,6 +41,8 @@ import IconLan from '~icons/ri/router-line'
import IconKernel from '~icons/ri/terminal-box-line'
import IconOverview from '~icons/ri/layout-grid-line'
import IconGo from '~icons/ri/arrow-right-s-line'
import IconProbe from '~icons/ri/global-line'
import IconRestart from '~icons/ri/restart-line'
const props = defineProps<{ data: ConfigObject }>()
@@ -135,7 +137,7 @@ function exitCell(probeable: boolean, port: number | null): ExitCell {
return {
kind: 'ok',
port,
text: [result.countryCode, result.ip].filter(Boolean).join(' ') || '未知地址',
text: [flagEmoji(result.countryCode ?? ''), result.ip].filter(Boolean).join(' ') || '未知地址',
title: `${result.country ?? ''} 往返 ${String(result.ms ?? '?')} ms,点击重测`,
}
}
@@ -431,7 +433,7 @@ const ports = computed(() => kernelPorts(configs.value ?? {}))
:disabled="restarting"
@click="confirmRestart = true"
>
{{ restarting ? '重启中' : '重启内核' }}
<IconRestart /> {{ restarting ? '重启中' : '重启内核' }}
</button>
</header>
<div class="sect-b">
@@ -490,9 +492,10 @@ const ports = computed(() => kernelPorts(configs.value ?? {}))
v-if="row.exit.kind === 'idle'"
type="button"
class="probe"
title="检测公网 IP"
@click.stop="void probeExit(row.exit.port)"
>
检测公网 IP
<IconProbe /> 检测
</button>
<span v-else-if="row.exit.kind === 'loading'" class="probe-wait">检测中</span>
<button
@@ -850,23 +853,30 @@ const ports = computed(() => kernelPorts(configs.value ?? {}))
/* ── 内核 ─────────────────────────────────────── */
.restart {
display: flex;
align-items: center;
gap: var(--s-1);
margin-left: auto;
padding: 2px var(--s-3);
border: 1px solid var(--c-border-strong);
padding: 2px var(--s-2);
border: none;
border-radius: var(--r-sm);
background: var(--c-surface);
background: none;
color: var(--c-text-soft);
font-size: var(--t-xs);
cursor: pointer;
}
.restart:hover:not(:disabled) {
border-color: color-mix(in srgb, var(--c-danger) 45%, var(--c-border));
background: var(--c-surface-sunken);
color: var(--c-danger);
}
.restart:disabled {
color: var(--c-text-faint);
cursor: default;
}
.restart svg {
width: 13px;
height: 13px;
}
/* ── 路由 ─────────────────────────────────────── */
.routes {
@@ -940,27 +950,33 @@ const ports = computed(() => kernelPorts(configs.value ?? {}))
.probe,
.exit {
display: inline-flex;
align-items: center;
gap: var(--s-1);
padding: 1px var(--s-2);
border: 1px solid var(--c-border-strong);
border: none;
border-radius: var(--r-sm);
background: var(--c-surface);
background: none;
color: var(--c-text-soft);
font-size: var(--t-xs);
cursor: pointer;
}
.probe:hover,
.exit:hover {
border-color: var(--c-accent);
background: var(--c-surface-sunken);
color: var(--c-accent-text);
}
.exit {
border-color: transparent;
color: var(--c-text-soft);
.probe svg {
width: 13px;
height: 13px;
}
.probe-fail {
color: var(--c-danger);
border-color: color-mix(in srgb, var(--c-danger) 35%, var(--c-border));
}
.probe-fail:hover {
color: var(--c-danger);
}
.probe-wait,
+6 -6
View File
@@ -149,22 +149,22 @@ function delayClass(ms: number | null): string {
display: flex;
align-items: center;
gap: var(--s-1);
padding: var(--s-1) var(--s-3);
border: 1px solid var(--c-border-strong);
padding: var(--s-1) var(--s-2);
border: none;
border-radius: var(--r-sm);
background: var(--c-surface);
background: none;
color: var(--c-text-soft);
font-size: var(--t-sm);
white-space: nowrap;
cursor: pointer;
}
.acts button:hover:not(:disabled) {
border-color: var(--c-accent);
color: var(--c-accent-text);
background: var(--c-surface-sunken);
color: var(--c-text);
}
.acts button.danger:hover:not(:disabled) {
border-color: var(--c-danger);
color: var(--c-danger);
}