Skip to content

Commit c292df4

Browse files
committedJan 12, 2025
Improvements
1 parent 855e3fb commit c292df4

File tree

6 files changed

+1448
-25
lines changed

6 files changed

+1448
-25
lines changed
 

‎.github/workflows/docker-image.yml

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ jobs:
4040
printf "RELEASE_VERSION=%s\n" "${{ github.event.release.tag_name }}" >> $GITHUB_ENV
4141
printf "RELEASE_NOTES<<EOF\n%s\nEOF\n" "${{ github.event.release.body }}" >> $GITHUB_ENV
4242
43+
- name: Clean RELEASE_NOTES
44+
run: |
45+
export CLEAN_RELEASE_NOTES=$(echo "${{ env.RELEASE_NOTES }}" | sed '/^\s*$/d')
46+
echo "RELEASE_NOTES=${CLEAN_RELEASE_NOTES}" >> $GITHUB_ENV
47+
4348
- name: Set version for manual dispatch
4449
if: github.event_name == 'workflow_dispatch'
4550
run: |

‎frontend/components/SpeedTest.vue

+87-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@
4444
</div>
4545
</div>
4646

47+
<Transition name="slide-fade">
48+
<div class="d-flex align-items-center align-content-center justify-content-end pb-2"
49+
:data-bs-theme="isDarkMode ? 'dark' : ''" v-if="speedTestStatus !== 'idle' && connectionData.colo">
50+
<div>
51+
<i class="bi bi-person-arms-up"></i>
52+
{{connectionData.country}}
53+
<span v-if="connectionData.country" :class="'jn-fl fi fi-' + connectionData.loc.toLowerCase()"></span>
54+
</div>
55+
<div class=" mx-2">
56+
<i class="bi bi-arrow-left-right"></i>
57+
</div>
58+
<div>
59+
<i class="bi bi-globe"></i>
60+
{{connectionData.colo}},&nbsp;
61+
{{connectionData.coloCountry}} <span v-if="connectionData.coloCountry"
62+
:class="'jn-fl fi fi-' + connectionData.coloCountryCode.toLowerCase()"></span>
63+
</div>
64+
</div>
65+
</Transition>
4766
<div class="progress" style="height: 20px; margin: 4pt 0 20pt 0;"
4867
:class="{ 'jn-opacity-0': speedTestStatus == 'idle', 'jn-progress-dark': isDarkMode }">
4968
<div class="progress-bar progress-bar-striped jn-progress"
@@ -84,7 +103,17 @@
84103
</div>
85104
<div class="row alert alert-success m-1 p-2 " :data-bs-theme="isDarkMode ? 'dark' : ''"
86105
v-if="speedTestStatus === 'finished' && hasScores">
87-
<p id="score" class="speedtest-p"><i class="bi bi-calendar2-check"></i> {{ t('speedtest.score') }}
106+
<p id="score" class="speedtest-p"><i class="bi bi-calendar2-check"></i>&nbsp;
107+
<span v-if="connectionData.colo">
108+
{{ t('speedtest.connectionFrom') }}
109+
{{ connectionData.ip }} ( {{ connectionData.country }} )
110+
{{ t('speedtest.connectionTo') }}
111+
{{ connectionData.colo }}
112+
( {{ connectionData.coloCity }}
113+
, {{ connectionData.coloCountry }} )
114+
{{ t('speedtest.connectionEnd') }}
115+
</span>
116+
{{ t('speedtest.score') }}
88117
{{ t('speedtest.videoStreaming') }}
89118
<span :class="speedTest.streamingScore >= 50 ? 'text-success' : 'jn-text-warning'">
90119
{{ speedTest.streamingScore }}
@@ -113,6 +142,9 @@ import { ref, computed, onMounted, reactive, markRaw } from 'vue';
113142
import { useMainStore } from '@/store';
114143
import { useI18n } from 'vue-i18n';
115144
import { trackEvent } from '@/utils/use-analytics';
145+
import { isValidIP } from '@/utils/valid-ip.js';
146+
import getCountryName from '@/utils/country-name.js';
147+
import getColoCountry from '@/utils/speedtest-colos.js';
116148
// 引入 SpeedTest
117149
import SpeedTestEngine from '@cloudflare/speedtest';
118150
@@ -121,6 +153,7 @@ const { t } = useI18n();
121153
const store = useMainStore();
122154
const isDarkMode = computed(() => store.isDarkMode);
123155
const isMobile = computed(() => store.isMobile);
156+
const lang = computed(() => store.lang);
124157
125158
const speedTest = reactive({
126159
id: "speedTest",
@@ -147,6 +180,40 @@ const packageSize = reactive({
147180
}
148181
});
149182
183+
const connectionData = ref({
184+
ip: "",
185+
colo: "",
186+
loc: "",
187+
country: "",
188+
coloCountry: "",
189+
coloCountryCode: "",
190+
coloCity: ""
191+
});
192+
193+
const getIPFromSpeedTest = async () => {
194+
try {
195+
const response = await fetch("https://speed.cloudflare.com/cdn-cgi/trace");
196+
const data = await response.text();
197+
const lines = data.split("\n");
198+
199+
const ip = lines.find((line) => line.startsWith("ip="))?.split("=")[1];
200+
const colo = lines.find((line) => line.startsWith("colo="))?.split("=")[1];
201+
const loc = lines.find((line) => line.startsWith("loc="))?.split("=")[1];
202+
203+
if (isValidIP(ip)) {
204+
const country = getCountryName(loc, lang.value) || '';
205+
const coloCountryCode = getColoCountry(colo).country || '';
206+
const coloCity = getColoCountry(colo).city || '';
207+
const coloCountry = getCountryName(coloCountryCode, lang.value) || '';
208+
return { ip, colo, loc, country, coloCountry, coloCountryCode, coloCity };
209+
} else {
210+
console.error("Invalid IP from SpeedTest Server:", ip);
211+
}
212+
} catch (error) {
213+
console.error("Error fetching IP from SpeedTest Server:", error);
214+
}
215+
};
216+
150217
// 定义 Speed Test 引擎
151218
let testEngine;
152219
@@ -166,12 +233,15 @@ const resetSpeedTest = () => {
166233
};
167234
168235
// Speed Test 引擎
169-
const speedTestController = () => {
236+
const speedTestController = async () => {
170237
if (speedTestStatus.value === 'running') {
171238
testEngine.pause();
172239
speedTestStatus.value = "paused";
173240
} else {
174241
startSpeedTest();
242+
if (!connectionData.value.ip) {
243+
connectionData.value = await getIPFromSpeedTest();
244+
}
175245
}
176246
};
177247
@@ -365,8 +435,23 @@ defineExpose({
365435
background-color: var(--bs-btn-hover-bg);
366436
border-color: var(--bs-btn-hover-border-color);
367437
}
438+
368439
.jn-text-warning {
369440
--bs-text-opacity: 1;
370441
color: #c67c14;
371442
}
443+
444+
.slide-fade-enter-active {
445+
transition: all 0.3s ease-out;
446+
}
447+
448+
.slide-fade-leave-active {
449+
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
450+
}
451+
452+
.slide-fade-enter-from,
453+
.slide-fade-leave-to {
454+
transform: translateX(20px);
455+
opacity: 0;
456+
}
372457
</style>

‎frontend/locales/en.json

+10-7
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@
5757
"Optional": "Optional",
5858
"Essential": "Essential",
5959
"Advanced": "Advanced",
60-
"Reset":"Reset Checklist",
61-
"ShowAll":"Show All",
62-
"ShowUnchecked":"Show Unchecked",
63-
"ShowIgnored":"Show Ignored",
64-
"ShowChecked":"Show Checked",
65-
"Loading":"Loading..."
60+
"Reset": "Reset Checklist",
61+
"ShowAll": "Show All",
62+
"ShowUnchecked": "Show Unchecked",
63+
"ShowIgnored": "Show Ignored",
64+
"ShowChecked": "Show Checked",
65+
"Loading": "Loading..."
6666
},
6767
"shell": {
6868
"Title": "Command Line API",
@@ -407,7 +407,10 @@
407407
"gaming": ", Gaming: ",
408408
"rtc": ", Video Chatting: ",
409409
"score": "Based on the speed test, got the following quality scores:",
410-
"resultNote": ". The score is for reference only."
410+
"resultNote": ". The score is for reference only.",
411+
"connectionFrom": "Finished speed test from your IP: ",
412+
"connectionTo": " to test server:",
413+
"connectionEnd": " ."
411414
},
412415
"pingtest": {
413416
"id": "pingtest",

‎frontend/locales/fr.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,10 @@
407407
"gaming": ", Jeu : ",
408408
"rtc": ", Chat vidéo : ",
409409
"score": "Sur la base du test de vitesse, voici les scores de qualité suivants :",
410-
"resultNote": ". Le score est donné à titre indicatif seulement."
410+
"resultNote": ". Le score est donné à titre indicatif seulement.",
411+
"connectionFrom": "Test de vitesse terminé depuis votre IP: ",
412+
"connectionTo": " vers le serveur de test:",
413+
"connectionEnd": " ."
411414
},
412415
"pingtest": {
413416
"id": "pingtest",

‎frontend/locales/zh.json

+18-15
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,23 @@
4646
"Items": "个项目",
4747
"Priority": "级别",
4848
"Ignore": "忽略",
49-
"alert-total":"安全检查一共有",
50-
"alert-checked":"你已经完成了",
51-
"alert-ignored":"被忽略",
52-
"alert-unchecked":"个未进行检查。",
49+
"alert-total": "安全检查一共有",
50+
"alert-checked": "你已经完成了",
51+
"alert-ignored": "被忽略",
52+
"alert-unchecked": "个未进行检查。",
5353
"Checked": "已检查",
5454
"Ignored": "已忽略",
5555
"Unchecked": "未检查",
56-
"Basic":"基础",
57-
"Optional":"可选",
58-
"Essential":"必要",
59-
"Advanced":"高级",
60-
"Reset":"重置",
61-
"ShowAll":"显示所有",
62-
"ShowUnchecked":"显示未检查",
63-
"ShowIgnored":"显示已忽略",
64-
"ShowChecked":"显示已检查",
65-
"Loading":"加载中..."
56+
"Basic": "基础",
57+
"Optional": "可选",
58+
"Essential": "必要",
59+
"Advanced": "高级",
60+
"Reset": "重置",
61+
"ShowAll": "显示所有",
62+
"ShowUnchecked": "显示未检查",
63+
"ShowIgnored": "显示已忽略",
64+
"ShowChecked": "显示已检查",
65+
"Loading": "加载中..."
6666
},
6767
"shell": {
6868
"Title": "命令行 API",
@@ -407,7 +407,10 @@
407407
"gaming": " 分,在线游戏:",
408408
"rtc": " 分,视频会议:",
409409
"score": "根据网速测试,得出以下质量分数:",
410-
"resultNote": " 分。分数仅供参考。"
410+
"resultNote": " 分。分数仅供参考。",
411+
"connectionFrom": "已完成从你的 IP:",
412+
"connectionTo": "与测速服务器:",
413+
"connectionEnd": " 的测试。"
411414
},
412415
"pingtest": {
413416
"id": "pingtest",

0 commit comments

Comments
 (0)