diff --git a/backend/package.json b/backend/package.json index 07ed9c7..5f5723c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -2,7 +2,7 @@ "name": "backend", "type": "module", "scripts": { - "dev": "wrangler dev --config ../wrangler.dev.toml --host 0.0.0.0 --port 8787 --test-scheduled", + "dev": "wrangler dev --config ../wrangler.dev.toml --ip 0.0.0.0 --port 8787 --test-scheduled", "deploy": "wrangler deploy --minify" }, "dependencies": { @@ -15,7 +15,7 @@ "@cloudflare/workers-types": "^4.20260226.1", "drizzle-kit": "^0.31.9", "typescript": "^5.9.3", - "wrangler": "^4.69.0" + "wrangler": "^4.71.0" }, "overrides": { "esbuild": ">=0.25.0" diff --git a/frontend/package.json b/frontend/package.json index de71dbe..e29cd5d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,15 +10,12 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.3.2", - "@noble/ciphers": "^2.1.1", - "@noble/hashes": "^2.0.1", "@tanstack/vue-query": "^5.66.0", "argon2-browser": "^1.18.0", "bcryptjs": "^3.0.3", "element-plus": "^2.9.5", "hash-wasm": "^4.12.0", "jsqr": "^1.4.0", - "libsodium-wrappers": "^0.8.2", "libsodium-wrappers-sumo": "^0.8.2", "pinia": "^3.0.4", "qrcode": "^1.5.4", diff --git a/frontend/src/app/app.vue b/frontend/src/app/app.vue index c862b68..5a86f06 100644 --- a/frontend/src/app/app.vue +++ b/frontend/src/app/app.vue @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/frontend/src/features/backup/components/backupSettings.vue b/frontend/src/features/backup/components/backupSettings.vue index da0b22b..e24ce80 100644 --- a/frontend/src/features/backup/components/backupSettings.vue +++ b/frontend/src/features/backup/components/backupSettings.vue @@ -66,34 +66,14 @@ - + - - - - - - - - - - - - ****** - {{ $t('backup.modify') }} - - - - - - - @@ -139,6 +119,27 @@ + + + + + + + + + + + + ****** + {{ $t('backup.modify') }} + + + + + + + + {{ $t('backup.auto_backup_config') }} @@ -162,7 +163,6 @@ {{ $t('backup.retain_zero_tip') }} - {{ $t('backup.test_connection') }} diff --git a/frontend/src/features/backup/composables/useBackupProviders.js b/frontend/src/features/backup/composables/useBackupProviders.js index 5a59cc2..5dbc15f 100644 --- a/frontend/src/features/backup/composables/useBackupProviders.js +++ b/frontend/src/features/backup/composables/useBackupProviders.js @@ -21,7 +21,7 @@ export function useBackupProviders() { const isEditingTelegramToken = ref(false) const initialFormState = () => ({ - type: 'webdav', + type: 's3', name: '', config: { url: '', username: '', password: '', saveDir: '/2fauth-worker-backup', endpoint: '', bucket: '', region: 'auto', accessKeyId: '', secretAccessKey: '', botToken: '', chatId: '' }, autoBackup: false, @@ -104,7 +104,7 @@ export function useBackupProviders() { return null } if (!form.value.autoBackupPassword || form.value.autoBackupPassword.length < 12) { - return '自动备份密码长度必须至少 12 位' + return t('backup.password_min_length') } } return null @@ -121,7 +121,7 @@ export function useBackupProviders() { form.value.config, isEditing.value ? currentProviderId.value : null ) - if (res.success) ElMessage.success('连接成功') + if (res.success) ElMessage.success(t('backup.test_success')) } catch (e) { // Already handled by request.js global error handler } finally { isTesting.value = false } @@ -141,7 +141,7 @@ export function useBackupProviders() { ? await backupService.updateProvider(currentProviderId.value, form.value) : await backupService.createProvider(form.value) if (res.success) { - ElMessage.success('保存成功') + ElMessage.success(t('backup.save_success')) showConfigDialog.value = false await fetchProviders() } @@ -152,7 +152,7 @@ export function useBackupProviders() { const deleteProvider = async (provider) => { try { - await ElMessageBox.confirm('确定删除该备份源吗?', '警告', { type: 'warning' }) + await ElMessageBox.confirm(t('backup.delete_provider_confirm'), t('common.warning'), { type: 'warning' }) await backupService.deleteProvider(provider.id) await fetchProviders() } catch (e) { diff --git a/frontend/src/features/health/views/healthCheck.vue b/frontend/src/features/health/views/healthCheck.vue index cf2d4b8..252033a 100644 --- a/frontend/src/features/health/views/healthCheck.vue +++ b/frontend/src/features/health/views/healthCheck.vue @@ -103,6 +103,7 @@ import { WarningFilled, CopyDocument, Refresh, Document, Select, Monitor, Settin import { ElMessage } from 'element-plus' import { request } from '@/shared/utils/request' import { useClipboard } from '@vueuse/core' +import { i18n } from '@/locales' const router = useRouter() const { copy, isSupported } = useClipboard() @@ -135,11 +136,11 @@ const generateNewKey = (field) => { const copyKey = async (field) => { if (!isSupported.value) { - ElMessage.error('您的浏览器不支持自动复制,请手动选中复制。') + ElMessage.error(i18n.global.t('healthCheck.copy_unsupported')) return } await copy(generatedKeys.value[field]) - ElMessage.success('安全密钥已复制到剪贴板') + ElMessage.success(i18n.global.t('healthCheck.copy_success')) } const checkHealth = async () => { @@ -178,7 +179,7 @@ const checkHealth = async () => { } }) } else { - ElMessage.error('无法连接到服务端进行安全校验') + ElMessage.error(i18n.global.t('healthCheck.connection_failed')) } } finally { loading.value = false diff --git a/frontend/src/features/migration/views/dataImport.vue b/frontend/src/features/migration/views/dataImport.vue index dddc0fd..cb29ae8 100644 --- a/frontend/src/features/migration/views/dataImport.vue +++ b/frontend/src/features/migration/views/dataImport.vue @@ -201,14 +201,18 @@ const { } .tags span.el-tag { - padding: 8px 15px; + padding: 4px 8px; /* 减小内边距,使其不那么像按钮 */ height: auto; color: var(--el-text-color-regular); + cursor: default; /* 明确鼠标状态不是可点击的 */ + border-color: transparent; /* 去除边框,使其更像高亮文本 */ + background-color: var(--el-fill-color-light); /* 更浅的背景色 */ } .tags span i.el-icon { display: inline-flex; flex-wrap: wrap; + margin-right: 4px; /* 图标和文字之间增加一点点间距 */ } .ga-tip { diff --git a/frontend/src/features/tools/components/appsReview.vue b/frontend/src/features/tools/components/appsReview.vue index cd184fa..0ec8bd1 100644 --- a/frontend/src/features/tools/components/appsReview.vue +++ b/frontend/src/features/tools/components/appsReview.vue @@ -52,11 +52,8 @@ - - - - - + + diff --git a/frontend/src/features/vault/components/appSidebar.vue b/frontend/src/features/vault/components/appSidebar.vue index e7b7167..2c200d2 100644 --- a/frontend/src/features/vault/components/appSidebar.vue +++ b/frontend/src/features/vault/components/appSidebar.vue @@ -179,8 +179,22 @@ const handleLogout = async () => { if (layoutStore.showMobileMenu) { layoutStore.showMobileMenu = false } - await authUserStore.logout() - router.replace('/login') + + // 1. 立即清空本地状态(同步执行,防止 UI 卡顿) + await authUserStore.clearUserInfo() + + // 2. 带有超时保护的异步注销,最多等待 1.5 秒保证后端请求发完,防止浏览器过早跳转导致请求 Abort + await Promise.race([ + authUserStore.logout(), + new Promise(resolve => setTimeout(resolve, 1500)) + ]).catch(() => {}) + + // 3. 物理跳转进入登录页 + // 使用 location.href 而不是 router.replace,目的是强制刷新全部 JS Chunks, + // 解决 Cloudflare 部署新版本后旧分块 404 导致的白屏或无响应问题。 + window.location.href = '/login' + + // 提示信息(由于页面重刷,这条提示可能稍纵即逝,但保留逻辑完整性) ElMessage.success(t('auth.logout_success')) } @@ -199,6 +213,7 @@ const handleLogout = async () => { } .user-avatar { + flex-shrink: 0; border: 2px solid var(--el-color-primary-light-8); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } @@ -206,6 +221,7 @@ const handleLogout = async () => { .user-detail { display: flex; flex-direction: column; + min-width: 0; } .user-name-row { @@ -220,6 +236,9 @@ const handleLogout = async () => { font-weight: 600; color: var(--el-text-color-primary); line-height: 1.2; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .status-dot { diff --git a/frontend/src/features/vault/components/vaultList.vue b/frontend/src/features/vault/components/vaultList.vue index 8c87c43..3dd0d33 100644 --- a/frontend/src/features/vault/components/vaultList.vue +++ b/frontend/src/features/vault/components/vaultList.vue @@ -1,8 +1,8 @@ - - isToolbarFixed = val"> + + isToolbarFixed = val"> diff --git a/frontend/src/features/vault/views/home.vue b/frontend/src/features/vault/views/home.vue index 0a75bab..b24b808 100644 --- a/frontend/src/features/vault/views/home.vue +++ b/frontend/src/features/vault/views/home.vue @@ -45,23 +45,32 @@