From 552ceb378bac40886fa2077f37a0d3f4a71adbaa Mon Sep 17 00:00:00 2001 From: nap0o Date: Mon, 16 Mar 2026 21:07:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9UI,=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E9=A3=8E=E6=A0=BC=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../styles/modules/components/migration.css | 6 -- .../migration/composables/useDataExport.js | 4 ++ .../migration/composables/useDataImport.js | 2 +- .../migration/service/dataMigrationService.js | 65 ++++++++++--------- .../features/migration/views/dataExport.vue | 4 +- .../features/migration/views/dataImport.vue | 11 ++-- .../features/tools/components/appsReview.vue | 8 +-- frontend/src/locales/en-US.json | 10 +-- frontend/src/locales/zh-CN.json | 8 +-- .../components/icons/iconBitwardenAuth.vue | 12 ++++ ...conBitwarden.vue => iconBitwardenPass.vue} | 2 +- .../src/shared/components/icons/iconEnte.vue | 9 +-- .../components/icons/iconLastPassAuth.vue | 8 +-- .../components/icons/iconProtonAuth.vue | 13 +--- .../components/icons/iconProtonPass.vue | 2 +- .../shared/utils/serializers/csvStrategy.js | 8 +-- 16 files changed, 85 insertions(+), 87 deletions(-) create mode 100644 frontend/src/shared/components/icons/iconBitwardenAuth.vue rename frontend/src/shared/components/icons/{iconBitwarden.vue => iconBitwardenPass.vue} (94%) diff --git a/frontend/src/app/styles/modules/components/migration.css b/frontend/src/app/styles/modules/components/migration.css index 59f1639..da679ae 100644 --- a/frontend/src/app/styles/modules/components/migration.css +++ b/frontend/src/app/styles/modules/components/migration.css @@ -237,19 +237,13 @@ .migration-ms-tip code { display: block; margin-top: 6px; - padding: 6px 10px; - background: rgba(0, 0, 0, 0.05); - border-radius: 4px; font-family: var(--el-font-family-mono); font-size: 11px; word-break: break-all; color: var(--el-text-color-regular); - border: 1px solid rgba(0, 0, 0, 0.05); } html.dark .migration-ms-tip code { - background: rgba(255, 255, 255, 0.05); - border-color: rgba(255, 255, 255, 0.1); color: var(--el-text-color-secondary); } diff --git a/frontend/src/features/migration/composables/useDataExport.js b/frontend/src/features/migration/composables/useDataExport.js index ca4959d..e2ab079 100644 --- a/frontend/src/features/migration/composables/useDataExport.js +++ b/frontend/src/features/migration/composables/useDataExport.js @@ -129,6 +129,10 @@ export function useDataExport() { mimeType = 'text/csv' filename = `2fauth-worker-export-csv-${date}.csv` break + case 'bitwarden_auth_csv': + mimeType = 'text/csv' + filename = `2fauth-worker-export-bitwarden-auth-${date}.csv` + break case 'bitwarden_auth_json': mimeType = 'application/json' filename = `2fauth-worker-export-bitwarden-auth-${date}.json` diff --git a/frontend/src/features/migration/composables/useDataImport.js b/frontend/src/features/migration/composables/useDataImport.js index ba41095..79ba5e6 100644 --- a/frontend/src/features/migration/composables/useDataImport.js +++ b/frontend/src/features/migration/composables/useDataImport.js @@ -182,7 +182,7 @@ export function useDataImport(emitFn) { } } - if (detectedType === '2fauth_encrypted' || detectedType === 'aegis_encrypted' || detectedType === 'proton_auth_encrypted' || detectedType === 'proton_pass_pgp' || detectedType === '2fas_encrypted' || detectedType === 'ente_encrypted' || detectedType === 'bitwarden_vault_encrypted') { + if (detectedType === '2fauth_encrypted' || detectedType === 'aegis_encrypted' || detectedType === 'proton_auth_encrypted' || detectedType === 'proton_pass_pgp' || detectedType === '2fas_encrypted' || detectedType === 'ente_encrypted' || detectedType === 'bitwarden_pass_encrypted') { importPassword.value = '' isDialogHandled.value = false showDecryptDialog.value = true diff --git a/frontend/src/features/migration/service/dataMigrationService.js b/frontend/src/features/migration/service/dataMigrationService.js index a6b4e1f..b73f1bc 100644 --- a/frontend/src/features/migration/service/dataMigrationService.js +++ b/frontend/src/features/migration/service/dataMigrationService.js @@ -35,7 +35,7 @@ export const dataMigrationService = { * 智能识别导入内容或文件的类型 * @param {string|ArrayBuffer|Uint8Array} content - 文件文本内容或二进制数据 * @param {string} filename - 文件名 - * @returns {'bitwarden_vault_csv'|'bitwarden_auth_csv'|'generic_csv'|'generic_text'|'bitwarden_vault_json'|'bitwarden_auth_json'|'bitwarden_vault_encrypted'|'2fauth_encrypted'|'2fauth_json'|'2fas'|'2fas_encrypted'|'aegis'|'aegis_encrypted'|'phonefactor'|'1password_pux'|'lastpass_auth_json'|'unknown'} 返回类型标识 + * @returns {'bitwarden_pass_csv'|'bitwarden_auth_csv'|'generic_csv'|'generic_text'|'bitwarden_pass_json'|'bitwarden_auth_json'|'bitwarden_pass_encrypted'|'2fauth_encrypted'|'2fauth_json'|'2fas'|'2fas_encrypted'|'aegis'|'aegis_encrypted'|'phonefactor'|'1password_pux'|'lastpass_auth_json'|'unknown'} 返回类型标识 */ detectFileType(content, filename) { // 如果是二进制数据,尝试用更宽容的方式判断 PhoneFactor @@ -74,7 +74,7 @@ export const dataMigrationService = { if (filename && filename.toLowerCase().endsWith('.csv')) { const firstLine = typeof textContent === 'string' ? textContent.split('\n')[0].toLowerCase() : '' - if (firstLine.includes('login_totp')) return 'bitwarden_vault_csv' + if (firstLine.includes('login_totp')) return 'bitwarden_pass_csv' if (firstLine.includes('title') && firstLine.includes('otpauth')) return '1password_csv' if (firstLine.includes('otpauth')) return 'bitwarden_auth_csv' if (firstLine.includes('totp') && firstLine.includes('vault') && firstLine.includes('createtime')) return 'proton_pass_csv' @@ -89,8 +89,8 @@ export const dataMigrationService = { if (typeof textContent === 'string') { const json = tryParseJSON(textContent) if (json) { - // 如果包含 folders 字段,通常是 Bitwarden Vault (密码管理器) - if (Array.isArray(json.items) && Array.isArray(json.folders)) return 'bitwarden_vault_json' + // 如果包含 folders 字段,通常是 Bitwarden Pass (密码管理器) + if (Array.isArray(json.items) && Array.isArray(json.folders)) return 'bitwarden_pass_json' // 如果只包含 items 且是明文,归类为 bitwarden_auth_json (之前测试过的独立 App 路径) if (Array.isArray(json.items) && (json.encrypted === false || !('encrypted' in json))) return 'bitwarden_auth_json' if (json.encrypted === true && json.app === '2fauth') return '2fauth_encrypted' @@ -105,8 +105,8 @@ export const dataMigrationService = { if (json.version === 1 && typeof json.salt === 'string' && typeof json.content === 'string') return 'proton_auth_encrypted' // Ente Auth 加密导出:同时包含 kdfParams 和 encryptedData 两个关键字段 if (json.kdfParams && typeof json.encryptedData === 'string') return 'ente_encrypted' - // Bitwarden password-protected export (Vault) - if (json.encrypted === true && json.passwordProtected === true && json.encKeyValidation_DO_NOT_EDIT) return 'bitwarden_vault_encrypted' + // Bitwarden Password password-protected export + if (json.encrypted === true && json.passwordProtected === true && json.encKeyValidation_DO_NOT_EDIT) return 'bitwarden_pass_encrypted' } } @@ -249,18 +249,19 @@ export const dataMigrationService = { }).join('\n') } + if (type === 'bitwarden_auth_csv') { + let csv = 'name,secret,totp,favorite,folder\n' + vault.forEach(acc => { + const name = `"${acc.service}${acc.account ? ':' + acc.account : ''}"` + const label = encodeURIComponent(`${acc.service}:${acc.account}`) + const issuer = encodeURIComponent(acc.service) + const totp = `"otpauth://totp/${label}?secret=${acc.secret}&issuer=${issuer}&digits=${acc.digits}&period=${acc.period}"` + csv += `${name},${acc.secret},${totp},0,\n` + }) + return csv + } + if (type === 'generic_csv') { - if (variant === 'bitwarden_auth') { - let csv = 'name,secret,totp,favorite,folder\n' - vault.forEach(acc => { - const name = `"${acc.service}${acc.account ? ':' + acc.account : ''}"` - const label = encodeURIComponent(`${acc.service}:${acc.account}`) - const issuer = encodeURIComponent(acc.service) - const totp = `"otpauth://totp/${label}?secret=${acc.secret}&issuer=${issuer}&digits=${acc.digits}&period=${acc.period}"` - csv += `${name},${acc.secret},${totp},0,\n` - }) - return csv - } // generic csv let csv = 'name,issuer,secret,algorithm,digits,period,type\n' vault.forEach(acc => { @@ -653,7 +654,7 @@ export const dataMigrationService = { * @param {Object} json * @returns {Promise} 解密后的 JSON 对象 */ - async decryptBitwardenVaultEncrypted(password, json) { + async decryptBitwardenPassEncrypted(password, json) { try { const saltStr = json.salt; const iterations = json.kdfIterations; @@ -666,7 +667,7 @@ export const dataMigrationService = { // 1. 衍生主密钥: 关键是直接使用 salt 字符串作为 UTF-8 字节输入 const saltBytes = new TextEncoder().encode(saltStr); const passwordBytes = new TextEncoder().encode(password); - + const keyMaterialHandle = await crypto.subtle.importKey( 'raw', passwordBytes, { name: 'PBKDF2' }, false, ['deriveBits'] ); @@ -1146,14 +1147,14 @@ export const dataMigrationService = { } // 处理 Bitwarden 加密导出 (Password-protected Vault) - if (type === 'bitwarden_vault_encrypted') { + if (type === 'bitwarden_pass_encrypted') { if (!password) throw new migrationError('导入 Bitwarden 加密文件需要密码', 'MISSING_PASSWORD') try { const bitwardenJson = typeof content === 'string' ? JSON.parse(content) : content - const decrypted = await this.decryptBitwardenVaultEncrypted(password, bitwardenJson) - // 解密后的格式就是普通的 bitwarden_vault_json 结构(有 items 数组) + const decrypted = await this.decryptBitwardenPassEncrypted(password, bitwardenJson) + // 解密后的格式就是普通的 bitwarden_pass_json 结构(有 items 数组) content = JSON.stringify(decrypted) - type = 'bitwarden_vault_json' + type = 'bitwarden_pass_json' password = undefined } catch (e) { if (e instanceof migrationError) throw e @@ -1225,7 +1226,7 @@ export const dataMigrationService = { }) } } - else if (type === 'bitwarden_vault_json' || type === 'bitwarden_auth_json') { + else if (type === 'bitwarden_pass_json' || type === 'bitwarden_auth_json') { const json = typeof content === 'string' ? JSON.parse(content) : content if (Array.isArray(json.items)) { json.items.forEach(item => { @@ -1288,7 +1289,7 @@ export const dataMigrationService = { })) } } - else if (type === 'bitwarden_vault_csv' || type === 'bitwarden_auth_csv' || type === '1password_csv' || type === 'proton_pass_csv' || type === 'dashlane_csv' || type === 'generic_csv') rawVault = csvStrategy.parseCsv(content) + else if (type === 'bitwarden_pass_csv' || type === 'bitwarden_auth_csv' || type === '1password_csv' || type === 'proton_pass_csv' || type === 'dashlane_csv' || type === 'generic_csv') rawVault = csvStrategy.parseCsv(content) return rawVault.map(acc => { if (typeof acc.account === 'string' && acc.account.includes(':')) { @@ -1357,15 +1358,15 @@ export const dataMigrationService = { const bytes = content instanceof Uint8Array ? content : new Uint8Array(content) const unzipped = unzipSync(bytes) const dataFileContent = unzipped['export.data'] - + if (!dataFileContent) throw new Error('未能在 .1pux 文件中找到 export.data') - + const text = new TextDecoder().decode(dataFileContent) const data = JSON.parse(text) - + const rawVault = [] const accounts = data.accounts || [] - + accounts.forEach(account => { const vaults = account.vaults || [] vaults.forEach(vault => { @@ -1373,7 +1374,7 @@ export const dataMigrationService = { items.forEach(item => { const title = item.overview?.title || 'Unknown' const subtitle = item.overview?.subtitle || '' - + // 1PUX 的 TOTP 字段路径通常在 sections[].fields 或是 loginFields 中 const checkFields = (fields) => { if (!Array.isArray(fields)) return @@ -1390,7 +1391,7 @@ export const dataMigrationService = { } }) } - + checkFields(item.details?.loginFields) if (Array.isArray(item.details?.sections)) { item.details.sections.forEach(section => checkFields(section.fields)) @@ -1398,7 +1399,7 @@ export const dataMigrationService = { }) }) }) - + return rawVault } catch (e) { throw new migrationError('解析 1Password 备份失败: ' + (e.message || String(e)), 'ONEPASSWORD_PARSE_FAILED', e) diff --git a/frontend/src/features/migration/views/dataExport.vue b/frontend/src/features/migration/views/dataExport.vue index b7221e5..ad6d929 100644 --- a/frontend/src/features/migration/views/dataExport.vue +++ b/frontend/src/features/migration/views/dataExport.vue @@ -41,7 +41,7 @@ {{ $t('migration.migrate_ga') }} - Bitwarden Auth (.json) + Bitwarden Auth (.json) @@ -177,7 +177,7 @@ import { import icon2FAS from '@/shared/components/icons/icon2FAS.vue' import iconAegis from '@/shared/components/icons/iconAegis.vue' import iconGoogleAuth from '@/shared/components/icons/iconGoogleAuth.vue' -import iconBitwarden from '@/shared/components/icons/iconBitwarden.vue' +import iconBitwardenAuth from '@/shared/components/icons/iconBitwardenAuth.vue' import { useLayoutStore } from '@/shared/stores/layoutStore' import { useDataExport } from '@/features/migration/composables/useDataExport' import { i18n } from '@/locales' diff --git a/frontend/src/features/migration/views/dataImport.vue b/frontend/src/features/migration/views/dataImport.vue index 689ff95..6b666f3 100644 --- a/frontend/src/features/migration/views/dataImport.vue +++ b/frontend/src/features/migration/views/dataImport.vue @@ -60,7 +60,7 @@ {{ $t('migration.password_manager_format') }}
- Bitwarden Vault (.json/.csv) + Bitwarden Pass (.json/.csv) 1Password (.1pux/.csv) Proton Pass (.pgp/.csv) Dashlane (.csv) @@ -76,7 +76,7 @@
2FAS (.2fas) Aegis (.json/.txt) - Bitwarden Auth (.json/.csv) + Bitwarden Auth (.json/.csv) Proton Auth(.json) Ente Auth(.txt) Google Auth (.png/.jpg) @@ -111,7 +111,7 @@
{{ $t('migration.ms_auth_desc') }} -

{{ $t('migration.ms_auth_detail') }}:

+

{{ $t('migration.ms_auth_detail') }}

/data/data/com.azure.authenticator/databases/PhoneFactor /data/data/com.azure.authenticator/databases/PhoneFactor-wal @@ -155,7 +155,7 @@ - + @@ -188,7 +188,8 @@ const triggerUpload = () => { import icon2FAS from '@/shared/components/icons/icon2FAS.vue' import iconAegis from '@/shared/components/icons/iconAegis.vue' import iconGoogleAuth from '@/shared/components/icons/iconGoogleAuth.vue' -import iconBitwarden from '@/shared/components/icons/iconBitwarden.vue' +import iconBitwardenPass from '@/shared/components/icons/iconBitwardenPass.vue' +import iconBitwardenAuth from '@/shared/components/icons/iconBitwardenAuth.vue' import iconMicrosoftAuth from '@/shared/components/icons/iconMicrosoftAuth.vue' import iconDashlanePass from '@/shared/components/icons/iconDashlanePass.vue' import iconProtonAuth from '@/shared/components/icons/iconProtonAuth.vue' diff --git a/frontend/src/features/tools/components/appsReview.vue b/frontend/src/features/tools/components/appsReview.vue index 0154d6e..9abc5c1 100644 --- a/frontend/src/features/tools/components/appsReview.vue +++ b/frontend/src/features/tools/components/appsReview.vue @@ -110,12 +110,12 @@ import Icon2FAS from '@/shared/components/icons/icon2FAS.vue' import IconAegis from '@/shared/components/icons/iconAegis.vue' import IconEnte from '@/shared/components/icons/iconEnte.vue' import IconProtonAuth from '@/shared/components/icons/iconProtonAuth.vue' -import IconBitwarden from '@/shared/components/icons/iconBitwarden.vue' +import IconBitwardenAuth from '@/shared/components/icons/iconBitwardenAuth.vue' import IconMicrosoftAuth from '@/shared/components/icons/iconMicrosoftAuth.vue' import IconGoogleAuth from '@/shared/components/icons/iconGoogleAuth.vue' import IconFreeOTP from '@/shared/components/icons/iconFreeOTP.vue' import IconAuthy from '@/shared/components/icons/iconAuthy.vue' -import IconLastPass from '@/shared/components/icons/iconLastPass.vue' +import iconLastPassAuth from '@/shared/components/icons/iconLastPassAuth.vue' import IconRaivo from '@/shared/components/icons/iconRaivo.vue' const appList = [ @@ -123,12 +123,12 @@ const appList = [ { id: 'ente', name: 'Ente Auth', rating: 4.8, icon: IconEnte, link: 'https://ente.io/auth/', recommended: true, securityIssue: false, downloads: { ios: 'https://apps.apple.com/app/ente-authenticator/id6444101188', android: 'https://play.google.com/store/apps/details?id=io.ente.auth', fdroid: 'https://f-droid.org/packages/io.ente.auth', github: 'https://github.com/ente-io/ente/releases', desktop: 'https://ente.io/download/auth/desktop' } }, { id: 'aegis', name: 'Aegis Authenticator', rating: 4.8, icon: IconAegis, link: 'https://getaegis.app/', recommended: true, securityIssue: false, downloads: { android: 'https://play.google.com/store/apps/details?id=com.beemdevelopment.aegis', fdroid: 'https://f-droid.org/packages/com.beemdevelopment.aegis/', github: 'https://github.com/beemdevelopment/Aegis/releases' } }, { id: 'proton', name: 'Proton Authenticator', rating: 4.5, icon: IconProtonAuth, link: 'https://proton.me/pass', recommended: false, securityIssue: false, downloads: { ios: 'https://apps.apple.com/us/app/proton-pass-password-manager/id6443490729', android: 'https://play.google.com/store/apps/details?id=me.proton.android.pass', extension: 'https://chrome.google.com/webstore/detail/proton-pass-free-password/ghmbeldphafepmbegfdlkmapnddhbheg' } }, - { id: 'bitwarden', name: 'Bitwarden Authenticator', rating: 4.2, icon: IconBitwarden, link: 'https://bitwarden.com/products/authenticator/', recommended: false, securityIssue: false, downloads: { ios: 'https://apps.apple.com/us/app/bitwarden-authenticator/id6475654992', android: 'https://play.google.com/store/apps/details?id=com.bitwarden.authenticator', github: 'https://github.com/bitwarden/authenticator/releases' } }, + { id: 'bitwarden', name: 'Bitwarden Authenticator', rating: 4.2, icon: IconBitwardenAuth, link: 'https://bitwarden.com/products/authenticator/', recommended: false, securityIssue: false, downloads: { ios: 'https://apps.apple.com/us/app/bitwarden-authenticator/id6475654992', android: 'https://play.google.com/store/apps/details?id=com.bitwarden.authenticator', github: 'https://github.com/bitwarden/authenticator/releases' } }, { id: 'google', name: 'Google Authenticator', rating: 4.0, icon: IconGoogleAuth, link: 'https://safety.google/authentication/', recommended: false, securityIssue: false, downloads: { ios: 'https://apps.apple.com/us/app/google-authenticator/id388497605', android: 'https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2' } }, { id: 'freeotp', name: 'FreeOTP', rating: 3.0, icon: IconFreeOTP, link: 'https://freeotp.github.io/', recommended: false, securityIssue: false, downloads: { ios: 'https://apps.apple.com/us/app/freeotp-authenticator/id872559395', android: 'https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp', fdroid: 'https://f-droid.org/en/packages/org.fedorahosted.freeotp/' } }, { id: 'microsoft', name: 'Microsoft Authenticator', rating: 2.0, icon: IconMicrosoftAuth, link: 'https://www.microsoft.com/en-us/security/mobile-authenticator-app', recommended: false, securityIssue: true, downloads: { ios: 'https://apps.apple.com/us/app/microsoft-authenticator/id983156458', android: 'https://play.google.com/store/apps/details?id=com.azure.authenticator' } }, { id: 'authy', name: 'Authy', rating: 1.5, icon: IconAuthy, link: 'https://authy.com/', recommended: false, securityIssue: true, downloads: { ios: 'https://apps.apple.com/us/app/twilio-authy/id494168017', android: 'https://play.google.com/store/apps/details?id=com.authy.authy' } }, - { id: 'lastpass', name: 'LastPass Auth', rating: 1.5, icon: IconLastPass, link: 'https://www.lastpass.com/auth', recommended: false, securityIssue: true, downloads: { ios: 'https://apps.apple.com/us/app/lastpass-authenticator/id1079110004', android: 'https://play.google.com/store/apps/details?id=com.lastpass.authenticator' } }, + { id: 'lastpass', name: 'LastPass Auth', rating: 1.5, icon: iconLastPassAuth, link: 'https://www.lastpass.com/auth', recommended: false, securityIssue: true, downloads: { ios: 'https://apps.apple.com/us/app/lastpass-authenticator/id1079110004', android: 'https://play.google.com/store/apps/details?id=com.lastpass.authenticator' } }, { id: 'raivo', name: 'Raivo OTP', rating: 1.0, icon: IconRaivo, link: 'https://raivo-otp.com/', recommended: false, securityIssue: true, downloads: { ios: 'https://apps.apple.com/us/app/raivo-otp/id1459042137' } } ] diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index 7671aa7..cd26de9 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -372,10 +372,10 @@ "center_desc": "Support restoring data from various 2FA apps or system backups.", "auto_identify_tip": "💡 Automatically recognize file types", "drag_drop_tip": "Drag backup files or migration QR screenshots here, or click to upload", - "support_desc": "Supported List", + "support_desc": "Support List", "ga_auth_desc": "Export 'Transfer QR code' in the App and upload the screenshot (.png / .jpg)", - "ms_auth_desc": "Microsoft Authenticator (Android Only)", - "ms_auth_detail": "Export the following 3 files from Android and upload them together", + "ms_auth_desc": "Microsoft Authenticator", + "ms_auth_detail": "Only support Android, export the following 3 files and upload them together", "import_guide": "Import Guide", "batch_import_processing": "📦 Batch Import Processing", "batch_progress": "{processed} / {total} tasks completed", @@ -385,13 +385,13 @@ "detect_proton_pass": "Proton Pass encrypted backup detected (.pgp)", "detect_2fas": "2FAS Auth encrypted backup detected", "detect_ente": "Ente Auth encrypted backup detected", - "detect_bitwarden_vault": "Bitwarden Vault encrypted backup detected", + "detect_bitwarden_pass": "Bitwarden Pass encrypted backup detected", "detect_system": "System encrypted backup detected", "input_decrypt_pwd_label": "Please enter the decryption password:", "input_decrypt_pwd_placeholder": "Enter the password set during export", "confirm_decrypt_import": "Confirm Decrypt & Import", "system_backup_format": "System Backup", - "password_manager_format": "Password Manager (Vault)", + "password_manager_format": "Password Manager", "encrypted_backup_json": "Encrypted Backup (.json)", "plaintext_backup_json": "Plaintext Backup (.json)", "mobile_app_format": "Mobile 2FA Apps", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index d841c95..9c9c1a4 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -374,8 +374,8 @@ "drag_drop_tip": "将备份文件或迁移二维码截图拖到此处,或 点击上传", "support_desc": "支持列表", "ga_auth_desc": "请在 App 内导出\"迁移二维码\",将截图直接上传 (.png / .jpg)", - "ms_auth_desc": "Microsoft Authenticator (仅支持 Android)", - "ms_auth_detail": "Android 手机导出以下3个文件后,同时选中上传即可导入", + "ms_auth_desc": "Microsoft Authenticator", + "ms_auth_detail": "仅支持 Android 手机,导出以下3个文件后,同时选中上传即可导入", "import_guide": "导入指南", "batch_import_processing": "📦 批量导入处理中", "batch_progress": "{processed} / {total} 任务已完成", @@ -385,13 +385,13 @@ "detect_proton_pass": "检测到 Proton Pass 加密备份 (.pgp)", "detect_2fas": "检测到 2FAS Auth 加密备份", "detect_ente": "检测到 Ente Auth 加密备份", - "detect_bitwarden_vault": "检测到 Bitwarden Vault 加密备份", + "detect_bitwarden_pass": "检测到 Bitwarden Pass 加密备份", "detect_system": "检测到本系统加密备份", "input_decrypt_pwd_label": "请输入该备份的解密密码:", "input_decrypt_pwd_placeholder": "输入当时设置的导出密码", "confirm_decrypt_import": "确认解密并导入", "system_backup_format": "本系统备份", - "password_manager_format": "密码管理器 (Vault)", + "password_manager_format": "密码管理器", "encrypted_backup_json": "加密备份 (.json)", "plaintext_backup_json": "明文备份 (.json)", "mobile_app_format": "移动端 2FA App", diff --git a/frontend/src/shared/components/icons/iconBitwardenAuth.vue b/frontend/src/shared/components/icons/iconBitwardenAuth.vue new file mode 100644 index 0000000..5b4a5d1 --- /dev/null +++ b/frontend/src/shared/components/icons/iconBitwardenAuth.vue @@ -0,0 +1,12 @@ + + diff --git a/frontend/src/shared/components/icons/iconBitwarden.vue b/frontend/src/shared/components/icons/iconBitwardenPass.vue similarity index 94% rename from frontend/src/shared/components/icons/iconBitwarden.vue rename to frontend/src/shared/components/icons/iconBitwardenPass.vue index e374a90..3933991 100644 --- a/frontend/src/shared/components/icons/iconBitwarden.vue +++ b/frontend/src/shared/components/icons/iconBitwardenPass.vue @@ -4,5 +4,5 @@ diff --git a/frontend/src/shared/components/icons/iconEnte.vue b/frontend/src/shared/components/icons/iconEnte.vue index f40da85..3d759df 100644 --- a/frontend/src/shared/components/icons/iconEnte.vue +++ b/frontend/src/shared/components/icons/iconEnte.vue @@ -1,10 +1,7 @@