From c15992a086ca8d718b9cf7863dcecc78acd53f10 Mon Sep 17 00:00:00 2001 From: Yukon <126093594+baseGame@users.noreply.github.com> Date: Wed, 7 Oct 2026 04:18:30 +0800 Subject: [PATCH 1/2] Clarify Script empty states and run hints Make the Script session friendlier for first-time users: plain how-to intro, empty hint, path/source placeholders, gated Run Script tip, friendlier run-log summary lines, plain errors, docs hint for commands, and Save Report labeling on the shared reports toolbar. --- src/app/sessionCatalog.ts | 3 +- src/i18n/locales/de-DE.ts | 21 +++++-- src/i18n/locales/en-US.ts | 19 ++++-- src/i18n/locales/es-ES.ts | 21 +++++-- src/i18n/locales/fr-FR.ts | 21 +++++-- src/i18n/locales/ja-JP.ts | 20 +++++-- src/i18n/locales/ko-KR.ts | 19 ++++-- src/i18n/locales/zh-CN.ts | 18 ++++-- src/i18n/locales/zh-TW.ts | 18 ++++-- src/views/reports/ReportsScriptView.test.ts | 54 +++++++++++++++-- src/views/reports/ReportsScriptView.vue | 65 ++++++++++++++++----- 11 files changed, 224 insertions(+), 55 deletions(-) diff --git a/src/app/sessionCatalog.ts b/src/app/sessionCatalog.ts index 83dcea6f..adb9aec7 100644 --- a/src/app/sessionCatalog.ts +++ b/src/app/sessionCatalog.ts @@ -189,8 +189,7 @@ export const sessionCatalog: SessionCatalogEntry[] = [ type: 'script', title: 'Script', titleKey: 'ui.script', - summary: - 'Run automation scripts with LOAD/COMPARE/REPORT, file ops, IF/ELSE, CALL/INCLUDE, samples, run log, and Stop', + summary: 'Run a script to load files, compare, write reports, and stop', summaryKey: 'session.summary.script', priority: 'P2', implemented: true, diff --git a/src/i18n/locales/de-DE.ts b/src/i18n/locales/de-DE.ts index 071fddf8..c7df066e 100644 --- a/src/i18n/locales/de-DE.ts +++ b/src/i18n/locales/de-DE.ts @@ -535,7 +535,7 @@ export const deDE: LanguagePack = { 'ui.automation': 'Automatisierung', 'ui.cli': 'CLI', 'ui.cliReportsAndRepeatableComparisonJobs': - 'CLI, Berichte und wiederholbare Vergleichsaufträge', + 'Berichte exportieren oder Automatisierungsskripte ausführen', 'ui.commonAncestor': 'Gemeinsamer Vorgänger', 'ui.directory': 'Verzeichnis', 'ui.draft': 'Entwurf', @@ -579,7 +579,7 @@ export const deDE: LanguagePack = { 'ui.same': 'Gleich', 'ui.settingsInspector': 'Einstellungsinspektor', 'ui.shell': 'Shell', - 'ui.scriptCli': 'Skript / CLI', + 'ui.scriptCli': 'Skript', 'ui.tableCompareInspector': 'Tabellenvergleich-Inspektor', 'ui.textCompareInspector': 'Textvergleich-Inspektor', 'ui.textMergeInspector': 'Textzusammenführung-Inspektor', @@ -770,7 +770,8 @@ export const deDE: LanguagePack = { 'ui.sheetSelectionSummary': '{leftCount} left / {rightCount} right · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': 'Compare ZIP/TAR/7z sides and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': + 'Skript ausführen: laden, vergleichen, Berichte schreiben und beenden', 'ui.archiveCompare': 'Archivvergleich', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -838,7 +839,19 @@ export const deDE: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - 'Die vollständige Legacy-Skriptsprache ist nicht implementiert. Unterstützte Befehle laufen; bekannte Lücken liefern unsupported.', + 'Beispielskript wählen (oder Befehle bearbeiten), dann Skript ausführen.', + 'ui.scriptEmptyHint': + 'Beispielskript wählen (oder Befehle einfügen), dann auf Skript ausführen klicken.', + 'ui.scriptPathPlaceholder': 'Optionaler Pfad zu einer Skriptdatei', + 'ui.scriptSourcePlaceholder': + 'Skriptbefehle wie LOAD, COMPARE und TEXT-REPORT — oder oben ein Beispiel wählen', + 'ui.runScriptNeedsSource': 'Zuerst ein Skript eingeben oder laden.', + 'ui.scriptCommandDocsHint': + 'Befehle unten. Beispiele zeigen typische LOAD → COMPARE → REPORT-Abläufe.', + 'ui.scriptLogExecuted': 'Befehle ausgeführt: {count}', + 'ui.scriptLogCompared': 'Verglichen: {count}', + 'ui.scriptLogDifferent': 'Unterschiedlich: {count}', + 'ui.scriptLogReports': 'Berichte geschrieben: {count}', 'ui.scriptingSupported': 'Unterstützt: LOAD, FILTER, COMPARE, REPORT, FILE-REPORT, HEX-REPORT, TABLE-REPORT, PICTURE-REPORT, VERSION-REPORT, REGISTRY-REPORT, MEDIA-REPORT, LOG, BEEP, OPTION, SELECT, COPY, COPYTO, MOVE, MOVETO, DELETE, RENAME, TOUCH, ATTRIB, EXPAND, COLLAPSE, SNAPSHOT, SYNC, CRITERIA, TEXT-REPORT, FOLDER-REPORT.', 'ui.scriptingUnsupported': 'Keine.', diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 97e5f0a2..cad68881 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -104,7 +104,7 @@ export const enUS: LanguagePack = { 'ui.clipboardText': 'Clipboard text', 'ui.clipboardEntryTitle': 'Clipboard {index}', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI, reports, and repeatable comparison jobs', + 'ui.cliReportsAndRepeatableComparisonJobs': 'Export reports or run automation scripts', 'ui.close': 'Close', 'ui.closeAll': 'Close All', 'ui.closeOthers': 'Close Others', @@ -458,7 +458,7 @@ export const enUS: LanguagePack = { 'ui.size': 'Size', 'ui.source': 'Source', 'ui.sources': 'Sources', - 'ui.scriptCli': 'Script / CLI', + 'ui.scriptCli': 'Script', 'ui.state': 'State', 'ui.status': 'Status', 'ui.strategy': 'Strategy', @@ -757,7 +757,7 @@ export const enUS: LanguagePack = { 'session.summary.versionCompare': 'Compare version info inside program files', 'session.summary.archiveCompare': 'Compare ZIP, TAR, or 7z archives and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': 'Run a script to load files, compare, write reports, and stop', 'ui.archiveCompare': 'Archive Compare', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -824,7 +824,18 @@ export const enUS: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - 'Full legacy scripting is not implemented. Supported commands run; known gaps fail as unsupported.', + 'Pick a sample script (or edit the commands), then click Run Script.', + 'ui.scriptEmptyHint': 'Pick a sample script (or paste commands), then click Run Script.', + 'ui.scriptPathPlaceholder': 'Optional path to a script file', + 'ui.scriptSourcePlaceholder': + 'Script commands such as LOAD, COMPARE, and TEXT-REPORT — or choose a sample above', + 'ui.runScriptNeedsSource': 'Enter or load a script first.', + 'ui.scriptCommandDocsHint': + 'Commands you can use below. Samples show common LOAD → COMPARE → REPORT flows.', + 'ui.scriptLogExecuted': 'Commands run: {count}', + 'ui.scriptLogCompared': 'Compared: {count}', + 'ui.scriptLogDifferent': 'Different: {count}', + 'ui.scriptLogReports': 'Reports written: {count}', 'ui.scriptingSupported': 'Supported commands: LOAD, FILTER, COMPARE, REPORT, FILE-REPORT, HEX-REPORT, TABLE-REPORT, PICTURE-REPORT, VERSION-REPORT, REGISTRY-REPORT, MEDIA-REPORT, LOG, BEEP, OPTION, SELECT, COPY, COPYTO, MOVE, MOVETO, DELETE, RENAME, TOUCH, ATTRIB, EXPAND, COLLAPSE, SNAPSHOT, SYNC, CRITERIA, TEXT-REPORT, FOLDER-REPORT.', 'ui.scriptingUnsupported': 'None.', diff --git a/src/i18n/locales/es-ES.ts b/src/i18n/locales/es-ES.ts index 78571e57..509190b9 100644 --- a/src/i18n/locales/es-ES.ts +++ b/src/i18n/locales/es-ES.ts @@ -531,7 +531,7 @@ export const esES: LanguagePack = { 'ui.automation': 'Automatización', 'ui.cli': 'CLI', 'ui.cliReportsAndRepeatableComparisonJobs': - 'CLI, informes y trabajos de comparación repetibles', + 'Exportar informes o ejecutar scripts de automatización', 'ui.commonAncestor': 'Ancestro común', 'ui.directory': 'Directorio', 'ui.draft': 'Borrador', @@ -575,7 +575,7 @@ export const esES: LanguagePack = { 'ui.same': 'Igual', 'ui.settingsInspector': 'Inspector de configuración', 'ui.shell': 'Shell', - 'ui.scriptCli': 'Script / CLI', + 'ui.scriptCli': 'Script', 'ui.tableCompareInspector': 'Inspector de comparación de tablas', 'ui.textCompareInspector': 'Inspector de comparación de texto', 'ui.textMergeInspector': 'Inspector de fusión de texto', @@ -765,7 +765,8 @@ export const esES: LanguagePack = { 'ui.sheetSelectionSummary': '{leftCount} left / {rightCount} right · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': 'Compare ZIP/TAR/7z sides and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': + 'Ejecutar un script para cargar, comparar, escribir informes y detener', 'ui.archiveCompare': 'Comparar archivos', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -834,7 +835,19 @@ export const esES: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - 'El lenguaje de scripts heredado completo no está implementado. Los comandos admitidos se ejecutan; las lagunas conocidas devuelven unsupported.', + 'Elija un script de ejemplo (o edite los comandos) y luego Ejecutar script.', + 'ui.scriptEmptyHint': + 'Elija un script de ejemplo (o pegue comandos) y luego haga clic en Ejecutar script.', + 'ui.scriptPathPlaceholder': 'Ruta opcional a un archivo de script', + 'ui.scriptSourcePlaceholder': + 'Comandos como LOAD, COMPARE y TEXT-REPORT — o elija un ejemplo arriba', + 'ui.runScriptNeedsSource': 'Introduzca o cargue un script primero.', + 'ui.scriptCommandDocsHint': + 'Comandos disponibles abajo. Los ejemplos muestran LOAD → COMPARE → REPORT.', + 'ui.scriptLogExecuted': 'Comandos ejecutados: {count}', + 'ui.scriptLogCompared': 'Comparado: {count}', + 'ui.scriptLogDifferent': 'Diferente: {count}', + 'ui.scriptLogReports': 'Informes escritos: {count}', 'ui.scriptingSupported': 'Comandos admitidos: LOAD, FILTER, COMPARE, REPORT, FILE-REPORT, HEX-REPORT, TABLE-REPORT, PICTURE-REPORT, VERSION-REPORT, REGISTRY-REPORT, MEDIA-REPORT, LOG, BEEP, OPTION, SELECT, COPY, COPYTO, MOVE, MOVETO, DELETE, RENAME, TOUCH, ATTRIB, EXPAND, COLLAPSE, SNAPSHOT, SYNC, CRITERIA, TEXT-REPORT, FOLDER-REPORT.', 'ui.scriptingUnsupported': 'Ninguno.', diff --git a/src/i18n/locales/fr-FR.ts b/src/i18n/locales/fr-FR.ts index 4eac9888..ff0658b9 100644 --- a/src/i18n/locales/fr-FR.ts +++ b/src/i18n/locales/fr-FR.ts @@ -530,7 +530,7 @@ export const frFR: LanguagePack = { 'ui.added': 'Ajouté', 'ui.automation': 'Automatisation', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI, rapports et tâches de comparaison répétables', + 'ui.cliReportsAndRepeatableComparisonJobs': 'Exporter des rapports ou exécuter des scripts', 'ui.commonAncestor': 'Ancêtre commun', 'ui.directory': 'Dossier', 'ui.draft': 'Brouillon', @@ -574,7 +574,7 @@ export const frFR: LanguagePack = { 'ui.same': 'Identique', 'ui.settingsInspector': 'Inspecteur des paramètres', 'ui.shell': 'Shell', - 'ui.scriptCli': 'Script / CLI', + 'ui.scriptCli': 'Script', 'ui.tableCompareInspector': 'Inspecteur de comparaison de tableaux', 'ui.textCompareInspector': 'Inspecteur de comparaison de texte', 'ui.textMergeInspector': 'Inspecteur de fusion de texte', @@ -766,7 +766,8 @@ export const frFR: LanguagePack = { 'ui.sheetSelectionSummary': '{leftCount} left / {rightCount} right · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': 'Compare ZIP/TAR/7z sides and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': + 'Exécuter un script pour charger, comparer, écrire des rapports et arrêter', 'ui.archiveCompare': 'Comparaison d’archives', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -834,7 +835,19 @@ export const frFR: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - 'Le langage de script hérité complet n’est pas implémenté. Les commandes prises en charge s’exécutent ; les lacunes connues renvoient unsupported.', + 'Choisissez un exemple (ou modifiez les commandes), puis cliquez sur Exécuter le script.', + 'ui.scriptEmptyHint': + 'Choisissez un exemple (ou collez des commandes), puis cliquez sur Exécuter le script.', + 'ui.scriptPathPlaceholder': 'Chemin facultatif vers un fichier script', + 'ui.scriptSourcePlaceholder': + 'Commandes telles que LOAD, COMPARE et TEXT-REPORT — ou choisissez un exemple ci-dessus', + 'ui.runScriptNeedsSource': "Saisissez ou chargez d'abord un script.", + 'ui.scriptCommandDocsHint': + 'Commandes disponibles ci-dessous. Les exemples montrent LOAD → COMPARE → REPORT.', + 'ui.scriptLogExecuted': 'Commandes exécutées : {count}', + 'ui.scriptLogCompared': 'Comparé : {count}', + 'ui.scriptLogDifferent': 'Différent : {count}', + 'ui.scriptLogReports': 'Rapports écrits : {count}', 'ui.scriptingSupported': 'Commandes prises en charge : LOAD, FILTER, COMPARE, REPORT, FILE-REPORT, HEX-REPORT, TABLE-REPORT, PICTURE-REPORT, VERSION-REPORT, REGISTRY-REPORT, MEDIA-REPORT, LOG, BEEP, OPTION, SELECT, COPY, COPYTO, MOVE, MOVETO, DELETE, RENAME, TOUCH, ATTRIB, EXPAND, COLLAPSE, SNAPSHOT, SYNC, CRITERIA, TEXT-REPORT, FOLDER-REPORT.', 'ui.scriptingUnsupported': 'Aucun.', diff --git a/src/i18n/locales/ja-JP.ts b/src/i18n/locales/ja-JP.ts index b5d7adaa..d6bae891 100644 --- a/src/i18n/locales/ja-JP.ts +++ b/src/i18n/locales/ja-JP.ts @@ -103,7 +103,7 @@ export const jaJP: LanguagePack = { 'ui.clipboardText': 'Clipboard text', 'ui.clipboardEntryTitle': 'クリップボード {index}', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI, reports, and repeatable comparison jobs', + 'ui.cliReportsAndRepeatableComparisonJobs': 'レポートの書き出し、または自動化スクリプトの実行', 'ui.close': 'Close', 'ui.closeAll': 'Close All', 'ui.closeOthers': '他を閉じる', @@ -455,7 +455,7 @@ export const jaJP: LanguagePack = { 'ui.size': 'Size', 'ui.source': 'Source', 'ui.sources': 'Sources', - 'ui.scriptCli': 'Script / CLI', + 'ui.scriptCli': 'スクリプト', 'ui.state': 'State', 'ui.status': 'Status', 'ui.strategy': 'Strategy', @@ -752,7 +752,7 @@ export const jaJP: LanguagePack = { 'session.summary.textPatch': 'Review and apply a patch file', 'session.summary.versionCompare': 'Compare version info inside program files', 'session.summary.archiveCompare': 'Compare ZIP/TAR/7z sides and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': 'スクリプトで読み込み・比較・レポート出力・停止を行います', 'ui.archiveCompare': 'アーカイブ比較', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -819,7 +819,19 @@ export const jaJP: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - '完全なレガシースクリプト言語は未実装です。対応コマンドは実行され、既知の欠落は unsupported を返します。', + 'サンプルを選ぶかコマンドを編集してから、スクリプトの実行をクリックします。', + 'ui.scriptEmptyHint': + 'サンプルを選ぶかコマンドを貼り付けてから、スクリプトの実行をクリックします。', + 'ui.scriptPathPlaceholder': 'スクリプトファイルのパス(任意)', + 'ui.scriptSourcePlaceholder': + 'LOAD、COMPARE、TEXT-REPORT などのコマンド — または上のサンプルを選択', + 'ui.runScriptNeedsSource': '先にスクリプトを入力または読み込んでください。', + 'ui.scriptCommandDocsHint': + '使えるコマンドは以下です。サンプルは LOAD → COMPARE → REPORT の流れを示します。', + 'ui.scriptLogExecuted': '実行したコマンド: {count}', + 'ui.scriptLogCompared': '比較: {count}', + 'ui.scriptLogDifferent': '差分あり: {count}', + 'ui.scriptLogReports': '書いたレポート: {count}', 'ui.scriptingSupported': '対応: LOAD、FILTER、COMPARE、REPORT、FILE-REPORT、HEX-REPORT、TABLE-REPORT、PICTURE-REPORT、VERSION-REPORT、REGISTRY-REPORT、MEDIA-REPORT、LOG、BEEP、OPTION、SELECT、COPY、COPYTO、MOVE、MOVETO、DELETE、RENAME、TOUCH、ATTRIB、EXPAND、COLLAPSE、SNAPSHOT、SYNC、CRITERIA、TEXT-REPORT、FOLDER-REPORT。', 'ui.scriptingUnsupported': 'なし。', diff --git a/src/i18n/locales/ko-KR.ts b/src/i18n/locales/ko-KR.ts index 66340194..0c54092e 100644 --- a/src/i18n/locales/ko-KR.ts +++ b/src/i18n/locales/ko-KR.ts @@ -518,7 +518,7 @@ export const koKR: LanguagePack = { 'ui.added': '추가됨', 'ui.automation': '자동화', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI, 보고서 및 반복 가능한 비교 작업', + 'ui.cliReportsAndRepeatableComparisonJobs': '보고서를 내보내거나 자동화 스크립트를 실행합니다', 'ui.commonAncestor': '공통 조상', 'ui.directory': '디렉터리', 'ui.draft': '초안', @@ -562,7 +562,7 @@ export const koKR: LanguagePack = { 'ui.same': '동일', 'ui.settingsInspector': '설정 검사기', 'ui.shell': '셸', - 'ui.scriptCli': '스크립트 / CLI', + 'ui.scriptCli': '스크립트', 'ui.tableCompareInspector': '테이블 비교 검사기', 'ui.textCompareInspector': '텍스트 비교 검사기', 'ui.textMergeInspector': '텍스트 병합 검사기', @@ -748,7 +748,7 @@ export const koKR: LanguagePack = { 'ui.sheetSelectionSummary': '{leftCount} left / {rightCount} right · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': 'Compare ZIP/TAR/7z sides and copy files out into a folder', - 'session.summary.script': 'Run automation scripts to load, compare, report, and stop a session', + 'session.summary.script': '스크립트로 파일을 불러오고 비교·보고서 작성 후 중지합니다', 'ui.archiveCompare': '아카이브 비교', 'ui.archivePathHint': 'Folders or ZIP/TAR/7z archives. Snapshot JSON or sftp://profile/id/path, webdav://profile/id/path, s3://profile/id/path, dropbox://profile/id/path, onedrive://profile/id/path, and svn://profile/id/path also work.', @@ -815,7 +815,18 @@ export const koKR: LanguagePack = { 'ui.scriptPromptTitle': 'Script prompt', 'ui.scriptPromptAnswer': 'Answer', 'ui.scriptingNotImplemented': - '전체 레거시 스크립트 언어는 구현되지 않았습니다. 지원 명령은 실행되고, 알려진 공백은 unsupported를 반환합니다.', + '샘플 스크립트를 고르거나 명령을 편집한 뒤 스크립트 실행을 누르세요.', + 'ui.scriptEmptyHint': '샘플 스크립트를 고르거나 명령을 붙여넣은 뒤 스크립트 실행을 클릭하세요.', + 'ui.scriptPathPlaceholder': '선택적 스크립트 파일 경로', + 'ui.scriptSourcePlaceholder': + 'LOAD, COMPARE, TEXT-REPORT 같은 스크립트 명령 — 또는 위에서 샘플을 고르세요', + 'ui.runScriptNeedsSource': '먼저 스크립트를 입력하거나 불러오세요.', + 'ui.scriptCommandDocsHint': + '아래는 사용 가능한 명령입니다. 샘플은 LOAD → COMPARE → REPORT 흐름을 보여 줍니다.', + 'ui.scriptLogExecuted': '실행한 명령: {count}', + 'ui.scriptLogCompared': '비교함: {count}', + 'ui.scriptLogDifferent': '다름: {count}', + 'ui.scriptLogReports': '작성한 보고서: {count}', 'ui.scriptingSupported': '지원: LOAD, FILTER, COMPARE, REPORT, FILE-REPORT, HEX-REPORT, TABLE-REPORT, PICTURE-REPORT, VERSION-REPORT, REGISTRY-REPORT, MEDIA-REPORT, LOG, BEEP, OPTION, SELECT, COPY, COPYTO, MOVE, MOVETO, DELETE, RENAME, TOUCH, ATTRIB, EXPAND, COLLAPSE, SNAPSHOT, SYNC, CRITERIA, TEXT-REPORT, FOLDER-REPORT.', 'ui.scriptingUnsupported': '없음.', diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 4f297a9c..be16d0bc 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -507,7 +507,7 @@ export const zhCN: LanguagePack = { 'ui.added': '已添加', 'ui.automation': '自动化', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI、报告和可重复比较任务', + 'ui.cliReportsAndRepeatableComparisonJobs': '导出报告或运行自动化脚本', 'ui.commonAncestor': '共同祖先', 'ui.directory': '目录', 'ui.draft': '草稿', @@ -551,7 +551,7 @@ export const zhCN: LanguagePack = { 'ui.same': '相同', 'ui.settingsInspector': '设置检查器', 'ui.shell': 'Shell', - 'ui.scriptCli': '脚本 / CLI', + 'ui.scriptCli': '脚本', 'ui.tableCompareInspector': '表格比较检查器', 'ui.textCompareInspector': '文本比较检查器', 'ui.textMergeInspector': '文本合并检查器', @@ -735,7 +735,7 @@ export const zhCN: LanguagePack = { 'ui.sheetSelectionEmpty': 'Excel 或 HTML 比较后显示工作表', 'ui.sheetSelectionSummary': '左 {leftCount} / 右 {rightCount} · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': '对比 ZIP/TAR/7z 压缩包并支持复制到文件夹', - 'session.summary.script': '运行自动化脚本:加载、比较、导出报告并可停止', + 'session.summary.script': '运行脚本以加载文件、比较、写出报告并停止', 'ui.archiveCompare': '压缩包比较', 'ui.archivePathHint': '文件夹或 ZIP/TAR/7z 压缩包。也支持快照 JSON,或 sftp://profile/id/path、webdav://profile/id/path、s3://profile/id/path、svn://profile/id/path', @@ -797,8 +797,16 @@ export const zhCN: LanguagePack = { 'ui.scriptMessageTitle': '脚本消息', 'ui.scriptPromptTitle': '脚本提示', 'ui.scriptPromptAnswer': '回答', - 'ui.scriptingNotImplemented': - '完整遗留脚本语言尚未实现。已支持的命令会真正执行;已知缺口以 unsupported 返回。', + 'ui.scriptingNotImplemented': '选择示例脚本(或编辑命令),然后点运行脚本。', + 'ui.scriptEmptyHint': '选择示例脚本(或粘贴命令),然后点运行脚本。', + 'ui.scriptPathPlaceholder': '可选的脚本文件路径', + 'ui.scriptSourcePlaceholder': '脚本命令,例如 LOAD、COMPARE、TEXT-REPORT — 或从上方选择示例', + 'ui.runScriptNeedsSource': '请先输入或加载脚本。', + 'ui.scriptCommandDocsHint': '下方是可用命令。示例展示常见的 LOAD → COMPARE → REPORT 流程。', + 'ui.scriptLogExecuted': '已执行命令:{count}', + 'ui.scriptLogCompared': '已比较:{count}', + 'ui.scriptLogDifferent': '有差异:{count}', + 'ui.scriptLogReports': '已写报告:{count}', 'ui.scriptingSupported': '已支持:LOAD、FILTER、COMPARE、REPORT、FILE-REPORT、HEX-REPORT、TABLE-REPORT、PICTURE-REPORT、VERSION-REPORT、REGISTRY-REPORT、MEDIA-REPORT、LOG、BEEP、OPTION、SELECT、COPY、COPYTO、MOVE、MOVETO、DELETE、RENAME、TOUCH、ATTRIB、EXPAND、COLLAPSE、SNAPSHOT、SYNC、CRITERIA、TEXT-REPORT、FOLDER-REPORT。', 'ui.scriptingUnsupported': '无。', diff --git a/src/i18n/locales/zh-TW.ts b/src/i18n/locales/zh-TW.ts index 50350f3c..15783386 100644 --- a/src/i18n/locales/zh-TW.ts +++ b/src/i18n/locales/zh-TW.ts @@ -508,7 +508,7 @@ export const zhTW: LanguagePack = { 'ui.added': '已新增', 'ui.automation': '自動化', 'ui.cli': 'CLI', - 'ui.cliReportsAndRepeatableComparisonJobs': 'CLI、報告和可重複比較工作', + 'ui.cliReportsAndRepeatableComparisonJobs': '匯出報告或執行自動化指令碼', 'ui.commonAncestor': '共同祖先', 'ui.directory': '目錄', 'ui.draft': '草稿', @@ -552,7 +552,7 @@ export const zhTW: LanguagePack = { 'ui.same': '相同', 'ui.settingsInspector': '設定檢查器', 'ui.shell': 'Shell', - 'ui.scriptCli': '腳本 / CLI', + 'ui.scriptCli': '指令碼', 'ui.tableCompareInspector': '表格比較檢查器', 'ui.textCompareInspector': '文字比較檢查器', 'ui.textMergeInspector': '文字合併檢查器', @@ -736,7 +736,7 @@ export const zhTW: LanguagePack = { 'ui.sheetSelectionEmpty': 'Excel 或 HTML 比較後顯示工作表', 'ui.sheetSelectionSummary': '左 {leftCount} / 右 {rightCount} · {leftSheet} vs {rightSheet}', 'session.summary.archiveCompare': '對比 ZIP/TAR/7z 壓縮檔並支援複製到資料夾', - 'session.summary.script': '執行自動化指令碼:載入、比較、匯出報告並可停止', + 'session.summary.script': '執行指令碼以載入檔案、比較、寫出報告並停止', 'ui.archiveCompare': '壓縮檔比較', 'ui.archivePathHint': '資料夾或 ZIP/TAR/7z 壓縮檔。也支援快照 JSON,或 sftp://profile/id/path、webdav://profile/id/path、s3://profile/id/path、svn://profile/id/path', @@ -798,8 +798,16 @@ export const zhTW: LanguagePack = { 'ui.scriptMessageTitle': '指令碼訊息', 'ui.scriptPromptTitle': '指令碼提示', 'ui.scriptPromptAnswer': '回答', - 'ui.scriptingNotImplemented': - '完整遺留指令碼語言尚未實作。已支援的命令會真正執行;已知缺口以 unsupported 回傳。', + 'ui.scriptingNotImplemented': '選擇範例指令碼(或編輯命令),然後按執行指令碼。', + 'ui.scriptEmptyHint': '選擇範例指令碼(或貼上命令),然後按執行指令碼。', + 'ui.scriptPathPlaceholder': '選用的指令碼檔案路徑', + 'ui.scriptSourcePlaceholder': '指令碼命令,例如 LOAD、COMPARE、TEXT-REPORT — 或從上方選擇範例', + 'ui.runScriptNeedsSource': '請先輸入或載入指令碼。', + 'ui.scriptCommandDocsHint': '下方是可用命令。範例展示常見的 LOAD → COMPARE → REPORT 流程。', + 'ui.scriptLogExecuted': '已執行命令:{count}', + 'ui.scriptLogCompared': '已比較:{count}', + 'ui.scriptLogDifferent': '有差異:{count}', + 'ui.scriptLogReports': '已寫報告:{count}', 'ui.scriptingSupported': '已支援:LOAD、FILTER、COMPARE、REPORT、FILE-REPORT、HEX-REPORT、TABLE-REPORT、PICTURE-REPORT、VERSION-REPORT、REGISTRY-REPORT、MEDIA-REPORT、LOG、BEEP、OPTION、SELECT、COPY、COPYTO、MOVE、MOVETO、DELETE、RENAME、TOUCH、ATTRIB、EXPAND、COLLAPSE、SNAPSHOT、SYNC、CRITERIA、TEXT-REPORT、FOLDER-REPORT。', 'ui.scriptingUnsupported': '無。', diff --git a/src/views/reports/ReportsScriptView.test.ts b/src/views/reports/ReportsScriptView.test.ts index bdca8f0b..9c047cb8 100644 --- a/src/views/reports/ReportsScriptView.test.ts +++ b/src/views/reports/ReportsScriptView.test.ts @@ -140,7 +140,7 @@ describe('ReportsScriptView', () => { source: 'load left.txt\nload right.txt\ncompare\ntext-report out.txt\n', path: 'C:/work/job.open-diff-script', }) - expect(wrapper.find('[data-testid="script-result"]').text()).toContain('reports=1') + expect(wrapper.find('[data-testid="script-result"]').text()).toContain('Reports written: 1') expect(wrapper.find('[data-testid="script-result"]').text()).toContain('wrote report.txt') expect(wrapper.find('[data-testid="script-run-log"]').text()).toContain('wrote report.txt') }) @@ -197,13 +197,55 @@ describe('ReportsScriptView', () => { expect(wrapper.find('[data-testid="script-supported-commands"]').text()).toContain('ATTRIB') expect(wrapper.find('[data-testid="script-supported-commands"]').text()).toContain('MOVETO') expect(wrapper.find('[data-testid="script-supported-commands"]').text()).toContain('CRITERIA') - expect(wrapper.find('[data-testid="script-unsupported-commands"]').text()).not.toContain( - 'CRITERIA', + expect(wrapper.find('[data-testid="script-unsupported-commands"]').exists()).toBe(false) + expect(wrapper.find('[data-testid="script-docs-hint"]').text()).toContain('Samples show') + expect(wrapper.text()).not.toMatch(/Beyond Compare|\bBC5?\b|Scooter/i) + }) + + it('guides first-time Script users with empty hint, placeholders, and gated Run', async () => { + const wrapper = mount(ReportsScriptView) + + expect(wrapper.find('[data-testid="script-empty-hint"]').text()).toContain( + 'Pick a sample script', ) - expect(wrapper.find('[data-testid="script-unsupported-commands"]').text()).not.toContain( - 'MEDIA-REPORT', + expect(wrapper.find('[data-testid="script-path"]').attributes('placeholder')).toContain( + 'Optional path', ) - expect(wrapper.text()).not.toMatch(/Beyond Compare|\bBC5?\b|Scooter/i) + expect(wrapper.find('[data-testid="script-source"]').attributes('placeholder')).toContain( + 'LOAD', + ) + expect(wrapper.find('[data-testid="run-script"]').attributes('title')).toContain('Run Script') + + await wrapper.find('[data-testid="script-source"]').setValue(' ') + await wrapper.vm.$nextTick() + + expect((wrapper.find('[data-testid="run-script"]').element as HTMLButtonElement).disabled).toBe( + true, + ) + expect(wrapper.find('[data-testid="run-script"]').attributes('title')).toContain( + 'Enter or load a script first', + ) + }) + + it('labels the export action Save Report instead of Compare', () => { + const wrapper = mount(ReportsScriptView) + + expect(wrapper.find('[data-testid="run-report-export"]').text()).toContain('Save Report') + }) + + it('surfaces plain script errors instead of raw invoke noise', async () => { + vi.mocked(runScript).mockRejectedValueOnce( + new Error('ENOENT: no such file or directory, open script.txt'), + ) + const wrapper = mount(ReportsScriptView) + + await wrapper.find('[data-testid="run-script"]').trigger('click') + await flushPromises() + + expect(wrapper.find('[data-testid="report-export-error"]').text()).toContain( + 'could not be found', + ) + expect(wrapper.find('[data-testid="report-export-error"]').text()).not.toContain('ENOENT') }) it('offers csv as a report export format', () => { diff --git a/src/views/reports/ReportsScriptView.vue b/src/views/reports/ReportsScriptView.vue index f345c494..7436de23 100644 --- a/src/views/reports/ReportsScriptView.vue +++ b/src/views/reports/ReportsScriptView.vue @@ -5,6 +5,7 @@ import { exportFolderCompareReport, exportTextCompareReport } from '@/api/diff' import { revealPathInOs } from '@/api/integration' import { answerScriptPrompt, runScript, stopScript } from '@/api/script' import { playCompareCompleteBeep } from '@/app/compareCompleteNotify' +import { formatCompareError } from '@/app/compareError' import { useSettingsStore } from '@/stores/settings' import { useTabsStore } from '@/stores/tabs' import { useRouter } from 'vue-router' @@ -62,6 +63,16 @@ const router = useRouter() const scriptRunning = ref(false) const selectedSampleId = ref(sampleScripts[0]?.id ?? 'text-report') const viewActions = useViewActionsStore() +const scriptSourceIsEmpty = computed(() => !scriptSource.value.trim()) +const runScriptDisabled = computed(() => scriptRunning.value || scriptSourceIsEmpty.value) +const runScriptTip = computed(() => + scriptSourceIsEmpty.value ? t('ui.runScriptNeedsSource') : t('ui.runScript'), +) +const showScriptEmptyHint = computed( + () => scriptLog.value.length === 0 && !scriptResult.value && !error.value, +) +const hasUnsupportedCommands = computed(() => unsupportedCommandsLabel.trim().length > 0) + const scriptPromptVisible = ref(false) const scriptPromptId = ref(0) const scriptPromptMessage = ref('') @@ -112,7 +123,7 @@ async function submitScriptPrompt(cancelled: boolean): Promise { cancelled, }) } catch (event) { - error.value = String(event) + error.value = formatCompareError(event, t) } } @@ -189,7 +200,7 @@ async function runExport(): Promise { } } } catch (event) { - error.value = String(event) + error.value = formatCompareError(event, t) jobs.value = recordRecentReportExport(jobs.value, { name: t('ui.export'), type: reportFormat.value.toUpperCase(), @@ -225,11 +236,15 @@ async function stopCurrentScript(): Promise { await stopScript() scriptLog.value = [...scriptLog.value, t('ui.scriptStopped')] } catch (event) { - error.value = String(event) + error.value = formatCompareError(event, t) } } async function runCurrentScript(): Promise { + if (scriptSourceIsEmpty.value || scriptRunning.value) { + return + } + scriptRunning.value = true error.value = '' scriptResult.value = '' @@ -242,10 +257,10 @@ async function runCurrentScript(): Promise { }) const lines = [ - `executed=${String(response.executed)}`, - `compared=${String(response.compared)}`, - `different=${String(response.different)}`, - `reports=${String(response.reportsWritten)}`, + t('ui.scriptLogExecuted', { count: response.executed }), + t('ui.scriptLogCompared', { count: response.compared }), + t('ui.scriptLogDifferent', { count: response.different }), + t('ui.scriptLogReports', { count: response.reportsWritten }), ...(response.cancelled ? [t('ui.scriptStopped')] : []), ...response.logs, ] @@ -273,7 +288,7 @@ async function runCurrentScript(): Promise { void router.push('/') } } catch (event) { - error.value = String(event) + error.value = formatCompareError(event, t) jobs.value = recordRecentReportExport(jobs.value, { name: t('ui.runScript'), type: 'SCRIPT', @@ -445,7 +460,7 @@ function fillFromLastCompare(): void { :disabled="running" @click="runExport" > - {{ $t('ui.runDiff') }} + {{ $t('ui.saveReport') }}