diff --git a/web/html/modals/nord_modal.html b/web/html/modals/nord_modal.html
index 814712db..5cd5fceb 100644
--- a/web/html/modals/nord_modal.html
+++ b/web/html/modals/nord_modal.html
@@ -47,10 +47,20 @@
-
+
+
+
+ {{ i18n "pages.xray.outbound.allCities" }}
+
+
+ [[ c.name ]]
+
+
+
+
-
- [[ s.name ]] ({{ i18n "pages.xray.outbound.load" }}: [[ s.load ]]%)
+
+ [[ s.cityName ]] - [[ s.name ]] ({{ i18n "pages.xray.outbound.load" }}: [[ s.load ]]%)
@@ -78,6 +88,8 @@
manualKey: '',
countries: [],
countryId: null,
+ cities: [],
+ cityId: null,
servers: [],
serverId: null,
show() {
@@ -129,8 +141,10 @@
this.token = '';
this.manualKey = '';
this.countries = [];
+ this.cities = [];
this.servers = [];
this.countryId = null;
+ this.cityId = null;
}
this.loading(false);
},
@@ -143,11 +157,31 @@
async fetchServers() {
this.loading(true);
this.servers = [];
+ this.cities = [];
this.serverId = null;
+ this.cityId = null;
const msg = await HttpUtil.post('/panel/xray/nord/servers', { countryId: this.countryId });
if (msg.success) {
const data = JSON.parse(msg.obj);
- this.servers = (data.servers || []).sort((a, b) => a.load - b.load);
+ const locations = data.locations || [];
+ const locToCity = {};
+ const citiesMap = new Map();
+ locations.forEach(loc => {
+ if (loc.country && loc.country.city) {
+ citiesMap.set(loc.country.city.id, loc.country.city);
+ locToCity[loc.id] = loc.country.city;
+ }
+ });
+ this.cities = Array.from(citiesMap.values()).sort((a, b) => a.name.localeCompare(b.name));
+
+ this.servers = (data.servers || []).map(s => {
+ const firstLocId = (s.location_ids || [])[0];
+ const city = locToCity[firstLocId];
+ s.cityId = city ? city.id : null;
+ s.cityName = city ? city.name : 'Unknown';
+ return s;
+ }).sort((a, b) => a.load - b.load);
+
if (this.servers.length === 0) {
app.$message.warning('No servers found for the selected country');
}
@@ -248,6 +282,12 @@
get: function () {
return app.templateSettings ? app.templateSettings.outbounds.findIndex((o) => o.tag.startsWith("nord-")) : -1;
}
+ },
+ filteredServers: function() {
+ if (!this.nordModal.cityId) {
+ return this.nordModal.servers;
+ }
+ return this.nordModal.servers.filter(s => s.cityId === this.nordModal.cityId);
}
}
});
diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml
index b1a622e7..77e35729 100644
--- a/web/translation/translate.en_US.toml
+++ b/web/translation/translate.en_US.toml
@@ -539,6 +539,8 @@
"accessToken" = "Access Token"
"country" = "Country"
"server" = "Server"
+"city" = "City"
+"allCities" = "All Cities"
"privateKey" = "Private Key"
"load" = "Load"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 724732a2..57bf7434 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -536,6 +536,8 @@
"accessToken" = "访问令牌"
"country" = "国家"
"server" = "服务器"
+"city" = "城市"
+"allCities" = "所有城市"
"privateKey" = "私钥"
"load" = "负载"