mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-28 05:57:19 +00:00
feat(frontend): Phase 5c-iv (a) — panel update / logs / backup modals
Adds three of the six dashboard modals plus a Quick Actions card that surfaces them. The remaining three (xray logs, version picker, CPU history sparkline) ship in 5c-iv-b. - PanelUpdateModal.vue — current vs latest version, "update now" button. Confirm dialog → POST /panel/api/server/updatePanel, then poll /server/status for up to 90s until the new panel answers, then reload. - LogModal.vue — panel logs viewer. Filters: rows (10-500), level (debug/info/notice/warning/error), syslog toggle. Auto-fetches on open and on every filter change. Color-coded timestamps and levels via inline span styles. Download button writes the raw log to x-ui.log via FileManager.downloadTextFile. - BackupModal.vue — db export (window.location to /getDb) and import (FormData upload to /importDB, then panel restart + reload). - Quick Actions card surfaces Logs / Backup / Update buttons and shows an orange update badge (extra slot) when an update is available. Modal-busy pattern: long-running operations (update, import) emit a `busy` event with a tip; IndexPage flips its a-spin overlay so the user sees a loading message while the panel is restarting. AD-Vue 4 changes: - v-model on <a-modal> renamed to v-model:open - v-model on <a-input>/<a-select>/<a-checkbox> uses the named v-model:value / v-model:checked pattern - <a-icon type="..."> dropped — explicit Ant icon imports (BarsOutlined, CloudServerOutlined, CloudDownloadOutlined, DownloadOutlined, UploadOutlined, SyncOutlined) - Modal.confirm() replaces this.$confirm() since setup() has no `this` Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<script setup>
|
||||
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons-vue';
|
||||
import { HttpUtil, PromiseUtil } from '@/utils';
|
||||
|
||||
defineProps({
|
||||
open: { type: Boolean, default: false },
|
||||
basePath: { type: String, default: '' },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:open', 'busy']);
|
||||
|
||||
function close() {
|
||||
emit('update:open', false);
|
||||
}
|
||||
|
||||
function exportDb() {
|
||||
// The Go endpoint streams x-ui.db as a download. Setting
|
||||
// window.location triggers a browser download without leaving
|
||||
// the page (the Go side responds with Content-Disposition: attachment).
|
||||
window.location = '/panel/api/server/getDb';
|
||||
}
|
||||
|
||||
function importDb() {
|
||||
const fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.accept = '.db';
|
||||
fileInput.addEventListener('change', async (e) => {
|
||||
const dbFile = e.target.files?.[0];
|
||||
if (!dbFile) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('db', dbFile);
|
||||
|
||||
close();
|
||||
emit('busy', { busy: true, tip: 'Importing database…' });
|
||||
|
||||
const upload = await HttpUtil.post('/panel/api/server/importDB', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
if (!upload?.success) {
|
||||
emit('busy', { busy: false });
|
||||
return;
|
||||
}
|
||||
|
||||
emit('busy', { busy: true, tip: 'Restarting panel…' });
|
||||
const restart = await HttpUtil.post('/panel/setting/restartPanel');
|
||||
if (restart?.success) {
|
||||
await PromiseUtil.sleep(5000);
|
||||
window.location.reload();
|
||||
} else {
|
||||
emit('busy', { busy: false });
|
||||
}
|
||||
});
|
||||
fileInput.click();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal :open="open" title="Database backup & restore" :closable="true" :footer="null" @cancel="close">
|
||||
<a-list bordered class="backup-list">
|
||||
<a-list-item class="backup-item">
|
||||
<a-list-item-meta>
|
||||
<template #title>Back up</template>
|
||||
<template #description>Click to download a .db file containing a backup of your current database to your device.</template>
|
||||
</a-list-item-meta>
|
||||
<a-button type="primary" @click="exportDb">
|
||||
<template #icon><DownloadOutlined /></template>
|
||||
</a-button>
|
||||
</a-list-item>
|
||||
|
||||
<a-list-item class="backup-item">
|
||||
<a-list-item-meta>
|
||||
<template #title>Restore</template>
|
||||
<template #description>Click to upload a .db file. The panel restarts after restore — your session will reconnect automatically.</template>
|
||||
</a-list-item-meta>
|
||||
<a-button type="primary" @click="importDb">
|
||||
<template #icon><UploadOutlined /></template>
|
||||
</a-button>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.backup-list { width: 100%; }
|
||||
.backup-item { display: flex; align-items: center; gap: 16px; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user