mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-19 21:42:24 +00:00
<tr> <td> instead of <a-form-item>
convert the form structure to use <tr> and <td> instead of <a-form-item>,
This commit is contained in:
parent
2088a4f815
commit
0f1f3d8439
15 changed files with 1285 additions and 733 deletions
|
@ -1,134 +1,207 @@
|
||||||
{{define "clientsBulkModal"}}
|
{{define "clientsBulkModal"}}
|
||||||
<a-modal id="client-bulk-modal" v-model="clientsBulkModal.visible" :title="clientsBulkModal.title" @ok="clientsBulkModal.ok"
|
<a-modal id="client-bulk-modal" v-model="clientsBulkModal.visible" :title="clientsBulkModal.title"
|
||||||
:confirm-loading="clientsBulkModal.confirmLoading" :closable="true" :mask-closable="false"
|
@ok="clientsBulkModal.ok" :confirm-loading="clientsBulkModal.confirmLoading" :closable="true" :mask-closable="false"
|
||||||
:class="themeSwitcher.currentTheme"
|
:ok-text="clientsBulkModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
|
||||||
:ok-text="clientsBulkModal.okText" cancel-text='{{ i18n "close" }}'>
|
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "pages.client.method" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-select v-model="clientsBulkModal.emailMethod" buttonStyle="solid" style="width: 350px" :dropdown-class-name="themeSwitcher.currentTheme">
|
<tr>
|
||||||
<a-select-option :value="0">Random</a-select-option>
|
<td>{{ i18n "pages.client.method" }}</td>
|
||||||
<a-select-option :value="1">Random+Prefix</a-select-option>
|
<td>
|
||||||
<a-select-option :value="2">Random+Prefix+Num</a-select-option>
|
<a-form-item>
|
||||||
<a-select-option :value="3">Random+Prefix+Num+Postfix</a-select-option>
|
<a-select v-model="clientsBulkModal.emailMethod" buttonStyle="solid" style="width: 250px"
|
||||||
<a-select-option :value="4">Prefix+Num+Postfix [ BE CAREFUL! ]</a-select-option>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
</a-select>
|
<a-select-option :value="0">Random</a-select-option>
|
||||||
</a-form-item><br />
|
<a-select-option :value="1">Random+Prefix</a-select-option>
|
||||||
<a-form-item v-if="clientsBulkModal.emailMethod>1">
|
<a-select-option :value="2">Random+Prefix+Num</a-select-option>
|
||||||
<span slot="label">{{ i18n "pages.client.first" }}</span>
|
<a-select-option :value="3">Random+Prefix+Num+Postfix</a-select-option>
|
||||||
<a-input-number v-model="clientsBulkModal.firstNum" :min="1"></a-input-number>
|
<a-select-option :value="4">Prefix+Num+Postfix</a-select-option>
|
||||||
</a-form-item>
|
</a-select>
|
||||||
<a-form-item v-if="clientsBulkModal.emailMethod>1">
|
</a-form-item>
|
||||||
<span slot="label">{{ i18n "pages.client.last" }}</span>
|
</td>
|
||||||
<a-input-number v-model="clientsBulkModal.lastNum" :min="clientsBulkModal.firstNum"></a-input-number>
|
</tr>
|
||||||
</a-form-item>
|
<tr v-if="clientsBulkModal.emailMethod>1">
|
||||||
<a-form-item v-if="clientsBulkModal.emailMethod>0">
|
<td>{{ i18n "pages.client.first" }}</td>
|
||||||
<span slot="label">{{ i18n "pages.client.prefix" }}</span>
|
<td>
|
||||||
<a-input v-model="clientsBulkModal.emailPrefix" style="width: 120px"></a-input>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input-number v-model="clientsBulkModal.firstNum" :min="1"></a-input-number>
|
||||||
<a-form-item v-if="clientsBulkModal.emailMethod>2">
|
</a-form-item>
|
||||||
<span slot="label">{{ i18n "pages.client.postfix" }}</span>
|
</td>
|
||||||
<a-input v-model="clientsBulkModal.emailPostfix" style="width: 120px"></a-input>
|
</tr>
|
||||||
</a-form-item>
|
<tr v-if="clientsBulkModal.emailMethod>1">
|
||||||
<a-form-item v-if="clientsBulkModal.emailMethod < 2">
|
<td>{{ i18n "pages.client.last" }}</td>
|
||||||
<span slot="label">{{ i18n "pages.client.clientCount" }}</span>
|
<td>
|
||||||
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input-number v-model="clientsBulkModal.lastNum"
|
||||||
<a-form-item v-if="app.subSettings.enable">
|
:min="clientsBulkModal.firstNum"></a-input-number>
|
||||||
<span slot="label">
|
</a-form-item>
|
||||||
Subscription
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="clientsBulkModal.emailMethod>0">
|
||||||
|
<td>{{ i18n "pages.client.prefix" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model="clientsBulkModal.emailPrefix" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="clientsBulkModal.emailMethod>2">
|
||||||
|
<td>{{ i18n "pages.client.postfix" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model="clientsBulkModal.emailPostfix" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="clientsBulkModal.emailMethod < 2">
|
||||||
|
<td>{{ i18n "pages.client.clientCount" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="clientsBulkModal.inbound.canEnableTlsFlow()">
|
||||||
|
<td>Flow</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="clientsBulkModal.flow" style="width: 250px"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
||||||
|
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="app.subSettings.enable">
|
||||||
|
<td>Subscription
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<span>{{ i18n "pages.inbounds.subscriptionDesc" }}</span>
|
<span>{{ i18n "pages.inbounds.subscriptionDesc" }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<a-icon @click="client.subId = RandomUtil.randomLowerAndNum(16)" type="sync"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="clientsBulkModal.subId" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="app.tgBotEnable">
|
||||||
|
<td>Telegram ID
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.telegramDesc" }}</span>
|
||||||
|
</template>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</td>
|
||||||
<a-input v-model.trim="clientsBulkModal.subId"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
<a-form-item v-if="app.tgBotEnable">
|
<a-input v-model.trim="clientsBulkModal.tgId" style="width: 250px"></a-input>
|
||||||
<span slot="label">
|
</a-form-item>
|
||||||
Telegram ID
|
</td>
|
||||||
<a-tooltip>
|
</tr>
|
||||||
<template slot="title">
|
<tr>
|
||||||
<span>{{ i18n "pages.inbounds.telegramDesc" }}</span>
|
<td>
|
||||||
</template>
|
<label>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<span>{{ i18n "pages.inbounds.IPLimit" }}</span>
|
||||||
</a-tooltip>
|
<a-tooltip>
|
||||||
</span>
|
<template slot="title">
|
||||||
<a-input v-model.trim="clientsBulkModal.tgId"></a-input>
|
<span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span>
|
||||||
</a-form-item>
|
</template>
|
||||||
<br>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
<a-form-item>
|
</a-tooltip>
|
||||||
<span slot="label">
|
</label>
|
||||||
<span>{{ i18n "pages.inbounds.IPLimit" }}</span>
|
</td>
|
||||||
<a-tooltip>
|
<td>
|
||||||
<template slot="title">
|
<a-form-item>
|
||||||
<span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span>
|
<a-input-number v-model="clientsBulkModal.limitIp" min="0"></a-input-number>
|
||||||
</template>
|
</a-form-item>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
</td>
|
||||||
</a-tooltip>
|
</tr>
|
||||||
</span>
|
<tr>
|
||||||
<a-input-number v-model="clientsBulkModal.limitIp" min="0"></a-input-number>
|
<td v-if="clientsBulkModal.inbound.xtls">
|
||||||
</a-form-item>
|
<label>Flow</label>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item v-if="clientsBulkModal.inbound.xtls" label="Flow">
|
<td v-if="clientsBulkModal.inbound.xtls">
|
||||||
<a-select v-model="clientsBulkModal.flow" style="width: 200px" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-form-item>
|
||||||
<a-select-option value="">{{ i18n "none" }}</a-select-option>
|
<a-select v-model="clientsBulkModal.flow" style="width: 200px"
|
||||||
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
</a-select>
|
<a-select-option value="">{{ i18n "none" }}</a-select-option>
|
||||||
</a-form-item>
|
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||||
<a-form-item v-if="clientsBulkModal.inbound.canEnableTlsFlow()" label="Flow" layout="inline">
|
</a-select>
|
||||||
<a-select v-model="clientsBulkModal.flow" style="width: 200px" :dropdown-class-name="themeSwitcher.currentTheme">
|
</a-form-item>
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
</td>
|
||||||
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
</tr>
|
||||||
</a-select>
|
<tr>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item>
|
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
|
||||||
<span slot="label">
|
<a-tooltip>
|
||||||
<span>{{ i18n "pages.inbounds.totalFlow" }}</span> (GB)
|
<template slot="title">
|
||||||
<a-tooltip>
|
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
||||||
<template slot="title">
|
</template>
|
||||||
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
</template>
|
</a-tooltip>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
</td>
|
||||||
</a-tooltip>
|
<td>
|
||||||
</span>
|
<a-form-item>
|
||||||
<a-input-number v-model="clientsBulkModal.totalGB" :min="0"></a-input-number>
|
<a-input-number v-model="clientsBulkModal.totalGB" :min="0"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item label='{{ i18n "pages.client.delayedStart" }}'>
|
</tr>
|
||||||
<a-switch v-model="clientsBulkModal.delayedStart" @click="clientsBulkModal.expiryTime=0"></a-switch>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "pages.client.delayedStart" }}</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label='{{ i18n "pages.client.expireDays" }}' v-if="clientsBulkModal.delayedStart">
|
<a-form-item>
|
||||||
<a-input-number v-model="delayedExpireDays" :min="0"></a-input-number>
|
<a-switch v-model="clientsBulkModal.delayedStart"
|
||||||
</a-form-item>
|
@click="clientsBulkModal.expiryTime=0"></a-switch>
|
||||||
<a-form-item v-else>
|
</a-form-item>
|
||||||
<span slot="label">
|
</td>
|
||||||
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
</tr>
|
||||||
<a-tooltip>
|
<tr v-if="clientsBulkModal.delayedStart">
|
||||||
<template slot="title">
|
<td>{{ i18n "pages.client.expireDays" }}</td>
|
||||||
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
<td>
|
||||||
</template>
|
<a-form-item>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<a-input-number v-model.number="delayedExpireDays" :min="0"></a-input-number>
|
||||||
</a-tooltip>
|
</a-form-item>
|
||||||
</span>
|
</td>
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
</tr>
|
||||||
:dropdown-class-name="themeSwitcher.darkCardClass"
|
<tr v-else>
|
||||||
v-model="clientsBulkModal.expiryTime" style="width: 300px;"></a-date-picker>
|
<td>
|
||||||
</a-form-item>
|
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
||||||
<a-form-item v-if="clientsBulkModal.expiryTime != 0">
|
<a-tooltip>
|
||||||
<span slot="label">
|
<template slot="title">
|
||||||
<span>{{ i18n "pages.client.renew" }}</span>
|
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
||||||
<a-tooltip>
|
</template>
|
||||||
<template slot="title">
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
<span>{{ i18n "pages.client.renewDesc" }}</span>
|
</a-tooltip>
|
||||||
</template>
|
</td>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<td>
|
||||||
</a-tooltip>
|
<a-form-item>
|
||||||
</span>
|
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
<a-input-number v-model.number="clientsBulkModal.reset" :min="0"></a-input-number>
|
:dropdown-class-name="themeSwitcher.currentTheme" v-model="clientsBulkModal.expiryTime"
|
||||||
</a-form-item>
|
style="width: 250px;"></a-date-picker>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="clientsBulkModal.expiryTime != 0">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.client.renew" }}</span>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.client.renewDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="clientsBulkModal.reset" :min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,168 +1,223 @@
|
||||||
{{define "form/client"}}
|
{{define "form/client"}}
|
||||||
<a-form layout="inline" v-if="client">
|
<a-form layout="inline" v-if="client">
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.enable" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-switch v-model="client.enable"></a-switch>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "pages.inbounds.enable" }}</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<span slot="label">
|
<a-switch v-model="client.enable"></a-switch>
|
||||||
<span>{{ i18n "pages.inbounds.email" }}</span>
|
</a-form-item>
|
||||||
<a-tooltip>
|
</td>
|
||||||
<template slot="title">
|
</tr>
|
||||||
<span>{{ i18n "pages.inbounds.emailDesc" }}</span>
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.email" }}</span>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.emailDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="sync" @click="client.email = RandomUtil.randomLowerAndNum(9)"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="client.email" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS">
|
||||||
|
<td>password
|
||||||
|
<a-icon v-if="inbound.protocol === Protocols.SHADOWSOCKS" @click="client.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon>
|
||||||
|
<a-icon v-if="inbound.protocol === Protocols.TROJAN" @click="client.password = RandomUtil.randomSeq(10)" type="sync"> </a-icon>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="client.password" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="inbound.protocol === Protocols.VMESS || inbound.protocol === Protocols.VLESS">
|
||||||
|
<td>ID <a-icon @click="client.id = RandomUtil.randomUUID()" type="sync"></a-icon></td>
|
||||||
|
<td>
|
||||||
|
<a-input v-model.trim="client.id" style="width: 300px;"></a-input>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="client.email && app.subSettings.enable">
|
||||||
|
<td>Subscription</td>
|
||||||
|
<td>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.subscriptionDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon @click="client.subId = RandomUtil.randomLowerAndNum(16)" type="sync"> </a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="client.subId" style="width: 150px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="client.email && app.tgBotEnable">
|
||||||
|
<td>Telegram ID</td>
|
||||||
|
<td>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.telegramDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="client.tgId"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.IPLimit" }}</span>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model="client.limitIp" min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="client.email && client.limitIp > 0 && isEdit">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.IPLimitlog" }}</span>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.IPLimitlogDesc" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.IPLimitlogclear" }}</span>
|
||||||
|
</template>
|
||||||
|
<span style="color: #FF4D4F">
|
||||||
|
<a-icon type="delete" @click="clearDBClientIps(client.email)"></a-icon>
|
||||||
|
</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form layout="block">
|
||||||
|
<a-textarea id="clientIPs" readonly @click="getDBClientIps(client.email)"
|
||||||
|
placeholder="Click To Get IPs" :auto-size="{ minRows: 5, maxRows: 10 }">
|
||||||
|
</a-textarea>
|
||||||
|
</a-form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="inbound.xtls">
|
||||||
|
<td>Flow</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="client.flow" style="width: 200px"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="">{{ i18n "none" }}</a-select-option>
|
||||||
|
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-else-if="inbound.canEnableTlsFlow()">
|
||||||
|
<td>Flow</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="client.flow" style="width: 200px"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
||||||
|
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.totalFlow" }}</span> (GB)
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model="client._totalGB" :min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
<template v-if="isEdit && clientStats">
|
||||||
|
<br>
|
||||||
|
<span> {{ i18n "usage" }}:</span>
|
||||||
|
<a-tag :color="clientUsageColor(clientStats, app.trafficDiff)">
|
||||||
|
[[ sizeFormat(clientStats.up) ]] /
|
||||||
|
[[ sizeFormat(clientStats.down) ]]
|
||||||
|
([[ sizeFormat(clientStats.up + clientStats.down) ]])
|
||||||
|
</a-tag>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">{{ i18n "pages.inbounds.resetTraffic" }}</template>
|
||||||
|
<a-icon type="retweet"
|
||||||
|
@click="resetClientTraffic(client.email,clientStats.inboundId,$event.target)"
|
||||||
|
v-if="client.email.length > 0"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</a-tooltip>
|
</td>
|
||||||
</span>
|
</tr>
|
||||||
<a-icon @click="client.email = RandomUtil.randomLowerAndNum(8)" type="sync"> </a-icon>
|
<tr>
|
||||||
<a-input v-model.trim="client.email" style="width: 200px;"></a-input>
|
<td>{{ i18n "pages.client.delayedStart" }}</td>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item label="Password" v-if="inbound.protocol === Protocols.TROJAN || inbound.protocol === Protocols.SHADOWSOCKS">
|
<a-form-item>
|
||||||
<a-icon v-if="inbound.protocol === Protocols.SHADOWSOCKS" @click="client.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon>
|
<a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch>
|
||||||
<a-icon v-if="inbound.protocol === Protocols.TROJAN" @click="client.password = RandomUtil.randomSeq(10)" type="sync"> </a-icon>
|
</a-form-item>
|
||||||
<a-input v-model.trim="client.password" style="width: 300px;"></a-input>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<br>
|
<tr v-if="delayedStart">
|
||||||
<a-form-item label="ID" v-if="inbound.protocol === Protocols.VMESS || inbound.protocol === Protocols.VLESS">
|
<td>{{ i18n "pages.client.expireDays" }}</td>
|
||||||
<a-icon @click="client.id = RandomUtil.randomUUID()" type="sync"> </a-icon>
|
<td>
|
||||||
<a-input v-model.trim="client.id" style="width: 300px;"></a-input>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input-number v-model="delayedExpireDays" :min="0"></a-input-number>
|
||||||
<a-form-item v-if="client.email && app.subSettings.enable">
|
</a-form-item>
|
||||||
<span slot="label">
|
</td>
|
||||||
Subscription
|
</tr>
|
||||||
<a-tooltip>
|
<tr v-else>
|
||||||
<template slot="title">
|
<td>
|
||||||
<span>{{ i18n "pages.inbounds.subscriptionDesc" }}</span>
|
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
||||||
</template>
|
<a-tooltip>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<template slot="title">
|
||||||
</a-tooltip>
|
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
||||||
</span>
|
</template>
|
||||||
<a-icon @click="client.subId = RandomUtil.randomLowerAndNum(16)" type="sync"> </a-icon>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
<a-input v-model.trim="client.subId" style="width: 150px;"></a-input>
|
</a-tooltip>
|
||||||
</a-form-item>
|
</td>
|
||||||
<a-form-item v-if="client.email && app.tgBotEnable" >
|
<td>
|
||||||
<span slot="label">
|
<a-form-item>
|
||||||
Telegram ID
|
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
<a-tooltip>
|
:dropdown-class-name="themeSwitcher.currentTheme" v-model="client._expiryTime"
|
||||||
<template slot="title">
|
style="width: 170px;"></a-date-picker>
|
||||||
<span>{{ i18n "pages.inbounds.telegramDesc" }}</span>
|
<a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag>
|
||||||
</template>
|
</a-form-item>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
</td>
|
||||||
</a-tooltip>
|
</tr>
|
||||||
</span>
|
<tr v-if="client.expiryTime != 0">
|
||||||
<a-input v-model.trim="client.tgId"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<span>{{ i18n "pages.client.renew" }}</span>
|
||||||
<a-form-item>
|
<a-tooltip>
|
||||||
<span slot="label">
|
<template slot="title">
|
||||||
<span>{{ i18n "pages.inbounds.IPLimit" }}</span>
|
<span>{{ i18n "pages.client.renewDesc" }}</span>
|
||||||
<a-tooltip>
|
</template>
|
||||||
<template slot="title">
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
<span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span>
|
</a-tooltip>
|
||||||
</template>
|
</td>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<td>
|
||||||
</a-tooltip>
|
<a-form-item>
|
||||||
</span>
|
<a-input-number v-model.number="client.reset" :min="0"></a-input-number>
|
||||||
<a-input-number v-model="client.limitIp" min="0"></a-input-number>
|
</a-form-item>
|
||||||
</a-form-item>
|
</td>
|
||||||
<a-form-item v-if="client.email && client.limitIp > 0 && isEdit">
|
</tr>
|
||||||
<span slot="label">
|
</table>
|
||||||
<span>{{ i18n "pages.inbounds.IPLimitlog" }}</span>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.inbounds.IPLimitlogDesc" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.inbounds.IPLimitlogclear" }}</span>
|
|
||||||
</template>
|
|
||||||
<span style="color: #FF4D4F">
|
|
||||||
<a-icon type="delete" @click="clearDBClientIps(client.email)"></a-icon>
|
|
||||||
</span>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
<a-form layout="block">
|
|
||||||
<a-textarea id="clientIPs" readonly
|
|
||||||
@click="getDBClientIps(client.email)"
|
|
||||||
placeholder="Click To Get IPs"
|
|
||||||
:auto-size="{ minRows: 5, maxRows: 10 }"
|
|
||||||
>
|
|
||||||
</a-textarea>
|
|
||||||
</a-form>
|
|
||||||
</a-form-item>
|
|
||||||
<br>
|
|
||||||
<a-form-item v-if="inbound.xtls" label="Flow">
|
|
||||||
<a-select v-model="client.flow" style="width: 200px" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="">{{ i18n "none" }}</a-select-option>
|
|
||||||
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-else-if="inbound.canEnableTlsFlow()" label="Flow">
|
|
||||||
<a-select v-model="client.flow" style="width: 200px" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
|
||||||
<a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item>
|
|
||||||
<span slot="label">
|
|
||||||
<span>{{ i18n "pages.inbounds.totalFlow" }}</span> (GB)
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
<a-input-number v-model="client._totalGB" :min="0"></a-input-number>
|
|
||||||
<template v-if="isEdit && clientStats">
|
|
||||||
<br>
|
|
||||||
<span> {{ i18n "usage" }}:</span>
|
|
||||||
<a-tag :color="clientUsageColor(clientStats, app.trafficDiff)">
|
|
||||||
[[ sizeFormat(clientStats.up) ]] /
|
|
||||||
[[ sizeFormat(clientStats.down) ]]
|
|
||||||
([[ sizeFormat(clientStats.up + clientStats.down) ]])
|
|
||||||
</a-tag>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">{{ i18n "pages.inbounds.resetTraffic" }}</template>
|
|
||||||
<a-icon type="retweet" @click="resetClientTraffic(client.email,clientStats.inboundId,$event.target)"
|
|
||||||
v-if="client.email.length > 0"></a-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
</template>
|
|
||||||
</a-form-item>
|
|
||||||
<br>
|
|
||||||
<a-form-item label='{{ i18n "pages.client.delayedStart" }}'>
|
|
||||||
<a-switch v-model="delayedStart" @click="client._expiryTime=0"></a-switch>
|
|
||||||
</a-form-item>
|
|
||||||
<br>
|
|
||||||
<a-form-item label='{{ i18n "pages.client.expireDays" }}' v-if="delayedStart">
|
|
||||||
<a-input-number v-model="delayedExpireDays" :min="0"></a-input-number>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-else>
|
|
||||||
<span slot="label">
|
|
||||||
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
|
||||||
v-model="client._expiryTime" style="width: 170px;"></a-date-picker>
|
|
||||||
<a-tag color="red" v-if="isEdit && isExpiry">Expired</a-tag>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="client.expiryTime != 0">
|
|
||||||
<span slot="label">
|
|
||||||
<span>{{ i18n "pages.client.renew" }}</span>
|
|
||||||
<a-tooltip>
|
|
||||||
<template slot="title">
|
|
||||||
<span>{{ i18n "pages.client.renewDesc" }}</span>
|
|
||||||
</template>
|
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
|
||||||
</a-tooltip>
|
|
||||||
</span>
|
|
||||||
<a-input-number v-model.number="client.reset" :min="0"></a-input-number>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,63 +1,94 @@
|
||||||
{{define "form/inbound"}}
|
{{define "form/inbound"}}
|
||||||
<!-- base -->
|
<!-- base -->
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "enable" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-switch v-model="dbInbound.enable"></a-switch>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "enable" }}</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label='{{ i18n "remark" }}'>
|
<a-form-item>
|
||||||
<a-input v-model.trim="dbInbound.remark"></a-input>
|
<a-switch v-model="dbInbound.enable"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "protocol" }}'>
|
</td>
|
||||||
<a-select v-model="inbound.protocol" style="width: 160px;" :disabled="isEdit" :dropdown-class-name="themeSwitcher.currentTheme">
|
</tr>
|
||||||
<a-select-option v-for="p in Protocols" :key="p" :value="p">[[ p ]]</a-select-option>
|
<tr>
|
||||||
</a-select>
|
<td>{{ i18n "remark" }}</td>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<span slot="label">
|
<a-input v-model.trim="dbInbound.remark" style="width: 250px;"></a-input>
|
||||||
{{ i18n "monitor" }}
|
</a-form-item>
|
||||||
<a-tooltip>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "protocol" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="inbound.protocol" style="width: 250px;" :disabled="isEdit" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="p in Protocols" :key="p" :value="p">[[ p ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "monitor" }}
|
||||||
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<span>{{ i18n "pages.inbounds.monitorDesc" }}</span>
|
<span>{{ i18n "pages.inbounds.monitorDesc" }}</span>
|
||||||
</template>
|
</template>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</td>
|
||||||
<a-input v-model.trim="inbound.listen"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
<br>
|
<a-input v-model.trim="inbound.listen" style="width: 250px;"></a-input>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.port" }}'>
|
</a-form-item>
|
||||||
<a-input-number v-model="inbound.port"></a-input-number>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<br>
|
<tr>
|
||||||
<a-form-item>
|
<td>{{ i18n "pages.inbounds.port" }}</td>
|
||||||
<span slot="label">
|
<td>
|
||||||
<span>{{ i18n "pages.inbounds.totalFlow" }}</span> (GB)
|
<a-form-item>
|
||||||
<a-tooltip>
|
<a-input-number v-model.number="inbound.port"></a-input-number>
|
||||||
<template slot="title">
|
</a-form-item>
|
||||||
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
</td>
|
||||||
</template>
|
</tr>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<tr>
|
||||||
</a-tooltip>
|
<td>
|
||||||
</span>
|
<span>{{ i18n "pages.inbounds.totalFlow" }}</span>(GB)
|
||||||
<a-input-number v-model="dbInbound.totalGB" :min="0"></a-input-number>
|
<a-tooltip>
|
||||||
</a-form-item>
|
<template slot="title">
|
||||||
<a-form-item>
|
0 <span>{{ i18n "pages.inbounds.meansNoLimit" }}</span>
|
||||||
<span slot="label">
|
</template>
|
||||||
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
<a-tooltip>
|
</a-tooltip>
|
||||||
<template slot="title">
|
</td>
|
||||||
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
<td>
|
||||||
</template>
|
<a-form-item>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<a-input-number v-model="dbInbound.totalGB" :min="0"></a-input-number>
|
||||||
</a-tooltip>
|
</a-form-item>
|
||||||
</span>
|
</td>
|
||||||
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
</tr>
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
<tr>
|
||||||
v-model="dbInbound._expiryTime" style="width: 250px;"></a-date-picker>
|
<td>
|
||||||
</a-form-item>
|
<span>{{ i18n "pages.inbounds.expireDate" }}</span>
|
||||||
|
<a-tooltip>
|
||||||
|
<template slot="title">
|
||||||
|
<span>{{ i18n "pages.inbounds.leaveBlankToNeverExpire" }}</span>
|
||||||
|
</template>
|
||||||
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
|
</a-tooltip>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-date-picker :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
|
v-model="dbInbound._expiryTime" style="width: 250px;"></a-date-picker>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
|
|
||||||
<!-- vmess settings -->
|
<!-- vmess settings -->
|
||||||
<template v-if="inbound.protocol === Protocols.VMESS">
|
<template v-if="inbound.protocol === Protocols.VMESS">
|
||||||
{{template "form/vmess"}}
|
{{template "form/vmess"}}
|
||||||
|
|
|
@ -1,22 +1,42 @@
|
||||||
{{define "form/dokodemo"}}
|
{{define "form/dokodemo"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.targetAddress"}}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-input v-model.trim="inbound.settings.address"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "pages.inbounds.targetAddress"}}</td>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.destinationPort"}}'>
|
<td>
|
||||||
<a-input-number v-model="inbound.settings.port"></a-input-number>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input v-model.trim="inbound.settings.address"></a-input>
|
||||||
<br>
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.network"}}'>
|
</td>
|
||||||
<a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
</tr>
|
||||||
<a-select-option value="tcp,udp">TCP+UDP</a-select-option>
|
<tr>
|
||||||
<a-select-option value="tcp">TCP</a-select-option>
|
<td>{{ i18n "pages.inbounds.destinationPort"}}</td>
|
||||||
<a-select-option value="udp">UDP</a-select-option>
|
<td>
|
||||||
</a-select>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input-number v-model.number="inbound.settings.port"></a-input-number>
|
||||||
<br>
|
</a-form-item>
|
||||||
<a-form-item label="FollowRedirect">
|
</td>
|
||||||
<a-switch v-model="inbound.settings.followRedirect"></a-switch>
|
</tr>
|
||||||
</a-form-item>
|
<tr>
|
||||||
|
<td>{{ i18n "pages.inbounds.network"}}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="tcp,udp">tcp+udp</a-select-option>
|
||||||
|
<a-select-option value="tcp">tcp</a-select-option>
|
||||||
|
<a-select-option value="udp">udp</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>FollowRedirect</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.settings.followRedirect"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,19 +1,21 @@
|
||||||
{{define "form/http"}}
|
{{define "form/http"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item>
|
<table style="width: 100%; text-align: center; margin-bottom: 10px;">
|
||||||
<a-row>
|
<tr>
|
||||||
<a-button type="primary" size="small" @click="inbound.settings.addAccount(new Inbound.SocksSettings.SocksAccount())">+</a-button>
|
<td width="45%">{{ i18n "username" }}</td>
|
||||||
</a-row>
|
<td width="45%">{{ i18n "password" }}</td>
|
||||||
<a-input-group v-for="(account, index) in inbound.settings.accounts">
|
<td><a-button size="small" @click="inbound.settings.addAccount(new Inbound.HttpSettings.HttpAccount())">+</a-button></td>
|
||||||
<a-input style="width: 45%" v-model.trim="account.user"
|
</tr>
|
||||||
addon-before='{{ i18n "username" }}'></a-input>
|
</table>
|
||||||
<a-input style="width: 55%" v-model.trim="account.pass"
|
<a-input-group compact v-for="(account, index) in inbound.settings.accounts" style="margin-bottom: 10px;">
|
||||||
addon-before='{{ i18n "password" }}'>
|
<a-input style="width: 50%" v-model.trim="account.user" placeholder='{{ i18n "username" }}'>
|
||||||
|
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||||
|
</a-input>
|
||||||
|
<a-input style="width: 50%" v-model.trim="account.pass" placeholder='{{ i18n "password" }}'>
|
||||||
<template slot="addonAfter">
|
<template slot="addonAfter">
|
||||||
<a-button type="primary" size="small" @click="inbound.settings.delAccount(index)">-</a-button>
|
<a-button size="small" @click="inbound.settings.delAccount(index)">-</a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,7 +1,7 @@
|
||||||
{{define "form/shadowsocks"}}
|
{{define "form/shadowsocks"}}
|
||||||
<a-form layout="inline" style="padding: 10px 0px;">
|
<a-form layout="inline">
|
||||||
<template v-if="inbound.isSSMultiUser">
|
<template v-if="inbound.isSSMultiUser">
|
||||||
<a-collapse activeKey="0" v-for="(client, index) in inbound.settings.shadowsockses.slice(0,1)" v-if="!isEdit">
|
<a-collapse activeKey="0" v-for="(client, index) in inbound.settings.shadowsockses.slice(0,1)" v-if="!isEdit">
|
||||||
<a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'>
|
<a-collapse-panel header='{{ i18n "pages.inbounds.client" }}'>
|
||||||
{{template "form/client"}}
|
{{template "form/client"}}
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
@ -20,24 +20,40 @@
|
||||||
</table>
|
</table>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
</template>
|
</template>
|
||||||
</a-form>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-form layout="inline">
|
<tr>
|
||||||
<a-form-item label='{{ i18n "encryption" }}'>
|
<td>{{ i18n "encryption" }}</td>
|
||||||
<a-select v-model="inbound.settings.method" style="width: 250px;" :dropdown-class-name="themeSwitcher.currentTheme" @change="SSMethodChange">
|
<td>
|
||||||
<a-select-option v-for="method in SSMethods" :value="method">[[ method ]]</a-select-option>
|
<a-form-item>
|
||||||
</a-select>
|
<a-select v-model="inbound.settings.method" style="width: 250px;" @change="SSMethodChange" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
</a-form-item>
|
<a-select-option v-for="method in SSMethods" :value="method">[[ method ]]</a-select-option>
|
||||||
<a-form-item v-if="inbound.isSS2022" label='{{ i18n "password" }}'>
|
</a-select>
|
||||||
<a-icon @click="inbound.settings.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon>
|
</a-form-item>
|
||||||
<a-input v-model.trim="inbound.settings.password" style="width: 250px;"></a-input>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.network" }}'>
|
<tr v-if="inbound.isSS2022">
|
||||||
<a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
<td>{{ i18n "password" }}
|
||||||
<a-select-option value="tcp,udp">TCP+UDP</a-select-option>
|
<a-icon @click="inbound.settings.password = RandomUtil.randomShadowsocksPassword()" type="sync"> </a-icon>
|
||||||
<a-select-option value="tcp">TCP</a-select-option>
|
</td>
|
||||||
<a-select-option value="udp">UDP</a-select-option>
|
<td>
|
||||||
</a-select>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input v-model.trim="inbound.settings.password" style="width: 250px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "pages.inbounds.network" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="inbound.settings.network" style="width: 100px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="tcp,udp">tcp+udp</a-select-option>
|
||||||
|
<a-select-option value="tcp">tcp</a-select-option>
|
||||||
|
<a-select-option value="udp">udp</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,33 +1,52 @@
|
||||||
{{define "form/socks"}}
|
{{define "form/socks"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "password" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-switch :checked="inbound.settings.auth === 'password'"
|
<tr>
|
||||||
@change="checked => inbound.settings.auth = checked ? 'password' : 'noauth'"></a-switch>
|
<td style="width: 30%;">{{ i18n "password" }}</td>
|
||||||
</a-form-item>
|
<td>
|
||||||
<br>
|
<a-form-item>
|
||||||
<template v-if="inbound.settings.auth === 'password'">
|
<a-switch :checked="inbound.settings.auth === 'password'"
|
||||||
<a-form-item>
|
@change="checked => inbound.settings.auth = checked ? 'password' : 'noauth'"></a-switch>
|
||||||
<a-row>
|
</a-form-item>
|
||||||
<a-button type="primary" size="small" @click="inbound.settings.addAccount(new Inbound.SocksSettings.SocksAccount())">+</a-button>
|
</td>
|
||||||
</a-row>
|
</tr>
|
||||||
<a-input-group v-for="(account, index) in inbound.settings.accounts">
|
<tr v-if="inbound.settings.auth === 'password'">
|
||||||
<a-input style="width: 45%" v-model.trim="account.user"
|
<td colspan="2">
|
||||||
addon-before='{{ i18n "username" }}'></a-input>
|
<table style="width: 100%; text-align: center; margin-bottom: 10px;">
|
||||||
<a-input style="width: 55%" v-model.trim="account.pass"
|
<tr>
|
||||||
addon-before='{{ i18n "password" }}'>
|
<td width="45%">{{ i18n "username" }}</td>
|
||||||
<template slot="addonAfter">
|
<td width="45%">{{ i18n "password" }}</td>
|
||||||
<a-button type="primary" size="small" @click="inbound.settings.delAccount(index)">-</a-button>
|
<td><a-button size="small" @click="inbound.settings.addAccount(new Inbound.SocksSettings.SocksAccount())">+</a-button></td>
|
||||||
</template>
|
</tr>
|
||||||
</a-input>
|
</table>
|
||||||
</a-input-group>
|
<a-input-group compact v-for="(account, index) in inbound.settings.accounts" style="margin-bottom: 10px;">
|
||||||
</a-form-item>
|
<a-input style="width: 50%" v-model.trim="account.user" placeholder='{{ i18n "username" }}'>
|
||||||
</template>
|
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||||
<br>
|
</a-input>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.enable" }} udp'>
|
<a-input style="width: 50%" v-model.trim="account.pass" placeholder='{{ i18n "password" }}'>
|
||||||
<a-switch v-model="inbound.settings.udp"></a-switch>
|
<template slot="addonAfter">
|
||||||
</a-form-item>
|
<a-button size="small" @click="inbound.settings.delAccount(index)">-</a-button>
|
||||||
<a-form-item v-if="inbound.settings.udp" label="IP">
|
</template>
|
||||||
<a-input v-model.trim="inbound.settings.ip"></a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-input-group>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "pages.inbounds.enable" }} udp</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.settings.udp"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="inbound.settings.udp">
|
||||||
|
<td>IP</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.settings.ip"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,10 +1,22 @@
|
||||||
{{define "form/streamGRPC"}}
|
{{define "form/streamGRPC"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label="ServiceName">
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-input v-model.trim="inbound.stream.grpc.serviceName"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>serviceName</td>
|
||||||
<a-form-item label="Multi Mode">
|
<td>
|
||||||
<a-switch v-model="inbound.stream.grpc.multiMode"></a-switch>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input v-model.trim="inbound.stream.grpc.serviceName" style="width: 250px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MultiMode</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.stream.grpc.multiMode"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,12 +1,24 @@
|
||||||
{{define "form/streamHTTP"}}
|
{{define "form/streamHTTP"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "path" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-input v-model.trim="inbound.stream.http.path"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "path" }}</td>
|
||||||
<a-form-item label="Host">
|
<td>
|
||||||
<a-row v-for="(host, index) in inbound.stream.http.host">
|
<a-form-item>
|
||||||
<a-input v-model.trim="inbound.stream.http.host[index]"></a-input>
|
<a-input v-model.trim="inbound.stream.http.path" style="width: 250px;"></a-input>
|
||||||
</a-row>
|
</a-form-item>
|
||||||
</a-form-item>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>host</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-row v-for="(host, index) in inbound.stream.http.host">
|
||||||
|
<a-input v-model.trim="inbound.stream.http.host[index]" style="width: 250px;"></a-input>
|
||||||
|
</a-row>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,47 +1,86 @@
|
||||||
{{define "form/streamKCP"}}
|
{{define "form/streamKCP"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "camouflage" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-select v-model="inbound.stream.kcp.type" style="width: 280px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
<tr>
|
||||||
<a-select-option value="none">None (Not Camouflage)</a-select-option>
|
<td>{{ i18n "camouflage" }}</td>
|
||||||
<a-select-option value="srtp">SRTP (Camouflage Video Call)</a-select-option>
|
<td>
|
||||||
<a-select-option value="utp">UTP (Camouflage BT Download)</a-select-option>
|
<a-form-item>
|
||||||
<a-select-option value="wechat-video">Wechat-Video (Camouflage WeChat Video)</a-select-option>
|
<a-select v-model="inbound.stream.kcp.type" style="width: 250px;"
|
||||||
<a-select-option value="dtls">DTLS (Camouflage DTLS 1.2 Packages)</a-select-option>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option value="wireguard">Wireguard (Camouflage Wireguard Packages)</a-select-option>
|
<a-select-option value="none">None (Not Camouflage)</a-select-option>
|
||||||
</a-select>
|
<a-select-option value="srtp">SRTP (Camouflage Video Call)</a-select-option>
|
||||||
</a-form-item>
|
<a-select-option value="utp">UTP (Camouflage BT Download)</a-select-option>
|
||||||
<br>
|
<a-select-option value="wechat-video">Wechat-Video (Camouflage WeChat Video)</a-select-option>
|
||||||
<a-form-item label='{{ i18n "password" }}'>
|
<a-select-option value="dtls">DTLS (Camouflage DTLS 1.2 Packages)</a-select-option>
|
||||||
<a-icon @click="inbound.stream.kcp.seed = RandomUtil.randomSeq(10)" type="sync"> </a-icon>
|
<a-select-option value="wireguard">Wireguard (Camouflage Wireguard Packages)</a-select-option>
|
||||||
<a-input v-model="inbound.stream.kcp.seed" style="width: 150px;" ></a-input>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item label="MTU">
|
</tr>
|
||||||
<a-input-number v-model="inbound.stream.kcp.mtu"></a-input-number>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "password" }}</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label="TTI (ms)">
|
<a-form-item>
|
||||||
<a-input-number v-model="inbound.stream.kcp.tti"></a-input-number>
|
<a-input v-model="inbound.stream.kcp.seed" style="width: 250px;"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item label="Uplink Capacity (MB/S)">
|
</tr>
|
||||||
<a-input-number v-model="inbound.stream.kcp.upCap"></a-input-number>
|
<tr>
|
||||||
</a-form-item>
|
<td>MTU</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label="Downlink Capacity (MB/S)">
|
<a-form-item>
|
||||||
<a-input-number v-model="inbound.stream.kcp.downCap"></a-input-number>
|
<a-input-number v-model.number="inbound.stream.kcp.mtu"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item label="Congestion">
|
</tr>
|
||||||
<a-switch v-model="inbound.stream.kcp.congestion"></a-switch>
|
<tr>
|
||||||
</a-form-item>
|
<td>TTI (ms)</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label="Read Buffer Size (MB)">
|
<a-form-item>
|
||||||
<a-input-number v-model="inbound.stream.kcp.readBuffer"></a-input-number>
|
<a-input-number v-model.number="inbound.stream.kcp.tti"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<br>
|
</td>
|
||||||
<a-form-item label="Write Buffer Size (MB)">
|
</tr>
|
||||||
<a-input-number v-model="inbound.stream.kcp.writeBuffer"></a-input-number>
|
<tr>
|
||||||
</a-form-item>
|
<td>Uplink Capacity (MB/S)</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="inbound.stream.kcp.upCap"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Downlink Capacity (MB/S)</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="inbound.stream.kcp.downCap"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Congestion</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.stream.kcp.congestion"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Read Buffer Size (MB)</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="inbound.stream.kcp.readBuffer"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Write Buffer Size (MB)</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="inbound.stream.kcp.writeBuffer"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,25 +1,43 @@
|
||||||
{{define "form/streamQUIC"}}
|
{{define "form/streamQUIC"}}
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.quic.encryption" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-select v-model="inbound.stream.quic.security" style="width: 165px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
<tr>
|
||||||
<a-select-option value="none">none</a-select-option>
|
<td>{{ i18n "pages.inbounds.stream.quic.encryption" }}</td>
|
||||||
<a-select-option value="aes-128-gcm">aes-128-gcm</a-select-option>
|
<td>
|
||||||
<a-select-option value="chacha20-poly1305">chacha20-poly1305</a-select-option>
|
<a-form-item>
|
||||||
</a-select>
|
<a-select v-model="inbound.stream.quic.security" style="width: 250px;"
|
||||||
</a-form-item>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-form-item label='{{ i18n "password" }}'>
|
<a-select-option value="none">none</a-select-option>
|
||||||
<a-icon @click="inbound.stream.quic.key = RandomUtil.randomSeq(10)" type="sync"> </a-icon>
|
<a-select-option value="aes-128-gcm">aes-128-gcm</a-select-option>
|
||||||
<a-input v-model.trim="inbound.stream.quic.key" style="width: 150px;"></a-input>
|
<a-select-option value="chacha20-poly1305">chacha20-poly1305</a-select-option>
|
||||||
</a-form-item>
|
</a-select>
|
||||||
<a-form-item label='{{ i18n "camouflage" }}'>
|
</a-form-item>
|
||||||
<a-select v-model="inbound.stream.quic.type" style="width: 280px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
</td>
|
||||||
<a-select-option value="none">none (not camouflage)</a-select-option>
|
</tr>
|
||||||
<a-select-option value="srtp">srtp (camouflage video call)</a-select-option>
|
<tr>
|
||||||
<a-select-option value="utp">utp (camouflage BT download)</a-select-option>
|
<td>{{ i18n "password" }}</td>
|
||||||
<a-select-option value="wechat-video">wechat-video (camouflage WeChat video)</a-select-option>
|
<td>
|
||||||
<a-select-option value="dtls">dtls (camouflage DTLS 1.2 packages)</a-select-option>
|
<a-form-item>
|
||||||
<a-select-option value="wireguard">wireguard (camouflage wireguard packages)</a-select-option>
|
<a-input v-model.trim="inbound.stream.quic.key" style="width: 250px;"></a-input>
|
||||||
</a-select>
|
</a-form-item>
|
||||||
</a-form-item>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "camouflage" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-select v-model="inbound.stream.quic.type" style="width: 280px;"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="none">none (not camouflage)</a-select-option>
|
||||||
|
<a-select-option value="srtp">srtp (camouflage video call)</a-select-option>
|
||||||
|
<a-select-option value="utp">utp (camouflage BT download)</a-select-option>
|
||||||
|
<a-select-option value="wechat-video">wechat-video (camouflage WeChat video)</a-select-option>
|
||||||
|
<a-select-option value="dtls">dtls (camouflage DTLS 1.2 packages)</a-select-option>
|
||||||
|
<a-select-option value="wireguard">wireguard (camouflage wireguard packages)</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -2,7 +2,8 @@
|
||||||
<!-- select stream network -->
|
<!-- select stream network -->
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label='{{ i18n "transmission" }}'>
|
<a-form-item label='{{ i18n "transmission" }}'>
|
||||||
<a-select v-model="inbound.stream.network" @change="streamNetworkChange" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100px;">
|
<a-select v-model="inbound.stream.network" @change="streamNetworkChange"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme" style="width: 100px;">
|
||||||
<a-select-option value="tcp">TCP</a-select-option>
|
<a-select-option value="tcp">TCP</a-select-option>
|
||||||
<a-select-option value="kcp">KCP</a-select-option>
|
<a-select-option value="kcp">KCP</a-select-option>
|
||||||
<a-select-option value="ws">WS</a-select-option>
|
<a-select-option value="ws">WS</a-select-option>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{define "form/streamTCP"}}
|
{{define "form/streamTCP"}}
|
||||||
<!-- tcp type -->
|
<!-- tcp type -->
|
||||||
<a-form layout="inline">
|
<a-form layout="inline">
|
||||||
<a-form-item label="AcceptProxyProtocol">
|
<a-form-item label="Accept Proxy Protocol" v-if="inbound.canEnableTls()">
|
||||||
<a-switch v-model="inbound.stream.tcp.acceptProxyProtocol"></a-switch>
|
<a-switch v-model="inbound.stream.tcp.acceptProxyProtocol"></a-switch>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='HTTP {{ i18n "camouflage" }}'>
|
<a-form-item label='HTTP {{ i18n "camouflage" }}'>
|
||||||
|
@ -14,68 +14,100 @@
|
||||||
|
|
||||||
<!-- tcp request -->
|
<!-- tcp request -->
|
||||||
<a-form v-if="inbound.stream.tcp.type === 'http'" layout="inline">
|
<a-form v-if="inbound.stream.tcp.type === 'http'" layout="inline">
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestVersion" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-input v-model.trim="inbound.stream.tcp.request.version"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>{{ i18n "pages.inbounds.stream.tcp.requestVersion" }}</td>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestMethod" }}'>
|
<td>
|
||||||
<a-input v-model.trim="inbound.stream.tcp.request.method"></a-input>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input v-model.trim="inbound.stream.tcp.request.version" style="width: 200px;"></a-input>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestPath" }}'>
|
</a-form-item>
|
||||||
<a-button size="small" @click="inbound.stream.tcp.request.addPath('/')">+</a-button>
|
</td>
|
||||||
<a-row v-for="(path, index) in inbound.stream.tcp.request.path">
|
</tr>
|
||||||
<a-input v-model.trim="inbound.stream.tcp.request.path[index]" style="width: 200px;">
|
<tr>
|
||||||
<a-button size="small" slot="addonAfter"
|
<td>{{ i18n "pages.inbounds.stream.tcp.requestMethod" }}</td>
|
||||||
@click="inbound.stream.tcp.request.removePath(index)"
|
<td>
|
||||||
v-if="inbound.stream.tcp.request.path.length>1">-</a-button>
|
<a-form-item>
|
||||||
</a-input>
|
<a-input v-model.trim="inbound.stream.tcp.request.method" style="width: 200px;"></a-input>
|
||||||
</a-row>
|
</a-form-item>
|
||||||
</a-form-item>
|
</td>
|
||||||
<br>
|
</tr>
|
||||||
<a-form-item>
|
<tr>
|
||||||
<a-row>
|
<td style="vertical-align: top; padding-top: 10px;">{{ i18n "pages.inbounds.stream.tcp.requestPath" }}
|
||||||
<span>{{ i18n "pages.inbounds.stream.general.requestHeader" }}:</span>
|
<a-button size="small" @click="inbound.stream.tcp.request.addPath('/')">+</a-button>
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.tcp.request.addHeader('Host', 'xxx.com')">+</a-button>
|
</td>
|
||||||
</a-row>
|
<td>
|
||||||
<a-input-group v-for="(header, index) in inbound.stream.tcp.request.headers">
|
<a-form-item>
|
||||||
<a-input style="width: 50%" v-model.trim="header.name"
|
<a-row v-for="(path, index) in inbound.stream.tcp.request.path">
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.name" }}'></a-input>
|
<a-input v-model.trim="inbound.stream.tcp.request.path[index]" style="width: 200px;">
|
||||||
<a-input style="width: 50%" v-model.trim="header.value"
|
<a-button size="small" slot="addonAfter"
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
@click="inbound.stream.tcp.request.removePath(index)"
|
||||||
<template slot="addonAfter">
|
v-if="inbound.stream.tcp.request.path.length>1">-</a-button>
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.tcp.request.removeHeader(index)">-</a-button>
|
</a-input>
|
||||||
</template>
|
</a-row>
|
||||||
</a-input>
|
</a-form-item>
|
||||||
</a-input-group>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
|
<tr>
|
||||||
</a-form>
|
<td colspan="2" width="100%">
|
||||||
|
<a-form-item>
|
||||||
<!-- tcp response -->
|
<span>{{ i18n "pages.inbounds.stream.general.requestHeader" }}:</span>
|
||||||
<a-form v-if="inbound.stream.tcp.type === 'http'" layout="inline">
|
<a-button size="small" style="margin-left: 10px" @click="inbound.stream.tcp.request.addHeader('', '')">+</a-button>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.responseVersion" }}'>
|
<a-input-group compact v-for="(header, index) in inbound.stream.tcp.request.headers">
|
||||||
<a-input v-model.trim="inbound.stream.tcp.response.version"></a-input>
|
<a-input style="width: 50%" v-model.trim="header.name" placeholder='{{ i18n "pages.inbounds.stream.general.name" }}'>
|
||||||
</a-form-item>
|
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.responseStatus" }}'>
|
</a-input>
|
||||||
<a-input v-model.trim="inbound.stream.tcp.response.status"></a-input>
|
<a-input style="width: 50%" v-model.trim="header.value" placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||||
</a-form-item>
|
<a-button slot="addonAfter" size="small" @click="inbound.stream.tcp.request.removeHeader(index)">-</a-button>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.responseStatusDescription" }}'>
|
</a-input>
|
||||||
<a-input v-model.trim="inbound.stream.tcp.response.reason"></a-input>
|
</a-input-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
</td>
|
||||||
<a-row>
|
</tr>
|
||||||
<span>{{ i18n "pages.inbounds.stream.tcp.responseHeader" }}:</span>
|
<!-- tcp response -->
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.tcp.response.addHeader('Content-Type', 'application/octet-stream')">+</a-button>
|
<tr>
|
||||||
</a-row>
|
<td>{{ i18n "pages.inbounds.stream.tcp.responseVersion" }}</td>
|
||||||
<a-input-group v-for="(header, index) in inbound.stream.tcp.response.headers">
|
<td>
|
||||||
<a-input style="width: 50%" v-model.trim="header.name"
|
<a-form-item>
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.name" }}'></a-input>
|
<a-input v-model.trim="inbound.stream.tcp.response.version" style="width: 200px;"></a-input>
|
||||||
<a-input style="width: 50%" v-model.trim="header.value"
|
</a-form-item>
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
</td>
|
||||||
<template slot="addonAfter">
|
</tr>
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.tcp.response.removeHeader(index)">-</a-button>
|
<tr>
|
||||||
</template>
|
<td>{{ i18n "pages.inbounds.stream.tcp.responseStatus" }}</td>
|
||||||
</a-input>
|
<td>
|
||||||
</a-input-group>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-input v-model.trim="inbound.stream.tcp.response.status" style="width: 200px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ i18n "pages.inbounds.stream.tcp.responseStatusDescription" }}</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.tcp.response.reason" style="width: 200px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" width="100%">
|
||||||
|
<a-form-item>
|
||||||
|
<span>{{ i18n "pages.inbounds.stream.tcp.responseHeader" }}:</span>
|
||||||
|
<a-button size="small" style="margin-left: 10px"
|
||||||
|
@click="inbound.stream.tcp.response.addHeader('Content-Type', 'application/octet-stream')">+</a-button>
|
||||||
|
<a-input-group compact v-for="(header, index) in inbound.stream.tcp.response.headers">
|
||||||
|
<a-input style="width: 50%" v-model.trim="header.name" placeholder='{{ i18n "pages.inbounds.stream.general.name" }}'>
|
||||||
|
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||||
|
</a-input>
|
||||||
|
<a-input style="width: 50%" v-model.trim="header.value"
|
||||||
|
placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||||
|
<template slot="addonAfter">
|
||||||
|
<a-button size="small" @click="inbound.stream.tcp.response.removeHeader(index)">-</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
|
@ -11,15 +11,17 @@
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-row>
|
<a-row>
|
||||||
<span>{{ i18n "pages.inbounds.stream.general.requestHeader" }}:</span>
|
<span>{{ i18n "pages.inbounds.stream.general.requestHeader" }}:</span>
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.ws.addHeader('Host', '')">+</a-button>
|
<a-button type="primary" size="small" style="margin-left: 10px"
|
||||||
|
@click="inbound.stream.ws.addHeader('Host', '')">+</a-button>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-input-group v-for="(header, index) in inbound.stream.ws.headers">
|
<a-input-group v-for="(header, index) in inbound.stream.ws.headers">
|
||||||
<a-input style="width: 50%" v-model.trim="header.name"
|
<a-input style="width: 50%" v-model.trim="header.name"
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.name"}}'></a-input>
|
addon-before='{{ i18n "pages.inbounds.stream.general.name"}}'></a-input>
|
||||||
<a-input style="width: 50%" v-model.trim="header.value"
|
<a-input style="width: 50%" v-model.trim="header.value"
|
||||||
addon-before='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
addon-before='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||||
<template slot="addonAfter">
|
<template slot="addonAfter">
|
||||||
<a-button type="primary" size="small" style="margin-left: 10px" @click="inbound.stream.ws.removeHeader(index)">-</a-button>
|
<a-button type="primary" size="small" style="margin-left: 10px"
|
||||||
|
@click="inbound.stream.ws.removeHeader(index)">-</a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
|
|
|
@ -2,187 +2,407 @@
|
||||||
<!-- tls enable -->
|
<!-- tls enable -->
|
||||||
<a-form layout="inline" v-if="inbound.canEnableTls()">
|
<a-form layout="inline" v-if="inbound.canEnableTls()">
|
||||||
<a-divider style="margin:0;"></a-divider>
|
<a-divider style="margin:0;"></a-divider>
|
||||||
<a-form-item label='{{ i18n "security" }}'>
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-radio-group v-model="inbound.stream.security" button-style="solid">
|
<tr>
|
||||||
<a-radio-button value="none">{{ i18n "none" }}</a-radio-button>
|
<td>
|
||||||
<a-tooltip>
|
<span>{{ i18n "security" }}</span>
|
||||||
<template slot="title">
|
</td>
|
||||||
<span>{{ i18n "pages.inbounds.xtlsDesc" }}</span>
|
<td>
|
||||||
</template>
|
<a-radio-group v-model="inbound.stream.security" button-style="solid">
|
||||||
<a-radio-button v-if="inbound.canEnableXtls()" value="xtls">XTLS</a-radio-button>
|
<a-radio-button value="none">{{ i18n "none" }}</a-radio-button>
|
||||||
</a-tooltip>
|
<a-tooltip>
|
||||||
<a-tooltip>
|
<template slot="title">
|
||||||
<template slot="title">
|
<span>{{ i18n "pages.inbounds.xtlsDesc" }}</span>
|
||||||
<span>{{ i18n "pages.inbounds.realityDesc" }}</span>
|
</template>
|
||||||
</template>
|
<a-radio-button v-if="inbound.canEnableXtls()" value="xtls">XTLS</a-radio-button>
|
||||||
<a-radio-button v-if="inbound.canEnableReality()" value="reality">Reality</a-radio-button>
|
</a-tooltip>
|
||||||
</a-tooltip>
|
<a-tooltip>
|
||||||
<a-radio-button value="tls">TLS</a-radio-button>
|
<template slot="title">
|
||||||
</a-radio-group>
|
<span>{{ i18n "pages.inbounds.realityDesc" }}</span>
|
||||||
</a-form-item>
|
</template>
|
||||||
|
<a-radio-button v-if="inbound.canEnableReality()" value="reality">Reality</a-radio-button>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-radio-button value="tls">TLS</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<!-- tls settings -->
|
<!-- tls settings -->
|
||||||
<a-form v-if="inbound.tls" layout="inline">
|
<a-form v-if="inbound.tls" layout="inline">
|
||||||
<a-form-item label="CipherSuites">
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-select v-model="inbound.stream.tls.cipherSuites" style="width: 300px" :dropdown-class-name="themeSwitcher.currentTheme">
|
<tr>
|
||||||
<a-select-option value="">auto</a-select-option>
|
<td>
|
||||||
<a-select-option v-for="key,value in TLS_CIPHER_OPTION" :value="key">[[ value ]]</a-select-option>
|
<span>CipherSuites</span>
|
||||||
</a-select>
|
</td>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item label="Min/Max Version">
|
<a-form-item>
|
||||||
<a-input-group compact>
|
<a-select v-model="inbound.stream.tls.cipherSuites" style="width: 300px"
|
||||||
<a-select style="width: 60px" v-model="inbound.stream.tls.minVersion" :dropdown-class-name="themeSwitcher.currentTheme">
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
|
<a-select-option value="">auto</a-select-option>
|
||||||
</a-select>
|
<a-select-option v-for="key,value in TLS_CIPHER_OPTION" :value="key">[[ value
|
||||||
<a-select style="width: 60px" v-model="inbound.stream.tls.maxVersion" :dropdown-class-name="themeSwitcher.currentTheme">
|
]]</a-select-option>
|
||||||
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
|
</a-select>
|
||||||
</a-select>
|
</a-form-item>
|
||||||
</a-input-group>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<a-form-item label="SNI" placeholder="Server Name Indication">
|
<tr>
|
||||||
<a-input v-model.trim="inbound.stream.tls.server" style="width: 250px"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<span>Min/Max Version</span>
|
||||||
<a-form-item label="uTLS">
|
</td>
|
||||||
<a-select v-model="inbound.stream.tls.settings.fingerprint"
|
<td>
|
||||||
style="width: 170px" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-form-item>
|
||||||
<a-select-option value=''>None</a-select-option>
|
<a-input-group compact>
|
||||||
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
|
<a-select style="width: 60px" v-model="inbound.stream.tls.minVersion"
|
||||||
</a-select>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
</a-form-item>
|
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
|
||||||
<a-form-item label="Alpn">
|
</a-select>
|
||||||
<a-select
|
<a-select style="width: 60px" v-model="inbound.stream.tls.maxVersion"
|
||||||
mode="multiple"
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
style="width: 250px"
|
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
</a-select>
|
||||||
v-model="inbound.stream.tls.alpn">
|
</a-input-group>
|
||||||
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
|
</a-form-item>
|
||||||
</a-select>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<br>
|
<tr>
|
||||||
<a-form-item label="Allow insecure">
|
<td>
|
||||||
<a-switch v-model="inbound.stream.tls.settings.allowInsecure"></a-switch>
|
<span>SNI</span>
|
||||||
</a-form-item>
|
</td>
|
||||||
<br>
|
<td>
|
||||||
<a-form-item label="Reject Unknown SNI">
|
<a-form-item>
|
||||||
<a-switch v-model="inbound.stream.tls.rejectUnknownSni"></a-switch>
|
<a-input v-model.trim="inbound.stream.tls.server" style="width: 250px"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<template v-for="cert,index in inbound.stream.tls.certs">
|
</td>
|
||||||
<a-form-item label='{{ i18n "certificate" }}'>
|
</tr>
|
||||||
<a-radio-group v-model="cert.useFile" button-style="solid">
|
<tr>
|
||||||
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
|
<td>
|
||||||
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
|
<span>uTLS</span>
|
||||||
</a-radio-group>
|
</td>
|
||||||
<a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.tls.addCert()" style="margin-left: 10px">+</a-button>
|
<td>
|
||||||
<a-button v-if="inbound.stream.tls.certs.length>1" type="primary" size="small" @click="inbound.stream.tls.removeCert(index)" style="margin-left: 10px">-</a-button>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-select v-model="inbound.stream.tls.settings.fingerprint" style="width: 170px"
|
||||||
<template v-if="cert.useFile">
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>
|
<a-select-option value=''>None</a-select-option>
|
||||||
<a-input v-model.trim="cert.certFile" style="width:300px;"></a-input>
|
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
|
||||||
</a-form-item>
|
</a-select>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.keyPath" }}'>
|
</a-form-item>
|
||||||
<a-input v-model.trim="cert.keyFile" style="width:300px;"></a-input>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<a-button type="primary" icon="import" @click="setDefaultCertData(index)">{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
|
<tr>
|
||||||
</template>
|
<td>
|
||||||
<template v-else>
|
<span>Alpn</span>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyContent" }}'>
|
</td>
|
||||||
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.cert"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.keyContent" }}'>
|
<a-select mode="multiple" style="width: 250px" :dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.key"></a-input>
|
v-model="inbound.stream.tls.alpn">
|
||||||
</a-form-item>
|
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
|
||||||
</template>
|
</a-select>
|
||||||
<br>
|
</a-form-item>
|
||||||
<a-form-item label="ocspStapling">
|
</td>
|
||||||
<a-input-number v-model.number="cert.ocspStapling" :min="0"></a-input-number>
|
</tr>
|
||||||
</a-form-item>
|
<tr>
|
||||||
</template>
|
<td>
|
||||||
|
<span>Allow insecure</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.stream.tls.settings.allowInsecure"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Reject Unknown SNI</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-switch v-model="inbound.stream.tls.rejectUnknownSni"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "certificate" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-radio-group v-model="cert.useFile" button-style="solid">
|
||||||
|
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
|
||||||
|
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.tls.addCert()"
|
||||||
|
style="margin-left: 10px">+</a-button>
|
||||||
|
<a-button v-if="inbound.stream.tls.certs.length>1" type="primary" size="small"
|
||||||
|
@click="inbound.stream.tls.removeCert(index)" style="margin-left: 10px">-</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.publicKeyPath" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="cert.certFile" style="width:300px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.keyPath" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="cert.keyFile" style="width:300px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<a-button type="primary" icon="import" @click="setDefaultCertData(index)">{{ i18n
|
||||||
|
"pages.inbounds.setDefaultCert" }}</a-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs" v-else>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.publicKeyContent" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.cert"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs" v-else>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.keyContent" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.key"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.tls.certs">
|
||||||
|
<td>
|
||||||
|
<span>ocspStapling</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input-number v-model.number="cert.ocspStapling" :min="0"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<!-- xtls settings -->
|
<!-- xtls settings -->
|
||||||
<a-form v-else-if="inbound.xtls" layout="inline">
|
<a-form v-else-if="inbound.xtls" layout="inline">
|
||||||
<a-form-item label="SNI" placeholder="Server Name Indication">
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-input v-model.trim="inbound.stream.xtls.server" style="width: 250px"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item label="Alpn">
|
<span>SNI</span>
|
||||||
<a-select
|
</td>
|
||||||
mode="multiple"
|
<td>
|
||||||
style="width: 250px"
|
<a-form-item>
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme"
|
<a-input v-model.trim="inbound.stream.xtls.server" style="width: 250px"></a-input>
|
||||||
v-model="inbound.stream.xtls.alpn">
|
</a-form-item>
|
||||||
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
|
</td>
|
||||||
</a-select>
|
</tr>
|
||||||
</a-form-item>
|
<tr>
|
||||||
<a-form-item label="Allow insecure">
|
<td>
|
||||||
<a-switch v-model="inbound.stream.xtls.settings.allowInsecure"></a-switch>
|
<span>Alpn</span>
|
||||||
</a-form-item>
|
</td>
|
||||||
<template v-for="cert,index in inbound.stream.xtls.certs">
|
<td>
|
||||||
<a-form-item label='{{ i18n "certificate" }}'>
|
<a-form-item>
|
||||||
<a-radio-group v-model="cert.useFile" button-style="solid">
|
<a-select mode="multiple" style="width: 250px" :dropdown-class-name="themeSwitcher.currentTheme"
|
||||||
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
|
v-model="inbound.stream.xtls.alpn">
|
||||||
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
|
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
|
||||||
</a-radio-group>
|
</a-select>
|
||||||
<a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()" style="margin-left: 10px">+</a-button>
|
</a-form-item>
|
||||||
<a-button v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small" @click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px">-</a-button>
|
</td>
|
||||||
</a-form-item>
|
</tr>
|
||||||
<template v-if="cert.useFile">
|
<tr>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyPath" }}'>
|
<td>
|
||||||
<a-input v-model.trim="cert.certFile" style="width:300px;"></a-input>
|
<span>Allow insecure</span>
|
||||||
</a-form-item>
|
</td>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.keyPath" }}'>
|
<td>
|
||||||
<a-input v-model.trim="cert.keyFile" style="width:300px;"></a-input>
|
<a-form-item>
|
||||||
</a-form-item>
|
<a-switch v-model="inbound.stream.xtls.settings.allowInsecure"></a-switch>
|
||||||
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
|
</a-form-item>
|
||||||
</template>
|
</td>
|
||||||
<template v-else>
|
</tr>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.publicKeyContent" }}'>
|
<tr v-for="cert,index in inbound.stream.xtls.certs">
|
||||||
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.cert"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<span>{{ i18n "certificate" }}</span>
|
||||||
<a-form-item label='{{ i18n "pages.inbounds.keyContent" }}'>
|
</td>
|
||||||
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.key"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
</template>
|
<a-radio-group v-model="cert.useFile" button-style="solid">
|
||||||
</template>
|
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
|
||||||
|
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-button v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()"
|
||||||
|
style="margin-left: 10px">+</a-button>
|
||||||
|
<a-button v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small"
|
||||||
|
@click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px">-</a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.xtls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.publicKeyPath" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="cert.certFile" style="width:300px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.xtls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.keyPath" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="cert.keyFile" style="width:300px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.xtls.certs" v-if="cert.useFile">
|
||||||
|
<td>
|
||||||
|
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">{{ i18n
|
||||||
|
"pages.inbounds.setDefaultCert" }}</a-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.xtls.certs" v-else>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.publicKeyContent" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.cert"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cert,index in inbound.stream.xtls.certs" v-else>
|
||||||
|
<td>
|
||||||
|
<span>{{ i18n "pages.inbounds.keyContent" }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input type="textarea" :rows="3" style="width:300px;" v-model="cert.key"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
<!-- reality settings -->
|
<!-- reality settings -->
|
||||||
<a-form v-else-if="inbound.reality" layout="inline">
|
<a-form v-else-if="inbound.reality" layout="inline">
|
||||||
<a-form-item label="Show">
|
<table width="100%" class="ant-table-tbody">
|
||||||
<a-switch v-model="inbound.stream.reality.show">
|
<tr>
|
||||||
</a-switch>
|
<td>
|
||||||
</a-form-item>
|
<span>Show</span>
|
||||||
<a-form-item label="xVer">
|
</td>
|
||||||
<a-input-number v-model="inbound.stream.reality.xver" :min="0" style="width: 60px"></a-input-number>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
<a-form-item label="uTLS">
|
<a-switch v-model="inbound.stream.reality.show"></a-switch>
|
||||||
<a-select v-model="inbound.stream.reality.settings.fingerprint"
|
</a-form-item>
|
||||||
style="width: 135px" :dropdown-class-name="themeSwitcher.currentTheme">
|
</td>
|
||||||
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
|
</tr>
|
||||||
</a-select>
|
<tr>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item label="Dest">
|
<span>xVer</span>
|
||||||
<a-input v-model.trim="inbound.stream.reality.dest" style="width: 300px"></a-input>
|
</td>
|
||||||
</a-form-item>
|
<td>
|
||||||
<a-form-item label="Server Names">
|
<a-form-item>
|
||||||
<a-input v-model.trim="inbound.stream.reality.serverNames" style="width: 300px"></a-input>
|
<a-input-number v-model="inbound.stream.reality.xver" :min="0" style="width: 60px"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="ShortIds">
|
</td>
|
||||||
<a-icon @click="inbound.stream.reality.shortIds = RandomUtil.randomShortId()" type="sync"> </a-icon>
|
</tr>
|
||||||
<a-input v-model.trim="inbound.stream.reality.shortIds" style="width: 150px;"></a-input>
|
<tr>
|
||||||
</a-form-item>
|
<td>
|
||||||
<br>
|
<span>uTLS</span>
|
||||||
<a-form-item label="SpiderX">
|
</td>
|
||||||
<a-input v-model.trim="inbound.stream.reality.settings.spiderX" style="width: 150px;"></a-input>
|
<td>
|
||||||
</a-form-item>
|
<a-form-item>
|
||||||
<a-form-item label="Private Key">
|
<a-select v-model="inbound.stream.reality.settings.fingerprint" style="width: 135px"
|
||||||
<a-input v-model.trim="inbound.stream.reality.privateKey" style="width: 300px"></a-input>
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
</a-form-item>
|
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
|
||||||
<a-form-item label="Public Key">
|
</a-select>
|
||||||
<a-input v-model.trim="inbound.stream.reality.settings.publicKey" style="width: 300px"></a-input>
|
</a-form-item>
|
||||||
</a-form-item>
|
</td>
|
||||||
<a-form-item>
|
</tr>
|
||||||
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Key</a-button>
|
<tr>
|
||||||
</a-form-item>
|
<td>
|
||||||
|
<span>Dest</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.dest" style="width: 300px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Server Names</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.serverNames" style="width: 300px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>ShortIds</span> <a-icon @click="inbound.stream.reality.shortIds = RandomUtil.randomShortId()" type="sync"> </a-icon>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.shortIds" style="width: 150px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>SpiderX</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.settings.spiderX" style="width: 150px;"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Private Key</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.privateKey" style="width: 300px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Public Key</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a-form-item>
|
||||||
|
<a-input v-model.trim="inbound.stream.reality.settings.publicKey" style="width: 300px"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Key</a-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
</a-form>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
Loading…
Reference in a new issue