mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-05 01:36:19 +00:00
Merge branch 'MHSanaei:main' into add-socks5-proxy-option-for-telegram-bot
This commit is contained in:
commit
0899740e94
9 changed files with 115 additions and 55 deletions
|
@ -680,7 +680,7 @@ style attribute {
|
|||
.dark .ant-table-row-expand-icon {
|
||||
color: #fff;
|
||||
background-color: #fff0;
|
||||
border-color: #9ea2a8;
|
||||
border-color: rgb(255 255 255 / 20%);
|
||||
}
|
||||
|
||||
.dark .ant-table-row-expand-icon:hover {
|
||||
|
@ -1099,3 +1099,16 @@ li.ant-select-dropdown-menu-item:empty:after {
|
|||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ant-table-row-expand-icon {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.qr-bg {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
padding: 0.5rem;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ func (s *AllSetting) CheckValid() error {
|
|||
return common.NewError("Sub port is not a valid port:", s.SubPort)
|
||||
}
|
||||
|
||||
if s.SubPort == s.WebPort {
|
||||
return common.NewError("Sub and Web could not use same port:", s.SubPort)
|
||||
if (s.SubPort == s.WebPort) && (s.WebListen == s.SubListen) {
|
||||
return common.NewError("Sub and Web could not use same ip:port, ", s.SubListen, ":", s.SubPort, " & ", s.WebListen, ":", s.WebPort)
|
||||
}
|
||||
|
||||
if s.WebCertFile != "" || s.WebKeyFile != "" {
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
</a-tag>
|
||||
<template v-if="app.subSettings.enable && qrModal.subId">
|
||||
<a-divider>Subscription</a-divider>
|
||||
<canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas>
|
||||
<div class="qr-bg"><canvas @click="copyToClipboard('qrCode-sub',genSubLink(qrModal.client.subId))" id="qrCode-sub" style="width: 100%; height: 100%;"></canvas></div>
|
||||
</template>
|
||||
<a-divider>{{ i18n "pages.inbounds.client" }}</a-divider>
|
||||
<template v-for="(row, index) in qrModal.qrcodes">
|
||||
<a-tag color="green" style="margin: 10px 0; display: block; text-align: center;">[[ row.remark ]]</a-tag>
|
||||
<canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas>
|
||||
<div class="qr-bg"><canvas @click="copyToClipboard('qrCode-'+index, row.link)" :id="'qrCode-'+index" style="width: 100%; height: 100%;"></canvas></div>
|
||||
</template>
|
||||
</a-modal>
|
||||
|
||||
|
@ -87,4 +87,4 @@
|
|||
});
|
||||
|
||||
</script>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -56,35 +56,12 @@
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.wave {
|
||||
opacity: 0.6;
|
||||
position: absolute;
|
||||
top: 80%;
|
||||
left: 60%;
|
||||
width: 6000px;
|
||||
height: 6000px;
|
||||
background-color: rgba(0, 135, 113, 0.08);
|
||||
margin-left: -3000px;
|
||||
transform-origin: 50% 50%;
|
||||
pointer-events: none;
|
||||
rotate: 115deg;
|
||||
}
|
||||
.wave2 {
|
||||
opacity: 0.4;
|
||||
rotate: 105deg;
|
||||
}
|
||||
.wave3 {
|
||||
opacity: 0.2;
|
||||
rotate: 62deg;
|
||||
}
|
||||
.under {
|
||||
background-color: #dbf5ed;
|
||||
}
|
||||
.dark .wave {
|
||||
background: rgb(10 117 87 / 20%);
|
||||
background-color: #c7ebe2;
|
||||
z-index: 0;
|
||||
}
|
||||
.dark .under {
|
||||
background-color: #101828;
|
||||
background-color: #0f2d32;
|
||||
}
|
||||
.dark #login {
|
||||
background-color: #151f31;
|
||||
|
@ -95,7 +72,6 @@
|
|||
.ant-form-item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.ant-btn-primary-login {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -147,8 +123,9 @@
|
|||
background-origin: border-box;
|
||||
background-clip: padding-box, border-box;
|
||||
background-size: 300%;
|
||||
transition: all 0.5s ease;
|
||||
transition: all 0.3s cubic-bezier(.645,.045,.355,1);
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
.dark .wave-btn-bg:hover {animation: wave-btn-tara 4s ease infinite;}
|
||||
.dark .wave-btn-bg-cl {
|
||||
|
@ -206,14 +183,84 @@
|
|||
background-position-x: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.waves-header {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
background-color: #dbf5ed;
|
||||
color: white;
|
||||
z-index: -1;
|
||||
}
|
||||
.dark .waves-header {
|
||||
background-color: #101828;
|
||||
}
|
||||
.waves-inner-header {
|
||||
height: 50vh;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.waves {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 15vh;
|
||||
margin-bottom: -5px; /*Fix for safari gap*/
|
||||
min-height: 100px;
|
||||
max-height: 150px;
|
||||
}
|
||||
.parallax > use {
|
||||
animation: move-forever 25s cubic-bezier(0.55, 0.5, 0.45, 0.5) infinite;
|
||||
}
|
||||
.dark .parallax > use {
|
||||
fill: rgb(10 117 87 / 20%);
|
||||
}
|
||||
.parallax > use:nth-child(1) {
|
||||
animation-delay: -2s;
|
||||
animation-duration: 7s;
|
||||
opacity: 0.2;
|
||||
}
|
||||
.parallax > use:nth-child(2) {
|
||||
animation-delay: -3s;
|
||||
animation-duration: 10s;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.parallax > use:nth-child(3) {
|
||||
animation-delay: -4s;
|
||||
animation-duration: 13s;
|
||||
opacity: 0.6;
|
||||
}
|
||||
@keyframes move-forever {
|
||||
0% {
|
||||
transform: translate3d(-90px, 0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(85px, 0, 0);
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.waves {
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||
<transition name="list" appear>
|
||||
<a-layout-content class="under" style="min-height: 0;">
|
||||
<div class='wave'></div>
|
||||
<div class='wave wave2'></div>
|
||||
<div class='wave wave3'></div>
|
||||
<div class="waves-header">
|
||||
<div class="waves-inner-header"></div>
|
||||
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
|
||||
<defs>
|
||||
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
|
||||
</defs>
|
||||
<g class="parallax">
|
||||
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(0, 135, 113, 0.08)" />
|
||||
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(0, 135, 113, 0.08)" />
|
||||
<use xlink:href="#gentle-wave" x="48" y="7" fill="rgba(0, 135, 113, 0.08)" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<a-row type="flex" justify="center" align="middle" style="height: 100%; overflow: auto;">
|
||||
<a-col :xs="22" :sm="20" :md="14" :lg="10" :xl="8" :xxl="6" id="login" style="margin: 3rem 0;">
|
||||
<a-row type="flex" justify="center">
|
||||
|
@ -243,7 +290,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-row justify="center" class="centered">
|
||||
<div class="wave-btn-bg wave-btn-bg-cl">
|
||||
<div class="wave-btn-bg wave-btn-bg-cl" :style="loading ? { width: '54px' } : { display: 'inline-block' }">
|
||||
<a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login" :icon="loading ? 'poweroff' : undefined"
|
||||
:style="loading ? { width: '50px' } : { display: 'inline-block' }">
|
||||
[[ loading ? '' : '{{ i18n "login" }}' ]]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{{define "form/streamGRPC"}}
|
||||
<a-form :colon="false" :label-col="{ md: {span:6} }" :wrapper-col="{ md: {span:14} }">
|
||||
<a-form-item label="Service Name">
|
||||
<a-input v-model.trim="inbound.stream.grpc.serviceName" style="width: 250px;"></a-input>
|
||||
<a-input v-model.trim="inbound.stream.grpc.serviceName"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="MultiMode">
|
||||
<a-switch v-model="inbound.stream.grpc.multiMode"></a-switch>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -74,10 +74,10 @@
|
|||
</a-form-item>
|
||||
<template v-if="cert.useFile">
|
||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>
|
||||
<a-input v-model.trim="cert.certFile" style="width:250px;"></a-input>
|
||||
<a-input v-model.trim="cert.certFile"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.keyPath" }}'>
|
||||
<a-input v-model.trim="cert.keyFile" style="width:250px;"></a-input>
|
||||
<a-input v-model.trim="cert.keyFile"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label=" ">
|
||||
<a-button type="primary" icon="import" @click="setDefaultCertData(index)">{{ i18n
|
||||
|
@ -86,10 +86,10 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyContent" }}'>
|
||||
<a-input type="textarea" :rows="3" style="width:250px;" v-model="cert.cert"></a-input>
|
||||
<a-input type="textarea" :rows="3" v-model="cert.cert"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.keyContent" }}'>
|
||||
<a-input type="textarea" :rows="3" style="width:250px;" v-model="cert.key"></a-input>
|
||||
<a-input type="textarea" :rows="3" v-model="cert.key"></a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<a-form-item label='ocspStapling'>
|
||||
|
@ -125,10 +125,10 @@
|
|||
</a-form-item>
|
||||
<template v-if="cert.useFile">
|
||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>
|
||||
<a-input v-model.trim="cert.certFile" style="width:250px;"></a-input>
|
||||
<a-input v-model.trim="cert.certFile"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.keyPath" }}'>
|
||||
<a-input v-model.trim="cert.keyFile" style="width:250px;"></a-input>
|
||||
<a-input v-model.trim="cert.keyFile"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label=" ">
|
||||
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">{{ i18n
|
||||
|
@ -137,10 +137,10 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyContent" }}'>
|
||||
<a-input type="textarea" :rows="3" style="width:250px;" v-model="cert.cert"></a-input>
|
||||
<a-input type="textarea" :rows="3" v-model="cert.cert"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.keyContent" }}'>
|
||||
<a-input type="textarea" :rows="3" style="width:250px;" v-model="cert.key"></a-input>
|
||||
<a-input type="textarea" :rows="3" v-model="cert.key"></a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
@ -175,10 +175,10 @@
|
|||
<a-icon @click="inbound.stream.reality.shortIds = RandomUtil.randomShortId()" type="sync"> </a-icon>
|
||||
</a-icon>
|
||||
</template>
|
||||
<a-input v-model.trim="inbound.stream.reality.shortIds" style="width:250px"></a-input>
|
||||
<a-input v-model.trim="inbound.stream.reality.shortIds"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='SpiderX'>
|
||||
<a-input v-model.trim="inbound.stream.reality.settings.spiderX" style="width:250px"></a-input>
|
||||
<a-input v-model.trim="inbound.stream.reality.settings.spiderX"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='Private Key'>
|
||||
<a-input v-model.trim="inbound.stream.reality.privateKey"></a-input>
|
||||
|
@ -191,4 +191,4 @@
|
|||
</a-form-item>
|
||||
</template>
|
||||
</a-form>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -427,7 +427,7 @@
|
|||
:columns="isMobile ? innerMobileColumns : innerColumns"
|
||||
:data-source="getInboundClients(record)"
|
||||
:pagination=pagination(getInboundClients(record))
|
||||
style="margin: -12px 2px -13px;">
|
||||
:style="isMobile ? 'margin: -12px 2px -13px;' : 'margin: -12px 22px -13px;'">
|
||||
{{template "client_table"}}
|
||||
</a-table>
|
||||
</template>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item label='Network'>
|
||||
<a-select v-model="ruleModal.rule.network" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option v-for="x in ['','tcp','tdp','tcp,udp']" :value="x">[[ x ]]</a-select-option>
|
||||
<a-select-option v-for="x in ['','TCP','UDP','TCP,UDP']" :value="x">[[ x ]]</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label='Protocol'>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
"hard" = "Жесткий диск"
|
||||
"xrayStatus" = "Статус"
|
||||
"stopXray" = "Остановить Xray"
|
||||
"restartXray" = "Рестарт Xray"
|
||||
"restartXray" = "Перезапустить Xray"
|
||||
"xraySwitch" = "Переключить версию"
|
||||
"xraySwitchClick" = "Выберите желаемую версию"
|
||||
"xraySwitchClickDesk" = "Выбирайте внимательно, так как старые версии могут быть несовместимы с текущими конфигурациями"
|
||||
|
@ -300,7 +300,7 @@
|
|||
[pages.xray]
|
||||
"title" = "Настройки Xray"
|
||||
"save" = "Сохранить настройки"
|
||||
"restart" = "Перезапустить рентген"
|
||||
"restart" = "Перезапустить Xray"
|
||||
"basicTemplate" = "Базовый шаблон"
|
||||
"advancedTemplate" = "Расширенный шаблон"
|
||||
"generalConfigs" = "Основные настройки"
|
||||
|
|
Loading…
Reference in a new issue