diff --git a/web/html/common/text_modal.html b/web/html/common/text_modal.html index b2da6160..ce77d0ca 100644 --- a/web/html/common/text_modal.html +++ b/web/html/common/text_modal.html @@ -4,7 +4,8 @@ :class="siderDrawer.isDarkTheme ? darkClass : ''" :ok-button-props="{attrs:{id:'txt-modal-ok-btn'}}"> + :href="'data:application/text;charset=utf-8,' + encodeURIComponent(txtModal.content)" + :download="txtModal.fileName"> {{ i18n "download" }} [[ txtModal.fileName ]] {{ i18n "menu.link" }}: - Log Reports - Config - Backup + {{ i18n "pages.index.logs" }} + {{ i18n "pages.index.config" }} + {{ i18n "pages.index.backup" }} @@ -188,6 +188,7 @@ + + - + + + +

+ + [[ backupModal.description ]] +

+ + + [[ backupModal.exportText ]] + + + [[ backupModal.importText ]] + + +
+ {{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) {