mirror of
				https://github.com/MHSanaei/3x-ui.git
				synced 2025-11-04 06:12:52 +00:00 
			
		
		
		
	pagination and sub URI support #1300
This commit is contained in:
		
							parent
							
								
									549f230221
								
							
						
					
					
						commit
						5e47b4e949
					
				
					 14 changed files with 142 additions and 59 deletions
				
			
		| 
						 | 
					@ -56,44 +56,11 @@ func (a *SettingController) getAllSetting(c *gin.Context) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *SettingController) getDefaultSettings(c *gin.Context) {
 | 
					func (a *SettingController) getDefaultSettings(c *gin.Context) {
 | 
				
			||||||
	type settingFunc func() (interface{}, error)
 | 
						result, err := a.settingService.GetDefaultSettings(c.Request.Host)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
	settings := map[string]settingFunc{
 | 
							jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
 | 
				
			||||||
		"expireDiff":  func() (interface{}, error) { return a.settingService.GetExpireDiff() },
 | 
							return
 | 
				
			||||||
		"trafficDiff": func() (interface{}, error) { return a.settingService.GetTrafficDiff() },
 | 
					 | 
				
			||||||
		"defaultCert": func() (interface{}, error) { return a.settingService.GetCertFile() },
 | 
					 | 
				
			||||||
		"defaultKey":  func() (interface{}, error) { return a.settingService.GetKeyFile() },
 | 
					 | 
				
			||||||
		"tgBotEnable": func() (interface{}, error) { return a.settingService.GetTgbotenabled() },
 | 
					 | 
				
			||||||
		"subEnable":   func() (interface{}, error) { return a.settingService.GetSubEnable() },
 | 
					 | 
				
			||||||
		"subPort":     func() (interface{}, error) { return a.settingService.GetSubPort() },
 | 
					 | 
				
			||||||
		"subPath":     func() (interface{}, error) { return a.settingService.GetSubPath() },
 | 
					 | 
				
			||||||
		"subDomain":   func() (interface{}, error) { return a.settingService.GetSubDomain() },
 | 
					 | 
				
			||||||
		"subKeyFile":  func() (interface{}, error) { return a.settingService.GetSubKeyFile() },
 | 
					 | 
				
			||||||
		"subCertFile": func() (interface{}, error) { return a.settingService.GetSubCertFile() },
 | 
					 | 
				
			||||||
		"subEncrypt":  func() (interface{}, error) { return a.settingService.GetSubEncrypt() },
 | 
					 | 
				
			||||||
		"subShowInfo": func() (interface{}, error) { return a.settingService.GetSubShowInfo() },
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	result := make(map[string]interface{})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for key, fn := range settings {
 | 
					 | 
				
			||||||
		value, err := fn()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		result[key] = value
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	subTLS := false
 | 
					 | 
				
			||||||
	if result["subKeyFile"] != "" || result["subCertFile"] != "" {
 | 
					 | 
				
			||||||
		subTLS = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	result["subTLS"] = subTLS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	delete(result, "subKeyFile")
 | 
					 | 
				
			||||||
	delete(result, "subCertFile")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	jsonObj(c, result, nil)
 | 
						jsonObj(c, result, nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ type AllSetting struct {
 | 
				
			||||||
	WebKeyFile       string `json:"webKeyFile" form:"webKeyFile"`
 | 
						WebKeyFile       string `json:"webKeyFile" form:"webKeyFile"`
 | 
				
			||||||
	WebBasePath      string `json:"webBasePath" form:"webBasePath"`
 | 
						WebBasePath      string `json:"webBasePath" form:"webBasePath"`
 | 
				
			||||||
	SessionMaxAge    int    `json:"sessionMaxAge" form:"sessionMaxAge"`
 | 
						SessionMaxAge    int    `json:"sessionMaxAge" form:"sessionMaxAge"`
 | 
				
			||||||
 | 
						PageSize         int    `json:"pageSize" form:"pageSize"`
 | 
				
			||||||
	ExpireDiff       int    `json:"expireDiff" form:"expireDiff"`
 | 
						ExpireDiff       int    `json:"expireDiff" form:"expireDiff"`
 | 
				
			||||||
	TrafficDiff      int    `json:"trafficDiff" form:"trafficDiff"`
 | 
						TrafficDiff      int    `json:"trafficDiff" form:"trafficDiff"`
 | 
				
			||||||
	TgBotEnable      bool   `json:"tgBotEnable" form:"tgBotEnable"`
 | 
						TgBotEnable      bool   `json:"tgBotEnable" form:"tgBotEnable"`
 | 
				
			||||||
| 
						 | 
					@ -44,6 +45,7 @@ type AllSetting struct {
 | 
				
			||||||
	SubUpdates       int    `json:"subUpdates" form:"subUpdates"`
 | 
						SubUpdates       int    `json:"subUpdates" form:"subUpdates"`
 | 
				
			||||||
	SubEncrypt       bool   `json:"subEncrypt" form:"subEncrypt"`
 | 
						SubEncrypt       bool   `json:"subEncrypt" form:"subEncrypt"`
 | 
				
			||||||
	SubShowInfo      bool   `json:"subShowInfo" form:"subShowInfo"`
 | 
						SubShowInfo      bool   `json:"subShowInfo" form:"subShowInfo"`
 | 
				
			||||||
 | 
						SubURI           string `json:"subURI" form:"subURI"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *AllSetting) CheckValid() error {
 | 
					func (s *AllSetting) CheckValid() error {
 | 
				
			||||||
| 
						 | 
					@ -93,6 +95,12 @@ func (s *AllSetting) CheckValid() error {
 | 
				
			||||||
	if !strings.HasSuffix(s.WebBasePath, "/") {
 | 
						if !strings.HasSuffix(s.WebBasePath, "/") {
 | 
				
			||||||
		s.WebBasePath += "/"
 | 
							s.WebBasePath += "/"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if !strings.HasPrefix(s.SubPath, "/") {
 | 
				
			||||||
 | 
							s.SubPath = "/" + s.SubPath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !strings.HasSuffix(s.SubPath, "/") {
 | 
				
			||||||
 | 
							s.SubPath += "/"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err := time.LoadLocation(s.TimeLocation)
 | 
						_, err := time.LoadLocation(s.TimeLocation)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,8 +86,7 @@
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            genSubLink(subID) {
 | 
					            genSubLink(subID) {
 | 
				
			||||||
                const { domain: host, port, tls: isTLS, path: base } = app.subSettings;
 | 
					                return app.subSettings.subURI+subID+'?name='+subID;
 | 
				
			||||||
                return buildURL({ host, port, isTLS, base, path: subID+'?name='+remark });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        updated() {
 | 
					        updated() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,10 +13,10 @@
 | 
				
			||||||
        </a-col>
 | 
					        </a-col>
 | 
				
			||||||
        <a-col :lg="24" :xl="12">
 | 
					        <a-col :lg="24" :xl="12">
 | 
				
			||||||
            <template v-if="type === 'text'">
 | 
					            <template v-if="type === 'text'">
 | 
				
			||||||
                <a-input :value="value" @input="$emit('input', $event.target.value)"></a-input>
 | 
					                <a-input :value="value" @input="$emit('input', $event.target.value)" :placeholder="placeholder"></a-input>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
            <template v-else-if="type === 'number'">
 | 
					            <template v-else-if="type === 'number'">
 | 
				
			||||||
                <a-input-number :value="value" @change="value => $emit('input', value)" :min="min" style="width: 100%;"></a-input-number>
 | 
					                <a-input-number :value="value" :step="step" @change="value => $emit('input', value)" :min="min" style="width: 100%;"></a-input-number>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
            <template v-else-if="type === 'switch'">
 | 
					            <template v-else-if="type === 'switch'">
 | 
				
			||||||
                <a-switch :checked="value" @change="value => $emit('input', value)"></a-switch>
 | 
					                <a-switch :checked="value" @change="value => $emit('input', value)"></a-switch>
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@
 | 
				
			||||||
{{define "component/setting"}}
 | 
					{{define "component/setting"}}
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
    Vue.component('setting-list-item', {
 | 
					    Vue.component('setting-list-item', {
 | 
				
			||||||
        props: ["type", "title", "desc", "value", "min"],
 | 
					        props: ["type", "title", "desc", "value", "min", "step", "placeholder"],
 | 
				
			||||||
        template: `{{template "component/settingListItem"}}`,
 | 
					        template: `{{template "component/settingListItem"}}`,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -300,8 +300,7 @@
 | 
				
			||||||
            infoModal.visible = false;
 | 
					            infoModal.visible = false;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        genSubLink(subID) {
 | 
					        genSubLink(subID) {
 | 
				
			||||||
            const { domain: host, port, tls: isTLS, path: base } = app.subSettings;
 | 
					            return app.subSettings.subURI+subID+'?name='+subID;
 | 
				
			||||||
            return buildURL({ host, port, isTLS, base, path: subID+'?name='+remark });
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,14 +173,13 @@
 | 
				
			||||||
                        <a-table :columns="isMobile ? mobileColums : columns" :row-key="dbInbound => dbInbound.id"
 | 
					                        <a-table :columns="isMobile ? mobileColums : columns" :row-key="dbInbound => dbInbound.id"
 | 
				
			||||||
                                 :data-source="searchedInbounds"
 | 
					                                 :data-source="searchedInbounds"
 | 
				
			||||||
                                 :scroll="isMobile ? {} : { x: 1000 }"
 | 
					                                 :scroll="isMobile ? {} : { x: 1000 }"
 | 
				
			||||||
                                 :pagination="false"
 | 
					                                 :pagination=pagination(searchedInbounds)
 | 
				
			||||||
                                 :expand-icon-as-cell="false"
 | 
					                                 :expand-icon-as-cell="false"
 | 
				
			||||||
                                 :expand-row-by-click="false"
 | 
					                                 :expand-row-by-click="false"
 | 
				
			||||||
                                 :expand-icon-column-index="0"
 | 
					                                 :expand-icon-column-index="0"
 | 
				
			||||||
                                 :indent-size="0"
 | 
					                                 :indent-size="0"
 | 
				
			||||||
                                 :row-class-name="dbInbound => (dbInbound.isMultiUser() ? '' : 'hideExpandIcon')"
 | 
					                                 :row-class-name="dbInbound => (dbInbound.isMultiUser() ? '' : 'hideExpandIcon')"
 | 
				
			||||||
                                 style="margin-top: 10px"
 | 
					                                 style="margin-top: 10px">
 | 
				
			||||||
                                 @change="() => getDBInbounds()">
 | 
					 | 
				
			||||||
                            <template slot="action" slot-scope="text, dbInbound">
 | 
					                            <template slot="action" slot-scope="text, dbInbound">
 | 
				
			||||||
                                <a-icon type="edit" style="font-size: 22px" @click="openEditInbound(dbInbound.id);"></a-icon>
 | 
					                                <a-icon type="edit" style="font-size: 22px" @click="openEditInbound(dbInbound.id);"></a-icon>
 | 
				
			||||||
                                <a-dropdown :trigger="['click']">
 | 
					                                <a-dropdown :trigger="['click']">
 | 
				
			||||||
| 
						 | 
					@ -416,7 +415,7 @@
 | 
				
			||||||
                                :row-key="client => client.id"
 | 
					                                :row-key="client => client.id"
 | 
				
			||||||
                                :columns="isMobile ? innerMobileColumns : innerColumns"
 | 
					                                :columns="isMobile ? innerMobileColumns : innerColumns"
 | 
				
			||||||
                                :data-source="getInboundClients(record)"
 | 
					                                :data-source="getInboundClients(record)"
 | 
				
			||||||
                                :pagination="false"
 | 
					                                :pagination=pagination(getInboundClients(record))
 | 
				
			||||||
                                :style="isMobile ? 'margin: -16px -5px -17px;' : 'margin-left: 10px;'">
 | 
					                                :style="isMobile ? 'margin: -16px -5px -17px;' : 'margin-left: 10px;'">
 | 
				
			||||||
                                    {{template "client_table"}}
 | 
					                                    {{template "client_table"}}
 | 
				
			||||||
                                </a-table>
 | 
					                                </a-table>
 | 
				
			||||||
| 
						 | 
					@ -547,12 +546,10 @@
 | 
				
			||||||
            refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000,
 | 
					            refreshInterval: Number(localStorage.getItem("refreshInterval")) || 5000,
 | 
				
			||||||
            subSettings: {
 | 
					            subSettings: {
 | 
				
			||||||
                enable : false,
 | 
					                enable : false,
 | 
				
			||||||
                port: 0,
 | 
					                subURI : ''
 | 
				
			||||||
                path: '',
 | 
					 | 
				
			||||||
                domain: '',
 | 
					 | 
				
			||||||
                tls: false
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            tgBotEnable: false,
 | 
					            tgBotEnable: false,
 | 
				
			||||||
 | 
					            pageSize: 0,
 | 
				
			||||||
            isMobile: window.innerWidth <= 768,
 | 
					            isMobile: window.innerWidth <= 768,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        methods: {
 | 
					        methods: {
 | 
				
			||||||
| 
						 | 
					@ -592,11 +589,9 @@
 | 
				
			||||||
                    this.tgBotEnable = tgBotEnable;
 | 
					                    this.tgBotEnable = tgBotEnable;
 | 
				
			||||||
                    this.subSettings = {
 | 
					                    this.subSettings = {
 | 
				
			||||||
                        enable : subEnable,
 | 
					                        enable : subEnable,
 | 
				
			||||||
                        port: subPort,
 | 
					                        subURI: subURI
 | 
				
			||||||
                        path: subPath,
 | 
					 | 
				
			||||||
                        domain: subDomain,
 | 
					 | 
				
			||||||
                        tls: subTLS
 | 
					 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					                    this.pageSize = pageSize;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            setInbounds(dbInbounds) {
 | 
					            setInbounds(dbInbounds) {
 | 
				
			||||||
| 
						 | 
					@ -1216,6 +1211,27 @@
 | 
				
			||||||
                    this.spinning = false;
 | 
					                    this.spinning = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            pagination(obj){
 | 
				
			||||||
 | 
					                if (this.pageSize > 0 && obj.length>this.pageSize) {
 | 
				
			||||||
 | 
					                    // Set page options based on object size
 | 
				
			||||||
 | 
					                    sizeOptions = []
 | 
				
			||||||
 | 
					                    for (i=this.pageSize;i<=obj.length;i=i+this.pageSize) {
 | 
				
			||||||
 | 
					                        sizeOptions.push(i.toString());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // Add option to see all in one page
 | 
				
			||||||
 | 
					                    sizeOptions.push(i.toString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    p = {
 | 
				
			||||||
 | 
					                        showSizeChanger: true,
 | 
				
			||||||
 | 
					                        size: 'small',
 | 
				
			||||||
 | 
					                        position: 'bottom',
 | 
				
			||||||
 | 
					                        pageSize: this.pageSize,
 | 
				
			||||||
 | 
					                        pageSizeOptions: sizeOptions
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return p
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return false
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            onResize() {
 | 
					            onResize() {
 | 
				
			||||||
                this.isMobile = window.innerWidth <= 768;
 | 
					                this.isMobile = window.innerWidth <= 768;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,6 +112,7 @@
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.privateKeyPath"}}' desc='{{ i18n "pages.settings.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.privateKeyPath"}}' desc='{{ i18n "pages.settings.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.panelUrlPath"}}' desc='{{ i18n "pages.settings.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.panelUrlPath"}}' desc='{{ i18n "pages.settings.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="number" title='{{ i18n "pages.settings.sessionMaxAge" }}' desc='{{ i18n "pages.settings.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="0"></setting-list-item>
 | 
					                                <setting-list-item type="number" title='{{ i18n "pages.settings.sessionMaxAge" }}' desc='{{ i18n "pages.settings.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="0"></setting-list-item>
 | 
				
			||||||
 | 
					                                <setting-list-item type="number" title='{{ i18n "pages.settings.pageSize" }}' desc='{{ i18n "pages.settings.pageSizeDesc" }}' v-model="allSetting.pageSize" :min="0" :step="5"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
 | 
					                                <setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
 | 
					                                <setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.timeZone"}}' desc='{{ i18n "pages.settings.timeZoneDesc"}}' v-model="allSetting.timeLocation"></setting-list-item>
 | 
				
			||||||
| 
						 | 
					@ -243,6 +244,7 @@
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.subPath"}}' desc='{{ i18n "pages.settings.subPathDesc"}}' v-model="allSetting.subPath"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.subPath"}}' desc='{{ i18n "pages.settings.subPathDesc"}}' v-model="allSetting.subPath"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.subCertPath"}}' desc='{{ i18n "pages.settings.subCertPathDesc"}}' v-model="allSetting.subCertFile"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.subCertPath"}}' desc='{{ i18n "pages.settings.subCertPathDesc"}}' v-model="allSetting.subCertFile"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="text" title='{{ i18n "pages.settings.subKeyPath"}}' desc='{{ i18n "pages.settings.subKeyPathDesc"}}' v-model="allSetting.subKeyFile"></setting-list-item>
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.subKeyPath"}}' desc='{{ i18n "pages.settings.subKeyPathDesc"}}' v-model="allSetting.subKeyFile"></setting-list-item>
 | 
				
			||||||
 | 
					                                <setting-list-item type="text" title='{{ i18n "pages.settings.subURI"}}' desc='{{ i18n "pages.settings.subURIDesc"}}' v-model="allSetting.subURI" placeholder="(http|https)://domain[:port]/path/"></setting-list-item>
 | 
				
			||||||
                                <setting-list-item type="number" title='{{ i18n "pages.settings.subUpdates"}}' desc='{{ i18n "pages.settings.subUpdatesDesc"}}' v-model="allSetting.subUpdates"></setting-list-item>
 | 
					                                <setting-list-item type="number" title='{{ i18n "pages.settings.subUpdates"}}' desc='{{ i18n "pages.settings.subUpdatesDesc"}}' v-model="allSetting.subUpdates"></setting-list-item>
 | 
				
			||||||
                            </a-list>
 | 
					                            </a-list>
 | 
				
			||||||
                        </a-tab-pane>
 | 
					                        </a-tab-pane>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ var defaultValueMap = map[string]string{
 | 
				
			||||||
	"secret":             random.Seq(32),
 | 
						"secret":             random.Seq(32),
 | 
				
			||||||
	"webBasePath":        "/",
 | 
						"webBasePath":        "/",
 | 
				
			||||||
	"sessionMaxAge":      "0",
 | 
						"sessionMaxAge":      "0",
 | 
				
			||||||
 | 
						"pageSize":           "0",
 | 
				
			||||||
	"expireDiff":         "0",
 | 
						"expireDiff":         "0",
 | 
				
			||||||
	"trafficDiff":        "0",
 | 
						"trafficDiff":        "0",
 | 
				
			||||||
	"timeLocation":       "Asia/Tehran",
 | 
						"timeLocation":       "Asia/Tehran",
 | 
				
			||||||
| 
						 | 
					@ -53,6 +54,7 @@ var defaultValueMap = map[string]string{
 | 
				
			||||||
	"subUpdates":         "12",
 | 
						"subUpdates":         "12",
 | 
				
			||||||
	"subEncrypt":         "true",
 | 
						"subEncrypt":         "true",
 | 
				
			||||||
	"subShowInfo":        "true",
 | 
						"subShowInfo":        "true",
 | 
				
			||||||
 | 
						"subURI":             "",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SettingService struct {
 | 
					type SettingService struct {
 | 
				
			||||||
| 
						 | 
					@ -406,6 +408,14 @@ func (s *SettingService) GetSubShowInfo() (bool, error) {
 | 
				
			||||||
	return s.getBool("subShowInfo")
 | 
						return s.getBool("subShowInfo")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SettingService) GetSubURI() (string, error) {
 | 
				
			||||||
 | 
						return s.getString("subURI")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SettingService) GetPageSize() (int, error) {
 | 
				
			||||||
 | 
						return s.getInt("pageSize")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
 | 
					func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
 | 
				
			||||||
	if err := allSetting.CheckValid(); err != nil {
 | 
						if err := allSetting.CheckValid(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -435,3 +445,61 @@ func (s *SettingService) GetDefaultXrayConfig() (interface{}, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return jsonData, nil
 | 
						return jsonData, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) {
 | 
				
			||||||
 | 
						type settingFunc func() (interface{}, error)
 | 
				
			||||||
 | 
						settings := map[string]settingFunc{
 | 
				
			||||||
 | 
							"expireDiff":  func() (interface{}, error) { return s.GetExpireDiff() },
 | 
				
			||||||
 | 
							"trafficDiff": func() (interface{}, error) { return s.GetTrafficDiff() },
 | 
				
			||||||
 | 
							"pageSize":    func() (interface{}, error) { return s.GetPageSize() },
 | 
				
			||||||
 | 
							"defaultCert": func() (interface{}, error) { return s.GetCertFile() },
 | 
				
			||||||
 | 
							"defaultKey":  func() (interface{}, error) { return s.GetKeyFile() },
 | 
				
			||||||
 | 
							"tgBotEnable": func() (interface{}, error) { return s.GetTgbotenabled() },
 | 
				
			||||||
 | 
							"subEnable":   func() (interface{}, error) { return s.GetSubEnable() },
 | 
				
			||||||
 | 
							"subURI":      func() (interface{}, error) { return s.GetSubURI() },
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := make(map[string]interface{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for key, fn := range settings {
 | 
				
			||||||
 | 
							value, err := fn()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							result[key] = value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if result["subEnable"].(bool) && result["subURI"].(string) == "" {
 | 
				
			||||||
 | 
							subURI := ""
 | 
				
			||||||
 | 
							subPort, _ := s.GetSubPort()
 | 
				
			||||||
 | 
							subPath, _ := s.GetSubPath()
 | 
				
			||||||
 | 
							subDomain, _ := s.GetSubDomain()
 | 
				
			||||||
 | 
							subKeyFile, _ := s.GetSubKeyFile()
 | 
				
			||||||
 | 
							subCertFile, _ := s.GetSubCertFile()
 | 
				
			||||||
 | 
							subTLS := false
 | 
				
			||||||
 | 
							if subKeyFile != "" && subCertFile != "" {
 | 
				
			||||||
 | 
								subTLS = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if subDomain == "" {
 | 
				
			||||||
 | 
								subDomain = strings.Split(host, ":")[0]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if subTLS {
 | 
				
			||||||
 | 
								subURI = "https://"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								subURI = "http://"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (subPort == 443 && subTLS) || (subPort == 80 && !subTLS) {
 | 
				
			||||||
 | 
								subURI += subDomain
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								subURI += fmt.Sprintf("%s:%d", subDomain, subPort)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if subPath[0] == byte('/') {
 | 
				
			||||||
 | 
								subURI += subPath
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								subURI += "/" + subPath
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							result["subURI"] = subURI
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,8 @@
 | 
				
			||||||
"privateKeyPathDesc" = "Fill in an absolute path starting with."
 | 
					"privateKeyPathDesc" = "Fill in an absolute path starting with."
 | 
				
			||||||
"panelUrlPath" = "Panel URL Root Path"
 | 
					"panelUrlPath" = "Panel URL Root Path"
 | 
				
			||||||
"panelUrlPathDesc" = "Must start with '/' and end with."
 | 
					"panelUrlPathDesc" = "Must start with '/' and end with."
 | 
				
			||||||
 | 
					"pageSize" = "Pagination size"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable"
 | 
				
			||||||
"oldUsername" = "Current Username"
 | 
					"oldUsername" = "Current Username"
 | 
				
			||||||
"currentPassword" = "Current Password"
 | 
					"currentPassword" = "Current Password"
 | 
				
			||||||
"newUsername" = "New Username"
 | 
					"newUsername" = "New Username"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "Encrypt the returned configs in subscription"
 | 
					"subEncryptDesc" = "Encrypt the returned configs in subscription"
 | 
				
			||||||
"subShowInfo" = "Show usage info"
 | 
					"subShowInfo" = "Show usage info"
 | 
				
			||||||
"subShowInfoDesc" = "Show remianed traffic and date after config name"
 | 
					"subShowInfoDesc" = "Show remianed traffic and date after config name"
 | 
				
			||||||
 | 
					"subURI" = "Reverse Proxy URI"
 | 
				
			||||||
 | 
					"subURIDesc" = "Change base URI of subscription URL for using on behind of proxies"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "Xray Settings"
 | 
					"title" = "Xray Settings"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,8 @@
 | 
				
			||||||
"privateKeyPathDesc" = "Complete con una ruta absoluta que comience con."
 | 
					"privateKeyPathDesc" = "Complete con una ruta absoluta que comience con."
 | 
				
			||||||
"panelUrlPath" = "Ruta Raíz de la URL del Panel"
 | 
					"panelUrlPath" = "Ruta Raíz de la URL del Panel"
 | 
				
			||||||
"panelUrlPathDesc" = "Debe empezar con '/' y terminar con."
 | 
					"panelUrlPathDesc" = "Debe empezar con '/' y terminar con."
 | 
				
			||||||
 | 
					"pageSize" = "Tamaño de paginación"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar"
 | 
				
			||||||
"oldUsername" = "Nombre de Usuario Actual"
 | 
					"oldUsername" = "Nombre de Usuario Actual"
 | 
				
			||||||
"currentPassword" = "Contraseña Actual"
 | 
					"currentPassword" = "Contraseña Actual"
 | 
				
			||||||
"newUsername" = "Nuevo Nombre de Usuario"
 | 
					"newUsername" = "Nuevo Nombre de Usuario"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "Encriptar las configuraciones devueltas en la suscripción."
 | 
					"subEncryptDesc" = "Encriptar las configuraciones devueltas en la suscripción."
 | 
				
			||||||
"subShowInfo" = "Mostrar información de uso"
 | 
					"subShowInfo" = "Mostrar información de uso"
 | 
				
			||||||
"subShowInfoDesc" = "Mostrar tráfico restante y fecha después del nombre de configuración."
 | 
					"subShowInfoDesc" = "Mostrar tráfico restante y fecha después del nombre de configuración."
 | 
				
			||||||
 | 
					"subURI" = "URI de proxy inverso"
 | 
				
			||||||
 | 
					"subURIDesc" = "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "Xray Configuración"
 | 
					"title" = "Xray Configuración"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,8 @@
 | 
				
			||||||
"privateKeyPathDesc" = "باید یک مسیر مطلق باشد که با / شروع می شود "
 | 
					"privateKeyPathDesc" = "باید یک مسیر مطلق باشد که با / شروع می شود "
 | 
				
			||||||
"panelUrlPath" = "آدرس روت پنل"
 | 
					"panelUrlPath" = "آدرس روت پنل"
 | 
				
			||||||
"panelUrlPathDesc" = "باید با '/' شروع شود و با '/' تمام شود"
 | 
					"panelUrlPathDesc" = "باید با '/' شروع شود و با '/' تمام شود"
 | 
				
			||||||
 | 
					"pageSize" = "اندازه صفحه بندی جدول"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال"
 | 
				
			||||||
"oldUsername" = "نام کاربری فعلی"
 | 
					"oldUsername" = "نام کاربری فعلی"
 | 
				
			||||||
"currentPassword" = "رمز عبور فعلی"
 | 
					"currentPassword" = "رمز عبور فعلی"
 | 
				
			||||||
"newUsername" = "نام کاربری جدید"
 | 
					"newUsername" = "نام کاربری جدید"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "رمزگذاری کانفیگ های بازگشتی سابسکریپشن"
 | 
					"subEncryptDesc" = "رمزگذاری کانفیگ های بازگشتی سابسکریپشن"
 | 
				
			||||||
"subShowInfo" = "نمایش اطلاعات مصرف"
 | 
					"subShowInfo" = "نمایش اطلاعات مصرف"
 | 
				
			||||||
"subShowInfoDesc" = "ترافیک و زمان باقیمانده را در هر کانفیگ نمایش میدهد"
 | 
					"subShowInfoDesc" = "ترافیک و زمان باقیمانده را در هر کانفیگ نمایش میدهد"
 | 
				
			||||||
 | 
					"subURI" = "آدرس پایه پروکسی معکوس"
 | 
				
			||||||
 | 
					"subURIDesc" = "آدرس پایه سابسکریپشن را برای استفاده در پشت پراکسی ها تغییر میدهد"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "الگوها"
 | 
					"title" = "الگوها"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,11 +233,13 @@
 | 
				
			||||||
"panelPort" = "Порт панели"
 | 
					"panelPort" = "Порт панели"
 | 
				
			||||||
"panelPortDesc" = "Порт, используемый для отображения этой панели"
 | 
					"panelPortDesc" = "Порт, используемый для отображения этой панели"
 | 
				
			||||||
"publicKeyPath" = "Путь к файлу публичного ключа сертификата панели"
 | 
					"publicKeyPath" = "Путь к файлу публичного ключа сертификата панели"
 | 
				
			||||||
"publicKeyPathDesc" = "Введите полный путь, начинающийся с "
 | 
					"publicKeyPathDesc" = "Введите полный путь, начинающийся с"
 | 
				
			||||||
"privateKeyPath" = "Путь к файлу приватного ключа сертификата панели"
 | 
					"privateKeyPath" = "Путь к файлу приватного ключа сертификата панели"
 | 
				
			||||||
"privateKeyPathDesc" = "Введите полный путь, начинающийся с "
 | 
					"privateKeyPathDesc" = "Введите полный путь, начинающийся с"
 | 
				
			||||||
"panelUrlPath" = "Корневой путь URL адреса панели"
 | 
					"panelUrlPath" = "Корневой путь URL адреса панели"
 | 
				
			||||||
"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться на "
 | 
					"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться на"
 | 
				
			||||||
 | 
					"pageSize" = "Размер нумерации страниц"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить"
 | 
				
			||||||
"oldUsername" = "Текущее имя пользователя"
 | 
					"oldUsername" = "Текущее имя пользователя"
 | 
				
			||||||
"currentPassword" = "Текущий пароль"
 | 
					"currentPassword" = "Текущий пароль"
 | 
				
			||||||
"newUsername" = "Новое имя пользователя"
 | 
					"newUsername" = "Новое имя пользователя"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "Шифровать возвращенные конфиги в подписке"
 | 
					"subEncryptDesc" = "Шифровать возвращенные конфиги в подписке"
 | 
				
			||||||
"subShowInfo" = "Показать информацию об использовании"
 | 
					"subShowInfo" = "Показать информацию об использовании"
 | 
				
			||||||
"subShowInfoDesc" = "Показывать восстановленный трафик и дату после имени конфигурации"
 | 
					"subShowInfoDesc" = "Показывать восстановленный трафик и дату после имени конфигурации"
 | 
				
			||||||
 | 
					"subURI" = "URI обратного прокси"
 | 
				
			||||||
 | 
					"subURIDesc" = "Изменить базовый URI URL-адреса подписки для использования за прокси-серверами"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "Xray Настройки"
 | 
					"title" = "Xray Настройки"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,8 @@
 | 
				
			||||||
"privateKeyPathDesc" = "Điền vào đường dẫn tuyệt đối bắt đầu với."
 | 
					"privateKeyPathDesc" = "Điền vào đường dẫn tuyệt đối bắt đầu với."
 | 
				
			||||||
"panelUrlPath" = "Đường dẫn gốc URL Bảng điều khiển"
 | 
					"panelUrlPath" = "Đường dẫn gốc URL Bảng điều khiển"
 | 
				
			||||||
"panelUrlPathDesc" = "Phải bắt đầu bằng '/' và kết thúc bằng."
 | 
					"panelUrlPathDesc" = "Phải bắt đầu bằng '/' và kết thúc bằng."
 | 
				
			||||||
 | 
					"pageSize" = "Kích thước phân trang"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt"
 | 
				
			||||||
"oldUsername" = "Tên người dùng hiện tại"
 | 
					"oldUsername" = "Tên người dùng hiện tại"
 | 
				
			||||||
"currentPassword" = "Mật khẩu hiện tại"
 | 
					"currentPassword" = "Mật khẩu hiện tại"
 | 
				
			||||||
"newUsername" = "Tên người dùng mới"
 | 
					"newUsername" = "Tên người dùng mới"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "Mã hóa các cấu hình được trả về trong đăng ký"
 | 
					"subEncryptDesc" = "Mã hóa các cấu hình được trả về trong đăng ký"
 | 
				
			||||||
"subShowInfo" = "Hiển thị thông tin sử dụng"
 | 
					"subShowInfo" = "Hiển thị thông tin sử dụng"
 | 
				
			||||||
"subShowInfoDesc" = "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình"
 | 
					"subShowInfoDesc" = "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình"
 | 
				
			||||||
 | 
					"subURI" = "URI proxy ngược"
 | 
				
			||||||
 | 
					"subURIDesc" = "Thay đổi URI cơ sở của URL đăng ký để sử dụng ở phía sau proxy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "Xray Cài đặt"
 | 
					"title" = "Xray Cài đặt"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,6 +238,8 @@
 | 
				
			||||||
"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径"
 | 
					"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径"
 | 
				
			||||||
"panelUrlPath" = "面板 url 根路径"
 | 
					"panelUrlPath" = "面板 url 根路径"
 | 
				
			||||||
"panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾"
 | 
					"panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾"
 | 
				
			||||||
 | 
					"pageSize" = "分页大小"
 | 
				
			||||||
 | 
					"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
 | 
				
			||||||
"oldUsername" = "原用户名"
 | 
					"oldUsername" = "原用户名"
 | 
				
			||||||
"currentPassword" = "原密码"
 | 
					"currentPassword" = "原密码"
 | 
				
			||||||
"newUsername" = "新用户名"
 | 
					"newUsername" = "新用户名"
 | 
				
			||||||
| 
						 | 
					@ -285,6 +287,8 @@
 | 
				
			||||||
"subEncryptDesc" = "在订阅中加密返回的配置"
 | 
					"subEncryptDesc" = "在订阅中加密返回的配置"
 | 
				
			||||||
"subShowInfo" = "显示使用信息"
 | 
					"subShowInfo" = "显示使用信息"
 | 
				
			||||||
"subShowInfoDesc" = "在配置名称后显示剩余流量和日期"
 | 
					"subShowInfoDesc" = "在配置名称后显示剩余流量和日期"
 | 
				
			||||||
 | 
					"subURI" = "反向代理 URI"
 | 
				
			||||||
 | 
					"subURIDesc" = "更改订阅 URL 的基本 URI 以在代理后面使用"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[pages.xray]
 | 
					[pages.xray]
 | 
				
			||||||
"title" = "Xray 设置"
 | 
					"title" = "Xray 设置"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue