| 
					
				 | 
			
			
				@@ -111,9 +111,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     <a-col :sm="24" :md="12"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         <a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             {{ i18n "menu.link" }}: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">Log Reports</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            <a-tag color="blue" style="cursor: pointer;" @click="openConfig">Config</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            <a-tag color="blue" style="cursor: pointer;" @click="getBackup">Backup</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ i18n "pages.index.logs" }}</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            <a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            <a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         </a-card> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     </a-col> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     <a-col :sm="24" :md="12"> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -188,6 +188,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             </transition> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </a-layout-content> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </a-layout> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              :closable="true" @ok="() => versionModal.visible = false" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              :class="siderDrawer.isDarkTheme ? darkClass : ''" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -201,6 +202,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             </a-tag> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </a-modal> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <a-modal id="log-modal" v-model="logModal.visible" title="X-UI logs" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              :closable="true" @ok="() => logModal.visible = false" @cancel="() => logModal.visible = false" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              :class="siderDrawer.isDarkTheme ? darkClass : ''" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -227,10 +229,28 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     {{ i18n "download" }} x-ui.log 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 </a-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             </a-form-item> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       </a-form> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </a-form> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <a-input type="textarea" v-model="logModal.logs" disabled="true" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 :autosize="{ minRows: 10, maxRows: 22}"></a-input> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </a-modal> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <a-modal id="backup-modal" v-model="backupModal.visible" :title="backupModal.title" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            :closable="true" :class="siderDrawer.isDarkTheme ? darkClass : ''" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            @ok="() => backupModal.hide()" @cancel="() => backupModal.hide()"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <p style="color: inherit; font-size: 16px; padding: 4px 2px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <a-icon type="warning" style="color: inherit; font-size: 20px;"></a-icon> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            [[ backupModal.description ]] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </p> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <a-space direction="horizontal" align="center" style="margin-bottom: 10px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <a-button type="primary" @click="exportDatabase()"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                [[ backupModal.exportText ]] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </a-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            <a-button type="primary" @click="importDatabase()"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                [[ backupModal.importText ]] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            </a-button> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </a-space> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </a-modal> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </a-layout> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {{template "js" .}} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 {{template "textModal"}} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -339,6 +359,29 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const backupModal = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        visible: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        title: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        description: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exportText: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        importText: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        show({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            title = '{{ i18n "pages.index.backupTitle" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            description = '{{ i18n "pages.index.backupDescription" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportText = '{{ i18n "pages.index.exportDatabase" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            importText = '{{ i18n "pages.index.importDatabase" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.title = title; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.description = description; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.exportText = exportText; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.importText = importText; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.visible = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        hide() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.visible = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const app = new Vue({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         delimiters: ['[[', ']]'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         el: '#app', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -347,6 +390,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             status: new Status(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             versionModal, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             logModal, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            backupModal, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             spinning: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             loadingTip: '{{ i18n "loading"}}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -388,7 +432,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	        //here add stop xray function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             async stopXrayService() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const msg = await HttpUtil.post('server/stopXrayService'); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -397,7 +440,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //here add restart xray function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             async restartXrayService() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const msg = await HttpUtil.post('server/restartXrayService'); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -413,20 +455,60 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (!msg.success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                logModal.show(msg.obj,rows); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                logModal.show(msg.obj, rows); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            async openConfig(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            async openConfig() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const msg = await HttpUtil.post('server/getConfigJson'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 this.loading(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (!msg.success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                txtModal.show('config.json',JSON.stringify(msg.obj, null, 2),'config.json'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                txtModal.show('config.json', JSON.stringify(msg.obj, null, 2), 'config.json'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            getBackup(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            openBackup() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                backupModal.show({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    title: '{{ i18n "pages.index.backupTitle" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    description: '{{ i18n "pages.index.backupDescription" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    exportText: '{{ i18n "pages.index.exportDatabase" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    importText: '{{ i18n "pages.index.importDatabase" }}', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            exportDatabase() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 window.location = basePath + 'server/getDb'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            importDatabase() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const fileInput = document.createElement('input'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileInput.type = 'file'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileInput.accept = '.db'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileInput.addEventListener('change', async (event) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const dbFile = event.target.files[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (dbFile) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        const formData = new FormData(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        formData.append('db', dbFile); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        backupModal.hide(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        const uploadMsg = await HttpUtil.post('server/importDB', formData, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            headers: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                'Content-Type': 'multipart/form-data', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        this.loading(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!uploadMsg.success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        const restartMsg = await HttpUtil.post("/xui/setting/restartPanel"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        this.loading(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (restartMsg.success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            this.loading(true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            await PromiseUtil.sleep(5000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            location.reload(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                fileInput.click(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         async mounted() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             while (true) { 
			 |