From 8e34d08545aae4065caedd7101819630afef1fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A6=E5=90=9B?= <73606411+setube@users.noreply.github.com> Date: Sat, 20 Dec 2025 02:55:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81Android=E7=AB=AF?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=88=B0Documents=E5=B9=B6=E5=A4=9A=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android端数据导出改为直接保存至Documents目录,导出成功后弹出带路径的多语言提示。引入@capacitor/status-bar与@capawesome/capacitor-file-picker依赖,主入口设置原生状态栏颜色与样式。各语言包补充导出成功带路径提示文案。 --- android/app/src/main/AndroidManifest.xml | 2 ++ package.json | 2 ++ pnpm-lock.yaml | 32 +++++++++++++++++++++--- src/locales/de.ts | 1 + src/locales/en.ts | 1 + src/locales/ja.ts | 1 + src/locales/ko.ts | 1 + src/locales/ru.ts | 1 + src/locales/zh-CN.ts | 1 + src/locales/zh-TW.ts | 1 + src/main.ts | 9 +++++++ src/views/SettingsView.vue | 17 +++++-------- 12 files changed, 54 insertions(+), 15 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 5fd9523..13ea633 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -40,4 +40,6 @@ + + diff --git a/package.json b/package.json index 5007d7d..875af73 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "@capacitor/core": "^8.0.0", "@capacitor/filesystem": "^8.0.0", "@capacitor/share": "^8.0.0", + "@capacitor/status-bar": "^8.0.0", + "@capawesome/capacitor-file-picker": "^8.0.0", "@tailwindcss/vite": "^4.1.17", "@tanstack/vue-table": "^8.21.3", "@vueuse/core": "^14.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8493af..78661f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,12 @@ importers: '@capacitor/share': specifier: ^8.0.0 version: 8.0.0(@capacitor/core@8.0.0) + '@capacitor/status-bar': + specifier: ^8.0.0 + version: 8.0.0(@capacitor/core@8.0.0) + '@capawesome/capacitor-file-picker': + specifier: ^8.0.0 + version: 8.0.0(@capacitor/core@8.0.0) '@tailwindcss/vite': specifier: ^4.1.17 version: 4.1.17(rolldown-vite@7.2.5(@types/node@24.10.2)(esbuild@0.25.12)(jiti@2.6.1)(terser@5.44.1)) @@ -682,9 +688,19 @@ packages: peerDependencies: '@capacitor/core': '>=8.0.0' + '@capacitor/status-bar@8.0.0': + resolution: {integrity: sha512-aIj3bc7z8lfPgOen8HlrBrkfnxpFnh21OCx6jCUx4Mvv+B6eEkUQ49b32DOddgVfr+igRHLX2SYi7duqIsNDXg==} + peerDependencies: + '@capacitor/core': '>=8.0.0' + '@capacitor/synapse@1.0.4': resolution: {integrity: sha512-/C1FUo8/OkKuAT4nCIu/34ny9siNHr9qtFezu4kxm6GY1wNFxrCFWjfYx5C1tUhVGz3fxBABegupkpjXvjCHrw==} + '@capawesome/capacitor-file-picker@8.0.0': + resolution: {integrity: sha512-eA39o8phSRcA78tnmQT6T2h73pljt5g+TcxI3xdR1hlWG7nlGLM2fDfiAaQ/2IASI4TA+s+NGBW1TdOXbwQiOw==} + peerDependencies: + '@capacitor/core': '>=8.0.0' + '@csstools/cascade-layer-name-parser@2.0.5': resolution: {integrity: sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==} engines: {node: '>=18'} @@ -995,8 +1011,8 @@ packages: resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} engines: {node: '>=12'} - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': - resolution: {tarball: https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2} + '@electron/node-gyp@git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2': + resolution: {commit: 06b29aafb7708acef8b3669835c8a7857ebc92d2, repo: https://github.com/electron/node-gyp.git, type: git} version: 10.2.0-electron.1 engines: {node: '>=12.13.0'} hasBin: true @@ -5143,8 +5159,16 @@ snapshots: dependencies: '@capacitor/core': 8.0.0 + '@capacitor/status-bar@8.0.0(@capacitor/core@8.0.0)': + dependencies: + '@capacitor/core': 8.0.0 + '@capacitor/synapse@1.0.4': {} + '@capawesome/capacitor-file-picker@8.0.0(@capacitor/core@8.0.0)': + dependencies: + '@capacitor/core': 8.0.0 + '@csstools/cascade-layer-name-parser@2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) @@ -5480,7 +5504,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@electron/node-gyp@https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2': + '@electron/node-gyp@git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2': dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.3 @@ -5517,7 +5541,7 @@ snapshots: '@electron/rebuild@3.7.0': dependencies: - '@electron/node-gyp': https://codeload.github.com/electron/node-gyp/tar.gz/06b29aafb7708acef8b3669835c8a7857ebc92d2 + '@electron/node-gyp': git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2 '@malept/cross-spawn-promise': 2.0.0 chalk: 4.1.2 debug: 4.4.3 diff --git a/src/locales/de.ts b/src/locales/de.ts index 6851bf8..b046a9b 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -850,6 +850,7 @@ export default { export: 'Exportieren', exporting: 'Exportieren...', exportSuccess: 'Export erfolgreich', + exportSuccessWithPath: 'Export erfolgreich, Datei gespeichert unter: {path}', exportFailed: 'Export fehlgeschlagen, bitte erneut versuchen', importData: 'Daten importieren', importDataDesc: 'Spielfortschritt aus JSON-Datei wiederherstellen', diff --git a/src/locales/en.ts b/src/locales/en.ts index c34efe5..6086d6a 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -886,6 +886,7 @@ export default { export: 'Export', exporting: 'Exporting...', exportSuccess: 'Export successful', + exportSuccessWithPath: 'Export successful, file saved to: {path}', exportFailed: 'Export failed, please try again', importData: 'Import Data', importDataDesc: 'Restore game progress from JSON file', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index 24055f6..aa48f93 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -844,6 +844,7 @@ export default { export: 'エクスポート', exporting: 'エクスポート中...', exportSuccess: 'エクスポート成功', + exportSuccessWithPath: 'エクスポート成功、ファイルの保存先:{path}', exportFailed: 'エクスポートに失敗しました。もう一度お試しください', importData: 'データインポート', importDataDesc: 'JSONファイルからゲームの進行状況を復元', diff --git a/src/locales/ko.ts b/src/locales/ko.ts index 90b9572..e3e85e1 100644 --- a/src/locales/ko.ts +++ b/src/locales/ko.ts @@ -845,6 +845,7 @@ export default { export: '내보내기', exporting: '내보내는 중...', exportSuccess: '내보내기 성공', + exportSuccessWithPath: '내보내기 성공, 파일 저장 위치: {path}', exportFailed: '내보내기 실패, 다시 시도해주세요', importData: '데이터 가져오기', importDataDesc: 'JSON 파일에서 게임 진행 상황 복원', diff --git a/src/locales/ru.ts b/src/locales/ru.ts index 9f29d43..01489cb 100644 --- a/src/locales/ru.ts +++ b/src/locales/ru.ts @@ -851,6 +851,7 @@ export default { export: 'Экспорт', exporting: 'Экспорт...', exportSuccess: 'Экспорт успешен', + exportSuccessWithPath: 'Экспорт успешен, файл сохранен в: {path}', exportFailed: 'Экспорт не удался, попробуйте еще раз', importData: 'Импорт данных', importDataDesc: 'Восстановить прогресс игры из JSON файла', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index bd9bfdb..8b8f6c3 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -873,6 +873,7 @@ export default { export: '导出', exporting: '导出中...', exportSuccess: '导出成功', + exportSuccessWithPath: '导出成功,文件已保存到:{path}', exportFailed: '导出失败,请重试', importData: '导入数据', importDataDesc: '从JSON文件恢复游戏进度', diff --git a/src/locales/zh-TW.ts b/src/locales/zh-TW.ts index e349eee..e15c7ad 100644 --- a/src/locales/zh-TW.ts +++ b/src/locales/zh-TW.ts @@ -846,6 +846,7 @@ export default { export: '匯出', exporting: '匯出中...', exportSuccess: '匯出成功', + exportSuccessWithPath: '匯出成功,檔案已儲存到:{path}', exportFailed: '匯出失敗,請重試', importData: '匯入資料', importDataDesc: '從JSON檔案恢復遊戲進度', diff --git a/src/main.ts b/src/main.ts index a93fd01..44914ef 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,19 @@ import { createApp } from 'vue' import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' +import { Capacitor } from '@capacitor/core' +import { StatusBar, Style } from '@capacitor/status-bar' import './style.css' import App from './App.vue' import router from './router' +// Android 设置状态栏 +if (Capacitor.isNativePlatform()) { + StatusBar.setBackgroundColor({ color: '#1a1a2e' }) + StatusBar.setStyle({ style: Style.Dark }) + StatusBar.setOverlaysWebView({ overlay: false }) +} + const app = createApp(App) const pinia = createPinia() diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue index ff1a18b..a952d7f 100644 --- a/src/views/SettingsView.vue +++ b/src/views/SettingsView.vue @@ -334,8 +334,7 @@ import { saveAs } from 'file-saver' import { toast } from 'vue-sonner' import { Capacitor } from '@capacitor/core' - import { Filesystem, Directory } from '@capacitor/filesystem' - import { Share } from '@capacitor/share' + import { Filesystem, Directory, Encoding } from '@capacitor/filesystem' import pkg from '../../package.json' import { checkLatestVersion, canCheckVersion } from '@/utils/versionCheck' import type { VersionInfo } from '@/utils/versionCheck' @@ -527,20 +526,16 @@ const fileName = `${pkg.name}-${new Date().toISOString().slice(0, 10)}-${Date.now()}.json` const jsonString = JSON.stringify(exportData, null, 2) - // Android 使用 Capacitor Filesystem + Share + // Android 保存到 Documents 目录 if (Capacitor.isNativePlatform()) { - // 写入文件到缓存目录 const result = await Filesystem.writeFile({ path: fileName, data: jsonString, - directory: Directory.Cache - }) - // 分享文件让用户选择保存位置 - await Share.share({ - title: t('settings.exportData'), - url: result.uri, - dialogTitle: t('settings.exportData') + directory: Directory.Documents, + encoding: Encoding.UTF8 }) + toast.success(t('settings.exportSuccessWithPath', { path: result.uri })) + return } else { // Web 使用 file-saver saveAs(new Blob([jsonString], { type: 'application/json' }), fileName)