diff --git a/README.md b/README.md index 80fdb4c6..224e7e64 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install. # Install custom version -To install your desired version you can add the version to the end of install command. Example for ver `v2.0.0`: +To install your desired version you can add the version to the end of install command. Example for ver `v2.0.1`: ``` -bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.0.0 +bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.0.1 ``` # SSL diff --git a/config/version b/config/version index 359a5b95..10bf840e 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -2.0.0 \ No newline at end of file +2.0.1 \ No newline at end of file diff --git a/web/assets/css/custom.css b/web/assets/css/custom.css index ae2dbf16..308d24a6 100644 --- a/web/assets/css/custom.css +++ b/web/assets/css/custom.css @@ -55,7 +55,7 @@ style attribute { } .ant-table-tbody > tr > td, .ant-table-thead > tr > th { - padding: 12px 16px; + padding: 12px 8px; overflow-wrap: break-word; } .ant-table-thead > tr > th { @@ -93,7 +93,6 @@ style attribute { .ant-table-body { overflow-x: auto !important; } - .ant-card-hoverable { cursor: auto; cursor: pointer; @@ -133,6 +132,13 @@ style attribute { margin: 0.5rem; padding: 0.5rem; } + .ant-modal-body { + padding: 10px; + } + .ant-form-item-label { + line-height: 1.5; + padding: 8px 0 0; + } } .ant-layout-content { @@ -410,6 +416,10 @@ style attribute { background-color: white; } +.ant-form-item { + margin-bottom: 0; +} + .ant-setting-textarea { margin-top: 1.5rem; } @@ -802,12 +812,6 @@ style attribute { border-color: #fec093; } -.ant-modal-confirm-confirm .ant-modal-confirm-body>.anticon, .ant-modal-confirm-warning .ant-modal-confirm-body>.anticon, -.ant-alert-warning .ant-alert-icon, -.has-warning.has-feedback .ant-form-item-children-icon { - color: #f37b24; -} - .dark .has-warning .ant-input, .dark .has-warning .ant-input:hover { border-color: #784e1d; @@ -848,6 +852,13 @@ style attribute { user-select: none; } +.ant-calendar-date, +.ant-calendar-year-panel-year, +.ant-calendar-decade-panel-decade, +.ant-calendar-month-panel-month { + border-radius: 5px; +} + .ant-calendar-date:hover { background-color: rgb(232 244 242); } @@ -904,7 +915,7 @@ li.ant-select-dropdown-menu-item:empty:after { .ant-select-dropdown.ant-select-dropdown--multiple .ant-select-dropdown-menu-item-selected:hover .ant-select-selected-icon { - color: #3c89e8; + color: #008771; } .ant-select-selection:hover, .ant-input-number-focused, @@ -1046,18 +1057,6 @@ li.ant-select-dropdown-menu-item:empty:after { overflow: clip; } -.tag-of-wrap { - text-wrap: pretty; - overflow-wrap: anywhere; - max-width: 200px; -} - -.tag-of-wrap-l { - text-wrap: pretty; - overflow-wrap: anywhere; - max-width: 350px; -} - .ant-modal-body, .ant-collapse-content>.ant-collapse-content-box { overflow-x: auto; @@ -1095,3 +1094,8 @@ li.ant-select-dropdown-menu-item:empty:after { .dark .ant-select-dropdown-menu-item:hover:not(.ant-select-dropdown-menu-item-disabled) { background-color: #313f5a; } + +.ant-popover-inner-content { + max-height: 400px; + overflow-y: auto; +} diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 75d3b878..5aad52dd 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -476,7 +476,7 @@ class Outbound extends CommonClass { if(data.length !=2) return null; switch(data[0].toLowerCase()){ case Protocols.VMess: - return this.fromVmessLink(JSON.parse(atob(data[1]))); + return this.fromVmessLink(JSON.parse(Base64.decode(data[1]))); case Protocols.VLESS: case Protocols.Trojan: case 'ss': @@ -493,8 +493,8 @@ class Outbound extends CommonClass { if (network === 'tcp') { stream.tcp = new TcpStreamSettings( json.type, - json.host ? json.host.split(','): [], - json.path ? json.path.split(','): []); + json.host ?? '', + json.path ?? ''); } else if (network === 'kcp') { stream.kcp = new KcpStreamSettings(); stream.type = json.type; @@ -505,7 +505,7 @@ class Outbound extends CommonClass { stream.network = 'http' stream.http = new HttpStreamSettings( json.path, - json.host ? json.host.split(',') : []); + json.host); } else if (network === 'quic') { stream.quic = new QuicStreamSettings( json.host ? json.host : 'none', @@ -570,7 +570,7 @@ class Outbound extends CommonClass { let sni=url.searchParams.get('sni') ?? ''; let sid=url.searchParams.get('sid') ?? ''; let spx=url.searchParams.get('spx') ?? ''; - stream.tls = new RealityStreamSettings(pbk, fp, sni, sid, spx); + stream.reality = new RealityStreamSettings(pbk, fp, sni, sid, spx); } let data = link.split('?'); diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 9478312e..e0c8a912 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -602,7 +602,7 @@ class XtlsStreamSettings extends XrayCommonClass { alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1], settings=new XtlsStreamSettings.Settings()) { super(); - this.server = serverName; + this.sni = serverName; this.certs = certificates; this.alpn = alpn; this.settings = settings; @@ -636,7 +636,7 @@ class XtlsStreamSettings extends XrayCommonClass { toJson() { return { - serverName: this.server, + serverName: this.sni, certificates: XtlsStreamSettings.toJsonArray(this.certs), alpn: this.alpn, settings: this.settings, @@ -1081,7 +1081,7 @@ class Inbound extends XrayCommonClass { get serverName() { if (this.stream.isTls) return this.stream.tls.sni; - if (this.stream.isXtls) return this.stream.xtls.server; + if (this.stream.isXtls) return this.stream.xtls.sni; if (this.stream.isReality) return this.stream.reality.serverNames; return ""; } @@ -1326,8 +1326,8 @@ class Inbound extends XrayCommonClass { if(this.stream.xtls.settings.allowInsecure){ params.set("allowInsecure", "1"); } - if (!ObjectUtil.isEmpty(this.stream.xtls.server)){ - params.set("sni", this.stream.xtls.server); + if (!ObjectUtil.isEmpty(this.stream.xtls.sni)){ + params.set("sni", this.stream.xtls.sni); } params.set("flow", flow); } @@ -1533,8 +1533,8 @@ class Inbound extends XrayCommonClass { if(this.stream.xtls.settings.allowInsecure){ params.set("allowInsecure", "1"); } - if (this.stream.xtls.settings.serverName !== ''){ - params.set("sni", this.stream.xtls.settings.serverName); + if (!ObjectUtil.isEmpty(this.stream.xtls.sni)){ + params.set("sni", this.stream.xtls.sni); } params.set("flow", flow); } diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 4be7997d..668f426c 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -72,7 +72,7 @@ }); }, genSubLink(subID) { - return app.subSettings.subURI+subID+'?name='+subID; + return app.subSettings.subURI+subID; } }, updated() { diff --git a/web/html/login.html b/web/html/login.html index 900dd176..62be1478 100644 --- a/web/html/login.html +++ b/web/html/login.html @@ -27,6 +27,7 @@ text-align: center; align-items: center; justify-content: center; + width: 100%; } .title { font-size: 32px; @@ -58,24 +59,23 @@ .wave { opacity: 0.6; position: absolute; - bottom: 40%; - left: 50%; + top: 80%; + left: 60%; width: 6000px; height: 6000px; background-color: rgba(0, 135, 113, 0.08); margin-left: -3000px; - transform-origin: 50% 48%; - border-radius: 46%; + transform-origin: 50% 50%; pointer-events: none; - rotate: 125deg; + rotate: 115deg; } .wave2 { opacity: 0.4; - rotate: 70deg; + rotate: 105deg; } .wave3 { opacity: 0.2; - rotate: 90deg; + rotate: 62deg; } .under { background-color: #dbf5ed; @@ -92,12 +92,11 @@ .dark h1 { color: rgba(255, 255, 255, 0.85); } + .ant-form-item { + margin-bottom: 16px; + } + .ant-btn-primary-login { - color: #008771; - background-color: #e8f4f2; - border-color: #a2d3cb; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); - box-shadow: none; width: 100%; } .ant-btn-primary-login:focus, diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index e0295110..75e9bf6b 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -2,206 +2,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{ i18n "pages.client.method" }} - - - Random - Random+Prefix - Random+Prefix+Num - Random+Prefix+Num+Postfix - Prefix+Num+Postfix - - -
{{ i18n "pages.client.first" }} - - - -
{{ i18n "pages.client.last" }} - - - -
{{ i18n "pages.client.prefix" }} - - - -
{{ i18n "pages.client.postfix" }} - - - -
{{ i18n "pages.client.clientCount" }} - - - -
Flow - - - {{ i18n "none" }} - [[ key ]] - - -
Subscription - - - - - - - - -
Telegram ID - - - - - - - - -
- - - - - -
- - - - - {{ i18n "none" }} - [[ key ]] - - -
- {{ i18n "pages.inbounds.totalFlow" }}(GB) - - - - - - - - -
{{ i18n "pages.client.delayedStart" }} - - - -
{{ i18n "pages.client.expireDays" }} - - - -
- {{ i18n "pages.inbounds.expireDate" }} - - - - - - - - -
- {{ i18n "pages.client.renew" }} - - - - - - - - -
+ + + + Random + Random+Prefix + Random+Prefix+Num + Random+Prefix+Num+Postfix + Prefix+Num+Postfix + + + + + + + + + + + + + + + + + + + + {{ i18n "none" }} + [[ key ]] + + + + + {{ i18n "none" }} + [[ key ]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-{{end}} +{{end}} \ No newline at end of file diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html index 4ef8f2d6..f7f9d727 100644 --- a/web/html/xui/inbound_modal.html +++ b/web/html/xui/inbound_modal.html @@ -98,6 +98,11 @@ client.flow = ""; }); } + if ((this.inModal.inbound.protocol == Protocols.VLESS || this.inModal.inbound.protocol == Protocols.TROJAN) && !inModal.inbound.xtls) { + this.inModal.inbound.settings.vlesses.forEach(client => { + client.flow = ""; + }); + } }, SSMethodChange() { if (this.inModal.inbound.isSSMultiUser) { diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index f842d5a1..3d1bc625 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -43,6 +43,10 @@ 0%, 50%, 100% { transform: scale(1); opacity: 1; } 10% { transform: scale(1.5); opacity: .2; } } + .info-large-tag { + max-width: 200px; + overflow: hidden; + } @@ -423,7 +427,7 @@ :columns="isMobile ? innerMobileColumns : innerColumns" :data-source="getInboundClients(record)" :pagination=pagination(getInboundClients(record)) - style="margin: -12px -6px -13px;"> + style="margin: -12px 2px -13px;"> {{template "client_table"}} @@ -1306,4 +1310,4 @@ {{template "clientsBulkModal"}} - \ No newline at end of file + diff --git a/web/html/xui/index.html b/web/html/xui/index.html index 675b267d..9920dd90 100644 --- a/web/html/xui/index.html +++ b/web/html/xui/index.html @@ -102,7 +102,7 @@ - + {{ i18n "pages.index.stopXray" }} {{ i18n "pages.index.restartXray" }} @@ -125,7 +125,7 @@ - + @@ -146,7 +146,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -195,7 +195,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -231,7 +231,7 @@ - + diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index 05f21052..147ed5e1 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -3,7 +3,7 @@ {{template "head" .}} - + @@ -29,6 +29,10 @@ margin: 0; padding: 12px .5rem; } + .ant-table-thead > tr > th, + .ant-table-tbody > tr > td { + padding: 10px 0px; + } } .ant-tabs-bar { @@ -71,7 +75,7 @@ - + @@ -527,7 +531,7 @@ ips: { local: ["geoip:private"], cn: ["geoip:cn"], - ir: ["ext:geoip_IR.dat:ir","ext:geoip_IR.dat:arvancloud","ext:geoip_IR.dat:derakcloud","ext:geoip_IR.dat:iranserver","ext:geoip_IR.dat:parspack"], + ir: ["ext:geoip_IR.dat:ir"], ru: ["geoip:ru"], }, domains: { @@ -1398,4 +1402,4 @@ }); - \ No newline at end of file + diff --git a/web/html/xui/xray_reverse_modal.html b/web/html/xui/xray_reverse_modal.html index 0980ffb9..cb4e7037 100644 --- a/web/html/xui/xray_reverse_modal.html +++ b/web/html/xui/xray_reverse_modal.html @@ -2,77 +2,41 @@ - - - - - - - - - - - - - - + + + + [[ x ]] + + + + + + + +
{{ i18n "pages.xray.outbound.type" }} - - - [[ x ]] - - -
{{ i18n "pages.xray.outbound.tag" }} - - - -
{{ i18n "pages.xray.outbound.domain" }} - - - -
@@ -173,4 +137,4 @@ }); -{{end}} \ No newline at end of file +{{end}} diff --git a/web/html/xui/xray_rule_modal.html b/web/html/xui/xray_rule_modal.html index a5fd2e54..523a3d2c 100644 --- a/web/html/xui/xray_rule_modal.html +++ b/web/html/xui/xray_rule_modal.html @@ -2,149 +2,100 @@ - - - - - - - -
Domain Matcher - - + + + [[ dm ]] - -
Source IPs + + + + + + + + + + + + [[ x ]] + + + + + [[ x ]] + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + [[ tag ]] + + + + + [[ tag ]] + +
@@ -274,4 +225,4 @@ }); -{{end}} \ No newline at end of file +{{end}} diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index e39a5cc9..d363979b 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -57,7 +57,7 @@ "dashboard" = "Статус системы" "inbounds" = "Подключения" "settings" = "Настройки панели" -"xray" = "Xray Настройки" +"xray" = "Настройки Xray" "logout" = "Выход" "link" = "Прочее" @@ -268,7 +268,7 @@ "expireTimeDiff" = "Порог истечения срока сессии для уведомления" "expireTimeDiffDesc" = "Получение уведомления об истечении срока действия сессии до достижения порогового значения (значение: день)" "trafficDiff" = "Порог трафика для уведомления" -"trafficDiffDesc" = "Получение уведомления об исчерпании трафика до достижения порога (значение: Гб)" +"trafficDiffDesc" = "Получение уведомления об исчерпании трафика до достижения порога (значение: ГБ)" "tgNotifyCpu" = "Порог нагрузки на ЦП для уведомления" "tgNotifyCpuDesc" = "Получение уведомления, если нагрузка на ЦП превышает этот порог (значение: %)" "timeZone" = "Часовой пояс" @@ -298,7 +298,7 @@ "subURIDesc" = "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами" [pages.xray] -"title" = "Xray Настройки" +"title" = "Настройки Xray" "save" = "Сохранить настройки" "restart" = "Перезапустить рентген" "basicTemplate" = "Базовый шаблон" @@ -385,7 +385,7 @@ "source" = "Источник" "dest" = "Пункт назначения" "inbound" = "Входящий" -"outboun" = "Исходящий" +"outbound" = "Исходящий" "info" = "Информация" "add" = "Добавить правило" "edit" = "Редактировать правило" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index efbb81e3..f6b3164d 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -1,6 +1,6 @@ "username" = "Tên người dùng" "password" = "Mật khẩu" -"login" = "Đăng nhập..." +"login" = "Đăng nhập" "confirm" = "Xác nhận" "cancel" = "Hủy bỏ" "close" = "Đóng" @@ -36,10 +36,10 @@ "status" = "Trạng thái" "enabled" = "Đã kích hoạt" "disabled" = "Đã tắt" -"depleted" = "Đã cạn kiệt" -"depletingSoon" = "Đang cạn kiệt" +"depleted" = "Depleted" +"depletingSoon" = "Depleting..." "offline" = "Ngoại tuyến" -"online" = "Ngoại tuyến" +"online" = "Trực tuyến" "domainName" = "Tên miền" "monitor" = "Listening IP" "certificate" = "Chứng chỉ" @@ -47,9 +47,9 @@ "success" = "Thành công" "getVersion" = "Lấy phiên bản" "install" = "Cài đặt" -"clients" = "Khách hàng" +"clients" = "Các khách hàng" "usage" = "Sử dụng" -"secretToken" = "secretToken" +"secretToken" = "Mã bí mật" "remained" = "Còn lại" "security" = "Bảo vệ" @@ -369,9 +369,9 @@ "SpotifyWARPDesc" = "Thêm định tuyến cho Spotify qua WARP." "IRWARP" = "Định tuyến tên miền của Iran qua WARP." "IRWARPDesc" = "Thêm định tuyến cho các tên miền của Iran qua WARP." -"Inbounds" = "Vào" +"Inbounds" = "Đầu vào" "InboundsDesc" = "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể." -"Outbounds" = "Outbounds" +"Outbounds" = "Đầu ra" "OutboundsDesc" = "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này." "Routings" = "Quy tắc định tuyến" "RoutingsDesc" = "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!" @@ -385,7 +385,7 @@ "source" = "Nguồn" "dest" = "Đích" "inbound" = "Vào" -"outbound" = "Ra ngoài" +"outbound" = "Ra" "info" = "Thông tin" "add" = "Thêm quy tắc" "edit" = "Chỉnh sửa quy tắc" @@ -435,8 +435,8 @@ "days" = "Ngày" "hours" = "Giờ" "unknown" = "Không rõ" -"inbounds" = "Inbounds" -"clients" = "Khách hàng" +"inbounds" = "Vào" +"clients" = "Các khách hàng" [tgbot.commands] "unknown" = "❗ Lệnh không rõ" @@ -499,10 +499,10 @@ "confirmResetTraffic" = "✅ Xác Nhận Đặt Lại Lưu Lượng?" "confirmClearIps" = "✅ Xác Nhận Xóa Các IP?" "confirmRemoveTGUser" = "✅ Xác Nhận Xóa Người Dùng Telegram?" -"dbBackup" = "Tải Backup DB" +"dbBackup" = "Tải bản sao lưu cơ sở dữ liệu" "serverUsage" = "Sử Dụng Máy Chủ" -"getInbounds" = "Lấy Inbounds" -"depleteSoon" = "Sắp Cạn Kiệt" +"getInbounds" = "Lấy cổng vào" +"depleteSoon" = "Depleted Soon" "clientUsage" = "Lấy Sử Dụng" "commands" = "Lệnh" "refresh" = "🔄 Cập Nhật" @@ -512,13 +512,13 @@ "selectOneTGUser" = "👤 Chọn một người dùng telegram:" "resetTraffic" = "📈 Đặt Lại Lưu Lượng" "resetExpire" = "📅 Đặt Lại Ngày Hết Hạn" -"ipLog" = "🔢 Log IP" -"ipLimit" = "🔢 Giới Hạn IP" +"ipLog" = "🔢 Nhật ký địa chỉ IP" +"ipLimit" = "🔢 Giới Hạn địa chỉ IP" "setTGUser" = "👤 Đặt Người Dùng Telegram" "toggle" = "🔘 Bật / Tắt" -"custom" = "🔢 Phong tục" +"custom" = "🔢 Tùy chỉnh" "confirmNumber" = "✅ Xác nhận : {{ .Num }}" -"limitTraffic" = "🚧 Giới hạn giao thông" +"limitTraffic" = "🚧 Giới hạn lưu lượng" [tgbot.answers] "successfulOperation" = "✅ Thành công!" @@ -532,8 +532,8 @@ "setTrafficLimitSuccess" = "✅ {{ .Email }} : Đã lưu thành công giới hạn lưu lượng." "expireResetSuccess" = "✅ {{ .Email }} : Đặt Lại Ngày Hết Hạn Thành Công." "resetIpSuccess" = "✅ {{ .Email }} : Giới Hạn IP {{ .Count }} Đã Được Lưu Thành Công." -"clearIpSuccess" = "✅ {{ .Email }} : IPs Đã Được Xóa Thành Công." -"getIpLog" = "✅ {{ .Email }} : Lấy Log IP Thành Công." +"clearIpSuccess" = "✅ {{ .Email }} : IP Đã Được Xóa Thành Công." +"getIpLog" = "✅ {{ .Email }} : Lấy nhật ký IP Thành Công." "getUserInfo" = "✅ {{ .Email }} : Lấy Thông Tin Người Dùng Telegram Thành Công." "removedTGUserSuccess" = "✅ {{ .Email }} : Người Dùng Telegram Đã Được Xóa Thành Công." "enableSuccess" = "✅ {{ .Email }} : Đã Bật Thành Công." diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index ebf361d6..33c01e1c 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -378,7 +378,7 @@ "completeTemplate" = "全部" [pages.xray.rules] -"firsto" = "第一个" +"first" = "第一个" "last" = "最后" "up" = "向上" "down" = "向下" @@ -399,7 +399,7 @@ "tag" = "标签" "tagDesc" = "独特的标签" "address" = "地址" -"rreverse" = "反转" +"reverse" = "反转" "domain" = "域名" "type" = "类型" "bridge" = "桥"