| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 | <!DOCTYPE html><html lang="en">{{template "head" .}}<style>    @media (min-width: 769px) {        .ant-layout-content {            margin: 24px 16px;        }    }    .ant-col-sm-24 {        margin-top: 10px;    }    .ant-tabs-bar {        margin: 0;    }    .ant-list-item {        display: block;    }    :not(.ant-card-dark)>.ant-tabs-top-bar {        background: white;    }</style><body><a-layout id="app" v-cloak>    {{ template "commonSider" . }}    <a-layout id="content-layout" :style="siderDrawer.isDarkTheme ? bgDarkStyle : ''">        <a-layout-content>            <a-spin :spinning="spinning" :delay="500" tip="loading">                <a-space direction="vertical">                    <a-space direction="horizontal">                        <a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.setting.save" }}</a-button>                        <a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.setting.restartPanel" }}</a-button>                    </a-space>                    <a-tabs default-active-key="1" :class="siderDrawer.isDarkTheme ? darkClass : ''">                        <a-tab-pane key="1" tab='{{ i18n "pages.setting.panelConfig"}}'>                            <a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">                                <setting-list-item type="text" title='{{ i18n "pages.setting.panelListeningIP"}}' desc='{{ i18n "pages.setting.panelListeningIPDesc"}}' v-model="allSetting.webListen"></setting-list-item>                                <setting-list-item type="number" title='{{ i18n "pages.setting.panelPort"}}' desc='{{ i18n "pages.setting.panelPortDesc"}}' v-model.number="allSetting.webPort"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>                                <setting-list-item type="number" title='{{ i18n "pages.setting.expireTimeDiff" }}' desc='{{ i18n "pages.setting.expireTimeDiffDesc" }}'  v-model="allSetting.expireDiff" :min="0"></setting-list-item>                                <setting-list-item type="number" title='{{ i18n "pages.setting.trafficDiff" }}' desc='{{ i18n "pages.setting.trafficDiffDesc" }}'  v-model="allSetting.trafficDiff" :min="0"></setting-list-item>                                <a-list-item>                                    <a-row style="padding: 20px">                                        <a-col :lg="24" :xl="12">                                            <a-list-item-meta title="Language"/>                                        </a-col>                                        <a-col :lg="24" :xl="12">                                            <template>                                                <a-select                                                        ref="selectLang"                                                        v-model="lang"                                                        @change="setLang(lang)"                                                        :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"                                                        style="width: 100%"                                                >                                                    <a-select-option :value="l.value" :label="l.value" v-for="l in supportLangs">                                                        <span role="img" aria-label="l.name" v-text="l.icon"></span>                                                          <span v-text="l.name"></span>                                                    </a-select-option>                                                </a-select>                                            </template>                                        </a-col>                                    </a-row>                                </a-list-item>                            </a-list>                        </a-tab-pane>                        <a-tab-pane key="2" tab='{{ i18n "pages.setting.userSetting"}}'>                            <a-form :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65); padding: 20px;': 'background: white; padding: 20px;'">                                <a-form-item label='{{ i18n "pages.setting.oldUsername"}}'>                                    <a-input v-model="user.oldUsername" style="max-width: 300px"></a-input>                                </a-form-item>                                <a-form-item label='{{ i18n "pages.setting.currentPassword"}}'>                                    <a-input type="password" v-model="user.oldPassword"                                             style="max-width: 300px"></a-input>                                </a-form-item>                                <a-form-item label='{{ i18n "pages.setting.newUsername"}}'>                                    <a-input v-model="user.newUsername" style="max-width: 300px"></a-input>                                </a-form-item>                                <a-form-item label='{{ i18n "pages.setting.newPassword"}}'>                                    <a-input type="password" v-model="user.newPassword"                                             style="max-width: 300px"></a-input>                                </a-form-item>                                <a-form-item><!--                                    <a-button type="primary" @click="updateUser">Revise</a-button>-->                                    <a-button type="primary" @click="updateUser">{{ i18n "confirm" }}</a-button>                                </a-form-item>                            </a-form>                        </a-tab-pane>                        <a-tab-pane key="3" tab='{{ i18n "pages.setting.xrayConfiguration"}}'>                            <a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">                                <setting-list-item type="switch" title='{{ i18n "pages.setting.xrayConfigTorrent"}}' desc='{{ i18n "pages.setting.xrayConfigTorrentDesc"}}'  v-model="torrentSettings"></setting-list-item>                                <setting-list-item type="switch" title='{{ i18n "pages.setting.xrayConfigPrivateIp"}}' desc='{{ i18n "pages.setting.xrayConfigPrivateIpDesc"}}'  v-model="privateIpSettings"></setting-list-item>                                <setting-list-item type="switch" title='{{ i18n "pages.setting.xrayConfigIRIp"}}' desc='{{ i18n "pages.setting.xrayConfigIRIpDesc"}}'  v-model="IRIpSettings"></setting-list-item>								<setting-list-item type="switch" title='{{ i18n "pages.setting.xrayConfigIRdomain"}}' desc='{{ i18n "pages.setting.xrayConfigIRdomainDesc"}}'  v-model="IRdomainSettings"></setting-list-item>								<a-divider>{{ i18n "pages.setting.advancedTemplate"}}</a-divider>                                <a-collapse>                                    <a-collapse-panel header="{{ i18n "pages.setting.xrayConfigInbounds"}}">                                        <setting-list-item type="textarea" title='{{ i18n "pages.setting.xrayConfigInbounds"}}' desc='{{ i18n "pages.setting.xrayConfigInboundsDesc"}}' v-model ="inboundSettings"></setting-list-item>                                    </a-collapse-panel>                                    <a-collapse-panel header="{{ i18n "pages.setting.xrayConfigOutbounds"}}">                                        <setting-list-item type="textarea" title='{{ i18n "pages.setting.xrayConfigOutbounds"}}' desc='{{ i18n "pages.setting.xrayConfigOutboundsDesc"}}' v-model ="outboundSettings"></setting-list-item>                                    </a-collapse-panel>                                    <a-collapse-panel header="{{ i18n "pages.setting.xrayConfigRoutings"}}">                                        <setting-list-item type="textarea" title='{{ i18n "pages.setting.xrayConfigRoutings"}}' desc='{{ i18n "pages.setting.xrayConfigRoutingsDesc"}}' v-model ="routingRuleSettings"></setting-list-item>                                    </a-collapse-panel>                                </a-collapse>                                <a-divider>{{ i18n "pages.setting.completeTemplate"}}</a-divider>                                <setting-list-item type="textarea" title='{{ i18n "pages.setting.xrayConfigTemplate"}}' desc='{{ i18n "pages.setting.xrayConfigTemplateDesc"}}' v-model="allSetting.xrayTemplateConfig"></setting-list-item>                            </a-list>                        </a-tab-pane>                        <a-tab-pane key="4" tab='{{ i18n "pages.setting.TGReminder"}}'>                            <a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">                                <setting-list-item type="switch" title='{{ i18n "pages.setting.telegramBotEnable" }}' desc='{{ i18n "pages.setting.telegramBotEnableDesc" }}'  v-model="allSetting.tgBotEnable"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.telegramToken"}}' desc='{{ i18n "pages.setting.telegramTokenDesc"}}'  v-model="allSetting.tgBotToken"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.telegramChatId"}}' desc='{{ i18n "pages.setting.telegramChatIdDesc"}}'  v-model="allSetting.tgBotChatId"></setting-list-item>                                <setting-list-item type="text" title='{{ i18n "pages.setting.telegramNotifyTime"}}' desc='{{ i18n "pages.setting.telegramNotifyTimeDesc"}}'  v-model="allSetting.tgRunTime"></setting-list-item>                                <setting-list-item type="switch" title='{{ i18n "pages.setting.tgNotifyBackup" }}' desc='{{ i18n "pages.setting.tgNotifyBackupDesc" }}'  v-model="allSetting.tgBotBackup"></setting-list-item>                                <setting-list-item type="number" title='{{ i18n "pages.setting.tgNotifyCpu" }}' desc='{{ i18n "pages.setting.tgNotifyCpuDesc" }}'  v-model="allSetting.tgCpu" :min="0" :max="100"></setting-list-item>                            </a-list>                        </a-tab-pane>                        <a-tab-pane key="5" tab='{{ i18n "pages.setting.otherSetting"}}'>                            <a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">                                <setting-list-item type="text" title='{{ i18n "pages.setting.timeZonee"}}' desc='{{ i18n "pages.setting.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>                            </a-list>                        </a-tab-pane>                    </a-tabs>                </a-space>            </a-spin>        </a-layout-content>    </a-layout></a-layout>{{template "js" .}}{{template "component/setting"}}<script>    const app = new Vue({        delimiters: ['[[', ']]'],        el: '#app',        data: {            siderDrawer,            spinning: false,            oldAllSetting: new AllSetting(),            allSetting: new AllSetting(),            saveBtnDisable: true,            user: {},            lang : getLang()        },        methods: {            loading(spinning = true) {                this.spinning = spinning;            },            async getAllSetting() {                this.loading(true);                const msg = await HttpUtil.post("/xui/setting/all");                this.loading(false);                if (msg.success) {                    this.oldAllSetting = new AllSetting(msg.obj);                    this.allSetting = new AllSetting(msg.obj);                    this.saveBtnDisable = true;                }            },            async updateAllSetting() {                this.loading(true);                const msg = await HttpUtil.post("/xui/setting/update", this.allSetting);                this.loading(false);                if (msg.success) {                    await this.getAllSetting();                }            },            async updateUser() {                this.loading(true);                const msg = await HttpUtil.post("/xui/setting/updateUser", this.user);                this.loading(false);                if (msg.success) {                    this.user = {};                }            },            async restartPanel() {                await new Promise(resolve => {                    this.$confirm({                        title: '{{ i18n "pages.setting.restartPanel" }}',                        content: '{{ i18n "pages.setting.restartPanelDesc" }}',                        okText: '{{ i18n "sure" }}',                        cancelText: '{{ i18n "cancel" }}',                        onOk: () => resolve(),                    });                });                this.loading(true);                const msg = await HttpUtil.post("/xui/setting/restartPanel");                this.loading(false);                if (msg.success) {                    this.loading(true);                    await PromiseUtil.sleep(5000);                    location.reload();                }            }        },        async mounted() {            await this.getAllSetting();            while (true) {                await PromiseUtil.sleep(1000);                this.saveBtnDisable = this.oldAllSetting.equals(this.allSetting);            }        },        computed: {            templateSettings: {                get: function () { return this.allSetting.xrayTemplateConfig ? JSON.parse(this.allSetting.xrayTemplateConfig) : null ; },                set: function (newValue) { this.allSetting.xrayTemplateConfig = JSON.stringify(newValue, null, 2) },            },            inboundSettings: {                get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.inbounds, null, 2) : null; },                set: function (newValue) {                    newTemplateSettings = this.templateSettings;                    newTemplateSettings.inbounds = JSON.parse(newValue)                    this.templateSettings = newTemplateSettings                },            },            outboundSettings: {                get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.outbounds, null, 2) : null; },                set: function (newValue) {                    newTemplateSettings = this.templateSettings;                    newTemplateSettings.outbounds = JSON.parse(newValue)                    this.templateSettings = newTemplateSettings                },            },            routingRuleSettings: {                get: function () { return this.templateSettings ? JSON.stringify(this.templateSettings.routing.rules, null, 2) : null; },                set: function (newValue) {                    newTemplateSettings = this.templateSettings;                    newTemplateSettings.routing.rules = JSON.parse(newValue)                    this.templateSettings = newTemplateSettings                },            },            torrentSettings: {                get: function () {                    torrentFilter = false                    if(this.templateSettings != null){                        this.templateSettings.routing.rules.forEach(routingRule => {                            if(routingRule.hasOwnProperty("protocol")){                                if (routingRule.protocol[0] === "bittorrent" && routingRule.outboundTag == "blocked"){                                    torrentFilter = true                                }                            }                        });                    }                    return torrentFilter                },                set: function (newValue) {                    newTemplateSettings = JSON.parse(this.allSetting.xrayTemplateConfig);                    if (newValue){                        newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"protocol\": [\"bittorrent\"],\"type\": \"field\"}"))                    }                    else {                        newTemplateSettings.routing.rules = [];                        this.templateSettings.routing.rules.forEach(routingRule => {                            if (routingRule.hasOwnProperty('protocol')){                                if (routingRule.protocol[0] === "bittorrent" && routingRule.outboundTag == "blocked"){                                    return;                                }                            }                            newTemplateSettings.routing.rules.push(routingRule);                        });                    }                    this.templateSettings = newTemplateSettings                },            },            privateIpSettings: {                get: function () {                    localIpFilter = false                    if(this.templateSettings != null){                        this.templateSettings.routing.rules.forEach(routingRule => {                            if(routingRule.hasOwnProperty("ip")){                                if (routingRule.ip[0] === "geoip:private" && routingRule.outboundTag == "blocked"){                                    localIpFilter = true                                }                            }                        });                    }                    return localIpFilter                },                set: function (newValue) {                    newTemplateSettings = JSON.parse(this.allSetting.xrayTemplateConfig);                    if (newValue){                        newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"ip\": [\"geoip:private\"],\"type\": \"field\"}"))                    }                    else {                        newTemplateSettings.routing.rules = [];                        this.templateSettings.routing.rules.forEach(routingRule => {                            if (routingRule.hasOwnProperty('ip')){                                if (routingRule.ip[0] === "geoip:private" && routingRule.outboundTag == "blocked"){                                    return;                                }                            }                            newTemplateSettings.routing.rules.push(routingRule);                        });                    }                    this.templateSettings = newTemplateSettings                },            },			IRIpSettings: {                get: function () {                    localIpFilter = false                    if(this.templateSettings != null){                        this.templateSettings.routing.rules.forEach(routingRule => {                            if(routingRule.hasOwnProperty("ip")){                                if (routingRule.ip[0] === "geoip:ir" && routingRule.outboundTag == "blocked"){                                    localIpFilter = true                                }                            }                        });                    }                    return localIpFilter                },                set: function (newValue) {                    newTemplateSettings = JSON.parse(this.allSetting.xrayTemplateConfig);                    if (newValue){                        newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"ip\": [\"geoip:ir\"],\"type\": \"field\"}"))                    }                    else {                        newTemplateSettings.routing.rules = [];                        this.templateSettings.routing.rules.forEach(routingRule => {                            if (routingRule.hasOwnProperty('ip')){                                if (routingRule.ip[0] === "geoip:ir" && routingRule.outboundTag == "blocked"){                                    return;                                }                            }                            newTemplateSettings.routing.rules.push(routingRule);                        });                    }                    this.templateSettings = newTemplateSettings                },            },			IRdomainSettings: {                get: function () {                    localdomainFilter = false                    if(this.templateSettings != null){                        this.templateSettings.routing.rules.forEach(routingRule => {                            if(routingRule.hasOwnProperty("domain")){                                if ((routingRule.domain[0] === "regexp:.+.ir$" || routingRule.domain[0] === "ext:iran.dat:ir" || routingRule.domain[0] === "ext:iran.dat:other") && routingRule.outboundTag == "blocked") {                                    localdomainFilter = true                                }                            }                        });                    }                    return localdomainFilter                },                set: function (newValue) {                    newTemplateSettings = JSON.parse(this.allSetting.xrayTemplateConfig);                    if (newValue){                        newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"domain\": [\"regexp:.+.ir$\", \"ext:iran.dat:ir\", \"ext:iran.dat:other\"],\"type\": \"field\"}"))                    }                    else {                        newTemplateSettings.routing.rules = [];                        this.templateSettings.routing.rules.forEach(routingRule => {                            if (routingRule.hasOwnProperty('domain')){                                if ((routingRule.domain[0] === "regexp:.+.ir$" || routingRule.domain[0] === "ext:iran.dat:ir" || routingRule.domain[0] === "ext:iran.dat:other") && routingRule.outboundTag == "blocked"){                                    return;                                }                            }                            newTemplateSettings.routing.rules.push(routingRule);                        });                    }                    this.templateSettings = newTemplateSettings                },            },			        }    });</script></body></html>
 |