mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
feat: enhance import/export page with new layout and features
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { argon2idAsync } from '@noble/hashes/argon2.js';
|
||||
import { strFromU8, unzipSync } from 'fflate';
|
||||
import { BlobReader, Uint8ArrayWriter, ZipReader, configure as configureZipJs } from '@zip.js/zip.js';
|
||||
import { Download, FileUp } from 'lucide-preact';
|
||||
import { Archive, ArrowLeftRight, Download, FileJson, FileUp } from 'lucide-preact';
|
||||
import ConfirmDialog from '@/components/ConfirmDialog';
|
||||
import type { CiphersImportPayload } from '@/lib/api';
|
||||
import {
|
||||
@@ -581,8 +581,43 @@ export default function ImportPage({ onImport, onImportEncryptedRaw, accountKeys
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="stack">
|
||||
<section className="card">
|
||||
<div className="import-export-page">
|
||||
<section className="card import-export-hero">
|
||||
<h3>{t('txt_import_export_title')}</h3>
|
||||
<p className="import-export-hero-sub">{t('txt_import_export_feature_intro')}</p>
|
||||
<div className="import-export-feature-grid">
|
||||
<article className="import-export-feature-item">
|
||||
<span className="import-export-feature-icon">
|
||||
<Archive size={16} />
|
||||
</span>
|
||||
<div>
|
||||
<strong>{t('txt_import_export_feature_bw_zip_title')}</strong>
|
||||
<p>{t('txt_import_export_feature_bw_zip_desc')}</p>
|
||||
</div>
|
||||
</article>
|
||||
<article className="import-export-feature-item">
|
||||
<span className="import-export-feature-icon">
|
||||
<FileJson size={16} />
|
||||
</span>
|
||||
<div>
|
||||
<strong>{t('txt_import_export_feature_nodewarden_json_title')}</strong>
|
||||
<p>{t('txt_import_export_feature_nodewarden_json_desc')}</p>
|
||||
</div>
|
||||
</article>
|
||||
<article className="import-export-feature-item">
|
||||
<span className="import-export-feature-icon">
|
||||
<ArrowLeftRight size={16} />
|
||||
</span>
|
||||
<div>
|
||||
<strong>{t('txt_import_export_feature_compat_title')}</strong>
|
||||
<p>{t('txt_import_export_feature_compat_desc')}</p>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="import-export-panels">
|
||||
<section className="card import-export-panel">
|
||||
<h3>{t('txt_import')}</h3>
|
||||
<p className="muted" style={{ textAlign: 'left', marginBottom: 12 }}>
|
||||
{t('txt_import_vault_data_hint')}
|
||||
@@ -665,7 +700,7 @@ export default function ImportPage({ onImport, onImportEncryptedRaw, accountKeys
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="card">
|
||||
<section className="card import-export-panel">
|
||||
<h3>{t('txt_export')}</h3>
|
||||
<p className="muted" style={{ textAlign: 'left', marginBottom: 12 }}>
|
||||
{t('txt_export_vault_data_hint')}
|
||||
@@ -735,6 +770,7 @@ export default function ImportPage({ onImport, onImportEncryptedRaw, accountKeys
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<ConfirmDialog
|
||||
open={exportAuthDialogOpen}
|
||||
|
||||
@@ -752,6 +752,14 @@ messages.en.txt_target_folder = 'Target folder';
|
||||
messages.en.txt_select_folder_placeholder = '-- Select folder --';
|
||||
messages.en.txt_import_vault_data_hint = 'Import vault data into your current account.';
|
||||
messages.en.txt_export_vault_data_hint = 'Export vault data from your current account.';
|
||||
messages.en.txt_import_export_title = 'Import & Export';
|
||||
messages.en.txt_import_export_feature_intro = 'Move your vault across clients with full compatibility, including attachments and encrypted formats.';
|
||||
messages.en.txt_import_export_feature_bw_zip_title = 'Bitwarden vault + attachments ZIP';
|
||||
messages.en.txt_import_export_feature_bw_zip_desc = 'Supports importing and exporting Bitwarden ZIP archives that include vault data and attachments.';
|
||||
messages.en.txt_import_export_feature_nodewarden_json_title = 'NodeWarden vault + attachments JSON';
|
||||
messages.en.txt_import_export_feature_nodewarden_json_desc = 'Supports NodeWarden JSON import/export with vault data and attachments bundled in one file.';
|
||||
messages.en.txt_import_export_feature_compat_title = 'Cross-client compatibility';
|
||||
messages.en.txt_import_export_feature_compat_desc = 'Supports Bitwarden JSON/CSV import and mainstream migration formats for a smooth move-in.';
|
||||
messages.en.txt_encrypted_mode = 'Encrypted mode';
|
||||
messages.en.txt_account_verification = 'Account verification';
|
||||
messages.en.txt_password_verification = 'Password verification';
|
||||
@@ -818,6 +826,15 @@ zhCNOverrides.txt_import_encrypted_file_message = '该 Bitwarden 导出文件已
|
||||
zhCNOverrides.txt_import_encrypted_zip_title = '导入加密 ZIP';
|
||||
zhCNOverrides.txt_import_encrypted_zip_message = '该 ZIP 压缩包已加密,请输入 ZIP 密码继续。';
|
||||
|
||||
zhCNOverrides.txt_import_export_title = '导入导出';
|
||||
zhCNOverrides.txt_import_export_feature_intro = '兼容主流客户端的数据迁移流程,支持附件与加密格式,导入导出一步完成。';
|
||||
zhCNOverrides.txt_import_export_feature_bw_zip_title = 'Bitwarden 密码库 + 附件 ZIP';
|
||||
zhCNOverrides.txt_import_export_feature_bw_zip_desc = '支持导入和导出包含密码库与附件的 Bitwarden ZIP 压缩包。';
|
||||
zhCNOverrides.txt_import_export_feature_nodewarden_json_title = 'NodeWarden 密码库 + 附件 JSON';
|
||||
zhCNOverrides.txt_import_export_feature_nodewarden_json_desc = '支持 NodeWarden 自研 JSON 导入导出,一个文件同时包含密码库和附件。';
|
||||
zhCNOverrides.txt_import_export_feature_compat_title = '跨客户端兼容';
|
||||
zhCNOverrides.txt_import_export_feature_compat_desc = '支持 Bitwarden JSON/CSV 导入及主流迁移格式,降低迁移门槛。';
|
||||
|
||||
messages['zh-CN'] = { ...messages.en, ...zhCNOverrides };
|
||||
|
||||
function resolveInitialLocale(): Locale {
|
||||
|
||||
@@ -1032,6 +1032,79 @@ input[type='file'].input::file-selector-button:hover {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.import-export-page {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.import-export-hero {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.import-export-hero h3 {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.import-export-hero-sub {
|
||||
margin: 0;
|
||||
color: #5f6f85;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.import-export-feature-grid {
|
||||
margin-top: 12px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.import-export-feature-item {
|
||||
border: 1px solid #d9e4f2;
|
||||
border-radius: 10px;
|
||||
background: #f7faff;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.import-export-feature-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #cbdcf7;
|
||||
background: #e9f1ff;
|
||||
color: #1d4ed8;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.import-export-feature-item strong {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.import-export-feature-item p {
|
||||
margin: 4px 0 0 0;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.import-export-panels {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.import-export-panel h3 {
|
||||
margin: 0 0 6px 0;
|
||||
}
|
||||
|
||||
.field-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
@@ -1510,6 +1583,11 @@ input[type='file'].input::file-selector-button:hover {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.import-export-feature-grid,
|
||||
.import-export-panels {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.uri-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user