fix(files): close preview on navigation/delete/rename + backfill i18n (#150)
* i18n: backfill files/download translations for de, es, fr, ja, ko, pt Add nav.files, files.* (39 keys), and download.* (9 keys) so the file browser UI is fully localized in these six locales instead of falling back to English. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(files): close preview when navigating or affected file changes Opening a preview and then navigating directories, deleting the previewed file, or renaming it left the preview pane stuck on stale content because previewFile was never cleared. - stores/hermes/files.ts: - fetchEntries clears previewFile on path change (in-place refresh keeps the preview). - deleteEntry / renameEntry clear preview/editor state when the affected entry matches the previewed/edited file or its parent. - Add isAffected(target, changed, isDir) helper. - components/hermes/files/FilePreview.vue: replace the misleading common.cancel close button with a dedicated files.closePreview key plus an X icon and quaternary style. - i18n: add files.closePreview to all 8 locales. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton } from 'naive-ui'
|
||||
import { h } from 'vue'
|
||||
import { NButton, NIcon } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useFilesStore } from '@/stores/hermes/files'
|
||||
import { getFileDownloadUrl } from '@/api/hermes/files'
|
||||
@@ -12,14 +13,24 @@ function getImageUrl(): string {
|
||||
if (!filesStore.previewFile) return ''
|
||||
return getFileDownloadUrl(filesStore.previewFile.path)
|
||||
}
|
||||
|
||||
const CloseIcon = () =>
|
||||
h(
|
||||
'svg',
|
||||
{ viewBox: '0 0 24 24', width: '14', height: '14', fill: 'currentColor' },
|
||||
[h('path', { d: 'M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z' })],
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="file-preview" v-if="filesStore.previewFile">
|
||||
<div class="preview-header">
|
||||
<span class="preview-filename">{{ filesStore.previewFile.path }}</span>
|
||||
<NButton size="small" @click="filesStore.closePreview()">
|
||||
{{ t('common.cancel') }}
|
||||
<NButton size="small" quaternary @click="filesStore.closePreview()">
|
||||
<template #icon>
|
||||
<NIcon><CloseIcon /></NIcon>
|
||||
</template>
|
||||
{{ t('files.closePreview') }}
|
||||
</NButton>
|
||||
</div>
|
||||
<div class="preview-content">
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: 'Nutzung',
|
||||
channels: 'Kanale',
|
||||
terminal: 'Terminal',
|
||||
files: 'Dateien',
|
||||
settings: 'Einstellungen',
|
||||
connected: 'Verbunden',
|
||||
disconnected: 'Getrennt',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: 'Aktualisierung abgeschlossen, bitte Server neu starten',
|
||||
updateFailed: 'Aktualisierung fehlgeschlagen',
|
||||
logout: 'Abmelden',
|
||||
nodeVersionWarning: 'Node.js v{version} erkannt. Version 23+ wird fur volle Funktionalitat benotigt (SQLite, node-pty).',
|
||||
changelog: 'Anderungsprotokoll',
|
||||
noChangelog: 'Kein Anderungsprotokoll verfugbar',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// Anderungsprotokoll
|
||||
changelog: {
|
||||
new_0_4_4_1: 'Dateibrowser mit Multi-Backend-Unterstutzung hinzugefugt (local/Docker/SSH/Singularity)',
|
||||
new_0_4_4_2: 'Dateidownload aus Chat-Nachrichtenanhangen hinzugefugt',
|
||||
new_0_4_4_3: 'Live-Badge auf aktiven Chat-Sitzungen hinzugefugt',
|
||||
new_0_4_4_4: 'StepFun- und Nous-Portal-Provider-Unterstutzung hinzugefugt',
|
||||
new_0_4_4_5: 'Spezialzeichen-Suche verursacht 500-Fehler behoben',
|
||||
new_0_4_3_1: 'Benutzername/Passwort-Login neben Token-Authentifizierung hinzugefugt',
|
||||
new_0_4_3_2: 'Kontoeinstellungen fur Anmeldeinformationen hinzugefugt',
|
||||
new_0_4_3_3: 'Abmelden-Schaltflache in der Seitenleiste hinzugefugt',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: 'Eingebaute Provider-Erkennung und Modellabgleich behoben',
|
||||
new_0_4_1_1: 'Authentifizierungsumgehung und SPA-Bereitstellung behoben',
|
||||
},
|
||||
|
||||
// Dateien
|
||||
files: {
|
||||
title: 'Dateien',
|
||||
tree: 'Verzeichnisbaum',
|
||||
list: 'Dateiliste',
|
||||
breadcrumbRoot: 'Start',
|
||||
newFile: 'Neue Datei',
|
||||
newFolder: 'Neuer Ordner',
|
||||
upload: 'Hochladen',
|
||||
refresh: 'Aktualisieren',
|
||||
open: 'Offnen',
|
||||
edit: 'Bearbeiten',
|
||||
preview: 'Vorschau',
|
||||
download: 'Herunterladen',
|
||||
copyPath: 'Pfad kopieren',
|
||||
rename: 'Umbenennen',
|
||||
delete: 'Loschen',
|
||||
name: 'Name',
|
||||
size: 'Grosse',
|
||||
modified: 'Geandert',
|
||||
actions: 'Aktionen',
|
||||
emptyDir: 'Leeres Verzeichnis',
|
||||
loading: 'Wird geladen...',
|
||||
confirmDelete: 'Mochten Sie "{name}" wirklich loschen?',
|
||||
confirmDeleteDir: 'Mochten Sie das Verzeichnis "{name}" und seinen gesamten Inhalt wirklich loschen?',
|
||||
deleteFailed: 'Loschen fehlgeschlagen',
|
||||
deleted: 'Geloscht',
|
||||
renameTo: 'Umbenennen in',
|
||||
newFileName: 'Dateiname',
|
||||
newFolderName: 'Ordnername',
|
||||
created: 'Erstellt',
|
||||
createFailed: 'Erstellen fehlgeschlagen',
|
||||
renamed: 'Umbenannt',
|
||||
renameFailed: 'Umbenennen fehlgeschlagen',
|
||||
uploadSuccess: '{count} Datei(en) hochgeladen',
|
||||
uploadFailed: 'Hochladen fehlgeschlagen',
|
||||
saveFailed: 'Speichern fehlgeschlagen',
|
||||
saved: 'Gespeichert',
|
||||
unsavedChanges: 'Sie haben ungespeicherte Anderungen. Verwerfen?',
|
||||
pathCopied: 'Pfad kopiert',
|
||||
fileTooLarge: 'Datei zu gross (max. 10 MB)',
|
||||
permissionDenied: 'Geschutzte Datei kann nicht geandert werden',
|
||||
notFound: 'Datei oder Verzeichnis nicht gefunden',
|
||||
backendError: 'Dateioperation fehlgeschlagen',
|
||||
dragDropHint: 'Dateien hierher ziehen, um sie hochzuladen',
|
||||
closeEditor: 'Editor schliessen',
|
||||
closePreview: 'Schliessen',
|
||||
saveFile: 'Speichern',
|
||||
},
|
||||
|
||||
// Download
|
||||
download: {
|
||||
downloading: 'Wird heruntergeladen...',
|
||||
downloadFailed: 'Download fehlgeschlagen',
|
||||
fileNotFound: 'Datei nicht gefunden oder geloscht',
|
||||
fileTooLarge: 'Datei zu gross (Limit uberschritten)',
|
||||
backendError: 'Lesen der Datei fehlgeschlagen, Remote-Umgebung moglicherweise nicht verfugbar',
|
||||
backendTimeout: 'Zeituberschreitung beim Lesen der Datei',
|
||||
unsupportedBackend: 'Aktuelles Terminal-Backend unterstutzt keine Datei-Downloads',
|
||||
invalidPath: 'Ungultiger Dateipfad',
|
||||
download: 'Herunterladen',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -595,6 +595,7 @@ export default {
|
||||
backendError: 'File operation failed',
|
||||
dragDropHint: 'Drag files here to upload',
|
||||
closeEditor: 'Close Editor',
|
||||
closePreview: 'Close',
|
||||
saveFile: 'Save',
|
||||
},
|
||||
// Download
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: 'Uso',
|
||||
channels: 'Canales',
|
||||
terminal: 'Terminal',
|
||||
files: 'Archivos',
|
||||
settings: 'Configuracion',
|
||||
connected: 'Conectado',
|
||||
disconnected: 'Desconectado',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: 'Actualizacion completa, por favor reinicia el servidor',
|
||||
updateFailed: 'Error al actualizar',
|
||||
logout: 'Cerrar sesion',
|
||||
nodeVersionWarning: 'Node.js v{version} detectado. Se requiere la version 23+ para todas las funcionalidades (SQLite, node-pty).',
|
||||
changelog: 'Registro de cambios',
|
||||
noChangelog: 'No hay registro de cambios',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// Registro de cambios
|
||||
changelog: {
|
||||
new_0_4_4_1: 'Agregar explorador de archivos con soporte multi-backend (local/Docker/SSH/Singularity)',
|
||||
new_0_4_4_2: 'Agregar descarga de archivos desde archivos adjuntos del chat',
|
||||
new_0_4_4_3: 'Agregar indicador en vivo en sesiones de chat activas',
|
||||
new_0_4_4_4: 'Agregar soporte para proveedores StepFun y Nous Portal',
|
||||
new_0_4_4_5: 'Corregir error 500 al buscar con caracteres especiales',
|
||||
new_0_4_3_1: 'Agregar inicio de sesion con usuario/contrasena junto a autenticacion por token',
|
||||
new_0_4_3_2: 'Agregar configuracion de cuenta para gestionar credenciales',
|
||||
new_0_4_3_3: 'Agregar boton de cerrar sesion en la barra lateral',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: 'Corregir deteccion de proveedores integrados y coincidencia de modelos',
|
||||
new_0_4_1_1: 'Corregir bypass de autenticacion y servicio de archivos SPA',
|
||||
},
|
||||
|
||||
// Archivos
|
||||
files: {
|
||||
title: 'Archivos',
|
||||
tree: 'Arbol de directorios',
|
||||
list: 'Lista de archivos',
|
||||
breadcrumbRoot: 'Inicio',
|
||||
newFile: 'Nuevo archivo',
|
||||
newFolder: 'Nueva carpeta',
|
||||
upload: 'Subir',
|
||||
refresh: 'Actualizar',
|
||||
open: 'Abrir',
|
||||
edit: 'Editar',
|
||||
preview: 'Vista previa',
|
||||
download: 'Descargar',
|
||||
copyPath: 'Copiar ruta',
|
||||
rename: 'Renombrar',
|
||||
delete: 'Eliminar',
|
||||
name: 'Nombre',
|
||||
size: 'Tamano',
|
||||
modified: 'Modificado',
|
||||
actions: 'Acciones',
|
||||
emptyDir: 'Directorio vacio',
|
||||
loading: 'Cargando...',
|
||||
confirmDelete: '?Seguro que quiere eliminar "{name}"?',
|
||||
confirmDeleteDir: '?Seguro que quiere eliminar el directorio "{name}" y todo su contenido?',
|
||||
deleteFailed: 'Error al eliminar',
|
||||
deleted: 'Eliminado',
|
||||
renameTo: 'Renombrar a',
|
||||
newFileName: 'Nombre del archivo',
|
||||
newFolderName: 'Nombre de la carpeta',
|
||||
created: 'Creado',
|
||||
createFailed: 'Error al crear',
|
||||
renamed: 'Renombrado',
|
||||
renameFailed: 'Error al renombrar',
|
||||
uploadSuccess: '{count} archivo(s) subido(s)',
|
||||
uploadFailed: 'Error al subir',
|
||||
saveFailed: 'Error al guardar',
|
||||
saved: 'Guardado',
|
||||
unsavedChanges: 'Tiene cambios sin guardar. ?Descartar?',
|
||||
pathCopied: 'Ruta copiada',
|
||||
fileTooLarge: 'Archivo demasiado grande (max 10MB)',
|
||||
permissionDenied: 'No se puede modificar un archivo protegido',
|
||||
notFound: 'Archivo o directorio no encontrado',
|
||||
backendError: 'Error en la operacion de archivo',
|
||||
dragDropHint: 'Arrastra archivos aqui para subir',
|
||||
closeEditor: 'Cerrar editor',
|
||||
closePreview: 'Cerrar',
|
||||
saveFile: 'Guardar',
|
||||
},
|
||||
|
||||
// Descarga
|
||||
download: {
|
||||
downloading: 'Descargando...',
|
||||
downloadFailed: 'Error en la descarga',
|
||||
fileNotFound: 'Archivo no encontrado o eliminado',
|
||||
fileTooLarge: 'Archivo demasiado grande (excede el limite)',
|
||||
backendError: 'Error al leer el archivo, el entorno remoto puede no estar disponible',
|
||||
backendTimeout: 'Tiempo de lectura del archivo agotado',
|
||||
unsupportedBackend: 'El backend del terminal actual no admite la descarga de archivos',
|
||||
invalidPath: 'Ruta de archivo invalida',
|
||||
download: 'Descargar',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: 'Utilisation',
|
||||
channels: 'Canaux',
|
||||
terminal: 'Terminal',
|
||||
files: 'Fichiers',
|
||||
settings: 'Parametres',
|
||||
connected: 'Connecte',
|
||||
disconnected: 'Deconnecte',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: 'Mise a jour terminee, veuillez redemarrer le serveur',
|
||||
updateFailed: 'Echec de la mise a jour',
|
||||
logout: 'Deconnexion',
|
||||
nodeVersionWarning: 'Node.js v{version} detecte. La version 23+ est requise pour toutes les fonctionnalites (SQLite, node-pty).',
|
||||
changelog: 'Journal des modifications',
|
||||
noChangelog: 'Aucun journal disponible',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// Journal des modifications
|
||||
changelog: {
|
||||
new_0_4_4_1: 'Ajout du navigateur de fichiers avec support multi-backend (local/Docker/SSH/Singularity)',
|
||||
new_0_4_4_2: 'Ajout du telechargement de fichiers depuis les pieces jointes',
|
||||
new_0_4_4_3: 'Ajout du badge en direct sur les sessions actives',
|
||||
new_0_4_4_4: 'Ajout du support des fournisseurs StepFun et Nous Portal',
|
||||
new_0_4_4_5: 'Correction de l\'erreur 500 lors de la recherche avec caracteres speciaux',
|
||||
new_0_4_3_1: 'Ajouter la connexion par nom d\'utilisateur/mot de passe en plus du token',
|
||||
new_0_4_3_2: 'Ajouter les parametres de compte pour gerer les identifiants',
|
||||
new_0_4_3_3: 'Ajouter le bouton de deconnexion dans la barre laterale',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: 'Corriger la detection des fournisseurs integres et l\'appariement des modeles',
|
||||
new_0_4_1_1: 'Corriger le contournement d\'authentification et le service de fichiers SPA',
|
||||
},
|
||||
|
||||
// Fichiers
|
||||
files: {
|
||||
title: 'Fichiers',
|
||||
tree: 'Arborescence',
|
||||
list: 'Liste des fichiers',
|
||||
breadcrumbRoot: 'Accueil',
|
||||
newFile: 'Nouveau fichier',
|
||||
newFolder: 'Nouveau dossier',
|
||||
upload: 'Telecharger',
|
||||
refresh: 'Actualiser',
|
||||
open: 'Ouvrir',
|
||||
edit: 'Modifier',
|
||||
preview: 'Apercu',
|
||||
download: 'Telecharger',
|
||||
copyPath: 'Copier le chemin',
|
||||
rename: 'Renommer',
|
||||
delete: 'Supprimer',
|
||||
name: 'Nom',
|
||||
size: 'Taille',
|
||||
modified: 'Modifie',
|
||||
actions: 'Actions',
|
||||
emptyDir: 'Dossier vide',
|
||||
loading: 'Chargement...',
|
||||
confirmDelete: 'Voulez-vous vraiment supprimer "{name}" ?',
|
||||
confirmDeleteDir: 'Voulez-vous vraiment supprimer le dossier "{name}" et tout son contenu ?',
|
||||
deleteFailed: 'Echec de la suppression',
|
||||
deleted: 'Supprime',
|
||||
renameTo: 'Renommer en',
|
||||
newFileName: 'Nom du fichier',
|
||||
newFolderName: 'Nom du dossier',
|
||||
created: 'Cree',
|
||||
createFailed: 'Echec de la creation',
|
||||
renamed: 'Renomme',
|
||||
renameFailed: 'Echec du renommage',
|
||||
uploadSuccess: '{count} fichier(s) televerse(s)',
|
||||
uploadFailed: 'Echec du televersement',
|
||||
saveFailed: 'Echec de l\'enregistrement',
|
||||
saved: 'Enregistre',
|
||||
unsavedChanges: 'Vous avez des modifications non enregistrees. Annuler ?',
|
||||
pathCopied: 'Chemin copie',
|
||||
fileTooLarge: 'Fichier trop volumineux (max 10 Mo)',
|
||||
permissionDenied: 'Impossible de modifier un fichier protege',
|
||||
notFound: 'Fichier ou dossier introuvable',
|
||||
backendError: 'Echec de l\'operation sur le fichier',
|
||||
dragDropHint: 'Glissez des fichiers ici pour les televerser',
|
||||
closeEditor: 'Fermer l\'editeur',
|
||||
closePreview: 'Fermer',
|
||||
saveFile: 'Enregistrer',
|
||||
},
|
||||
|
||||
// Telechargement
|
||||
download: {
|
||||
downloading: 'Telechargement...',
|
||||
downloadFailed: 'Echec du telechargement',
|
||||
fileNotFound: 'Fichier introuvable ou supprime',
|
||||
fileTooLarge: 'Fichier trop volumineux (limite depassee)',
|
||||
backendError: 'Echec de la lecture du fichier, l\'environnement distant est peut-etre indisponible',
|
||||
backendTimeout: 'Delai de lecture du fichier depasse',
|
||||
unsupportedBackend: 'Le backend de terminal actuel ne prend pas en charge le telechargement de fichiers',
|
||||
invalidPath: 'Chemin de fichier invalide',
|
||||
download: 'Telecharger',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: '使用量',
|
||||
channels: 'チャンネル',
|
||||
terminal: 'ターミナル',
|
||||
files: 'ファイル',
|
||||
settings: '設定',
|
||||
connected: '接続済み',
|
||||
disconnected: '未接続',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: '更新が完了しました。サーバーを再起動してください',
|
||||
updateFailed: '更新に失敗しました',
|
||||
logout: 'ログアウト',
|
||||
nodeVersionWarning: 'Node.js v{version} が検出されました。全機能にはバージョン23+が必要です(SQLite、node-pty)。',
|
||||
changelog: '更新履歴',
|
||||
noChangelog: '更新履歴はありません',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// 更新履歴
|
||||
changelog: {
|
||||
new_0_4_4_1: 'ファイルブラウザを追加(local/Docker/SSH/Singularity対応)',
|
||||
new_0_4_4_2: 'チャットメッセージの添付ファイルダウンロードを追加',
|
||||
new_0_4_4_3: 'アクティブセッションにライブバッジを表示',
|
||||
new_0_4_4_4: 'StepFunとNous Portalプロバイダーに対応',
|
||||
new_0_4_4_5: '特殊文字検索で500エラーになる問題を修正',
|
||||
new_0_4_3_1: 'トークン認証に加えてユーザー名/パスワードログインを追加',
|
||||
new_0_4_3_2: '資格情報管理のためのアカウント設定を追加',
|
||||
new_0_4_3_3: 'サイドバーにログアウトボタンを追加',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: '組み込みプロバイダー検出とモデルマッチングを修正',
|
||||
new_0_4_1_1: '認証バイパスとSPAファイル配信を修正',
|
||||
},
|
||||
|
||||
// ファイル
|
||||
files: {
|
||||
title: 'ファイル',
|
||||
tree: 'ディレクトリツリー',
|
||||
list: 'ファイル一覧',
|
||||
breadcrumbRoot: 'ホーム',
|
||||
newFile: '新規ファイル',
|
||||
newFolder: '新規フォルダ',
|
||||
upload: 'アップロード',
|
||||
refresh: '更新',
|
||||
open: '開く',
|
||||
edit: '編集',
|
||||
preview: 'プレビュー',
|
||||
download: 'ダウンロード',
|
||||
copyPath: 'パスをコピー',
|
||||
rename: '名前の変更',
|
||||
delete: '削除',
|
||||
name: '名前',
|
||||
size: 'サイズ',
|
||||
modified: '更新日時',
|
||||
actions: '操作',
|
||||
emptyDir: '空のディレクトリ',
|
||||
loading: '読み込み中...',
|
||||
confirmDelete: '「{name}」を削除してもよろしいですか?',
|
||||
confirmDeleteDir: 'ディレクトリ「{name}」とそのすべての内容を削除してもよろしいですか?',
|
||||
deleteFailed: '削除に失敗しました',
|
||||
deleted: '削除しました',
|
||||
renameTo: '名前を変更',
|
||||
newFileName: 'ファイル名',
|
||||
newFolderName: 'フォルダ名',
|
||||
created: '作成しました',
|
||||
createFailed: '作成に失敗しました',
|
||||
renamed: '名前を変更しました',
|
||||
renameFailed: '名前の変更に失敗しました',
|
||||
uploadSuccess: '{count} 個のファイルをアップロードしました',
|
||||
uploadFailed: 'アップロードに失敗しました',
|
||||
saveFailed: '保存に失敗しました',
|
||||
saved: '保存しました',
|
||||
unsavedChanges: '未保存の変更があります。破棄しますか?',
|
||||
pathCopied: 'パスをコピーしました',
|
||||
fileTooLarge: 'ファイルが大きすぎます(最大10MB)',
|
||||
permissionDenied: '保護されたファイルは変更できません',
|
||||
notFound: 'ファイルまたはディレクトリが見つかりません',
|
||||
backendError: 'ファイル操作に失敗しました',
|
||||
dragDropHint: 'ここにファイルをドラッグしてアップロード',
|
||||
closeEditor: 'エディタを閉じる',
|
||||
closePreview: '閉じる',
|
||||
saveFile: '保存',
|
||||
},
|
||||
|
||||
// ダウンロード
|
||||
download: {
|
||||
downloading: 'ダウンロード中...',
|
||||
downloadFailed: 'ダウンロードに失敗しました',
|
||||
fileNotFound: 'ファイルが見つからないか削除されています',
|
||||
fileTooLarge: 'ファイルが大きすぎます(制限超過)',
|
||||
backendError: 'ファイルの読み取りに失敗しました。リモート環境が利用できない可能性があります',
|
||||
backendTimeout: 'ファイルの読み取りがタイムアウトしました',
|
||||
unsupportedBackend: '現在のターミナルバックエンドはファイルのダウンロードに対応していません',
|
||||
invalidPath: '無効なファイルパス',
|
||||
download: 'ダウンロード',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: '사용량',
|
||||
channels: '채널',
|
||||
terminal: '터미널',
|
||||
files: '파일',
|
||||
settings: '설정',
|
||||
connected: '연결됨',
|
||||
disconnected: '연결 끊김',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: '업데이트 완료, 서버를 재시작해 주세요',
|
||||
updateFailed: '업데이트 실패',
|
||||
logout: '로그아웃',
|
||||
nodeVersionWarning: 'Node.js v{version}이(가) 감지되었습니다. 전체 기능에는 버전 23+가 필요합니다(SQLite, node-pty).',
|
||||
changelog: '변경 이력',
|
||||
noChangelog: '변경 이력이 없습니다',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// 변경 이력
|
||||
changelog: {
|
||||
new_0_4_4_1: '파일 브라우저 추가 (local/Docker/SSH/Singularity 지원)',
|
||||
new_0_4_4_2: '채팅 메시지 첨부 파일 다운로드 추가',
|
||||
new_0_4_4_3: '활성 세션에 라이브 배지 표시',
|
||||
new_0_4_4_4: 'StepFun 및 Nous Portal 프로바이더 지원 추가',
|
||||
new_0_4_4_5: '특수문자 검색 시 500 에러 수정',
|
||||
new_0_4_3_1: '토큰 인증과 함께 사용자 이름/비밀번호 로그인 추가',
|
||||
new_0_4_3_2: '자격 증명 관리를 위한 계정 설정 추가',
|
||||
new_0_4_3_3: '사이드바에 로그아웃 버튼 추가',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: '내장 프로바이더 감지 및 모델 매칭 수정',
|
||||
new_0_4_1_1: '인증 우회 및 SPA 파일 서비스 수정',
|
||||
},
|
||||
|
||||
// 파일
|
||||
files: {
|
||||
title: '파일',
|
||||
tree: '디렉터리 트리',
|
||||
list: '파일 목록',
|
||||
breadcrumbRoot: '홈',
|
||||
newFile: '새 파일',
|
||||
newFolder: '새 폴더',
|
||||
upload: '업로드',
|
||||
refresh: '새로고침',
|
||||
open: '열기',
|
||||
edit: '편집',
|
||||
preview: '미리보기',
|
||||
download: '다운로드',
|
||||
copyPath: '경로 복사',
|
||||
rename: '이름 변경',
|
||||
delete: '삭제',
|
||||
name: '이름',
|
||||
size: '크기',
|
||||
modified: '수정일',
|
||||
actions: '작업',
|
||||
emptyDir: '빈 디렉터리',
|
||||
loading: '불러오는 중...',
|
||||
confirmDelete: '"{name}"을(를) 삭제하시겠습니까?',
|
||||
confirmDeleteDir: '디렉터리 "{name}"과 그 내부 항목을 모두 삭제하시겠습니까?',
|
||||
deleteFailed: '삭제 실패',
|
||||
deleted: '삭제됨',
|
||||
renameTo: '새 이름',
|
||||
newFileName: '파일 이름',
|
||||
newFolderName: '폴더 이름',
|
||||
created: '생성됨',
|
||||
createFailed: '생성 실패',
|
||||
renamed: '이름이 변경됨',
|
||||
renameFailed: '이름 변경 실패',
|
||||
uploadSuccess: '{count}개 파일이 업로드되었습니다',
|
||||
uploadFailed: '업로드 실패',
|
||||
saveFailed: '저장 실패',
|
||||
saved: '저장됨',
|
||||
unsavedChanges: '저장하지 않은 변경 사항이 있습니다. 취소하시겠습니까?',
|
||||
pathCopied: '경로가 복사되었습니다',
|
||||
fileTooLarge: '파일이 너무 큽니다 (최대 10MB)',
|
||||
permissionDenied: '보호된 파일은 수정할 수 없습니다',
|
||||
notFound: '파일 또는 디렉터리를 찾을 수 없습니다',
|
||||
backendError: '파일 작업 실패',
|
||||
dragDropHint: '여기로 파일을 드래그하여 업로드',
|
||||
closeEditor: '편집기 닫기',
|
||||
closePreview: '닫기',
|
||||
saveFile: '저장',
|
||||
},
|
||||
|
||||
// 다운로드
|
||||
download: {
|
||||
downloading: '다운로드 중...',
|
||||
downloadFailed: '다운로드 실패',
|
||||
fileNotFound: '파일을 찾을 수 없거나 삭제되었습니다',
|
||||
fileTooLarge: '파일이 너무 큽니다 (제한 초과)',
|
||||
backendError: '파일 읽기에 실패했습니다. 원격 환경이 사용 불가능할 수 있습니다',
|
||||
backendTimeout: '파일 읽기 시간 초과',
|
||||
unsupportedBackend: '현재 터미널 백엔드는 파일 다운로드를 지원하지 않습니다',
|
||||
invalidPath: '잘못된 파일 경로',
|
||||
download: '다운로드',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
usage: 'Uso',
|
||||
channels: 'Canais',
|
||||
terminal: 'Terminal',
|
||||
files: 'Arquivos',
|
||||
settings: 'Configuracoes',
|
||||
connected: 'Conectado',
|
||||
disconnected: 'Desconectado',
|
||||
@@ -84,7 +85,6 @@ export default {
|
||||
updateSuccess: 'Atualizacao concluida, por favor reinicie o servidor',
|
||||
updateFailed: 'Falha na atualizacao',
|
||||
logout: 'Sair',
|
||||
nodeVersionWarning: 'Node.js v{version} detectado. A versao 23+ e necessaria para todas as funcionalidades (SQLite, node-pty).',
|
||||
changelog: 'Registro de alteracoes',
|
||||
noChangelog: 'Nenhum registro disponivel',
|
||||
},
|
||||
@@ -511,11 +511,6 @@ export default {
|
||||
|
||||
// Registro de alteracoes
|
||||
changelog: {
|
||||
new_0_4_4_1: 'Adicionar navegador de arquivos com suporte multi-backend (local/Docker/SSH/Singularity)',
|
||||
new_0_4_4_2: 'Adicionar download de arquivos dos anexos de chat',
|
||||
new_0_4_4_3: 'Adicionar indicador ao vivo nas sessoes de chat ativas',
|
||||
new_0_4_4_4: 'Adicionar suporte para provedores StepFun e Nous Portal',
|
||||
new_0_4_4_5: 'Corrigir erro 500 ao pesquisar com caracteres especiais',
|
||||
new_0_4_3_1: 'Adicionar login por usuario/senha junto com autenticacao por token',
|
||||
new_0_4_3_2: 'Adicionar configuracoes de conta para gerenciar credenciais',
|
||||
new_0_4_3_3: 'Adicionar botao de sair na barra lateral',
|
||||
@@ -527,4 +522,67 @@ export default {
|
||||
new_0_4_2_5: 'Corrigir deteccao de provedores integrados e combinacao de modelos',
|
||||
new_0_4_1_1: 'Corrigir bypass de autenticacao e servico de arquivos SPA',
|
||||
},
|
||||
|
||||
// Arquivos
|
||||
files: {
|
||||
title: 'Arquivos',
|
||||
tree: 'Arvore de diretorios',
|
||||
list: 'Lista de arquivos',
|
||||
breadcrumbRoot: 'Inicio',
|
||||
newFile: 'Novo arquivo',
|
||||
newFolder: 'Nova pasta',
|
||||
upload: 'Enviar',
|
||||
refresh: 'Atualizar',
|
||||
open: 'Abrir',
|
||||
edit: 'Editar',
|
||||
preview: 'Visualizar',
|
||||
download: 'Baixar',
|
||||
copyPath: 'Copiar caminho',
|
||||
rename: 'Renomear',
|
||||
delete: 'Excluir',
|
||||
name: 'Nome',
|
||||
size: 'Tamanho',
|
||||
modified: 'Modificado',
|
||||
actions: 'Acoes',
|
||||
emptyDir: 'Diretorio vazio',
|
||||
loading: 'Carregando...',
|
||||
confirmDelete: 'Tem certeza de que deseja excluir "{name}"?',
|
||||
confirmDeleteDir: 'Tem certeza de que deseja excluir o diretorio "{name}" e todo o seu conteudo?',
|
||||
deleteFailed: 'Falha ao excluir',
|
||||
deleted: 'Excluido',
|
||||
renameTo: 'Renomear para',
|
||||
newFileName: 'Nome do arquivo',
|
||||
newFolderName: 'Nome da pasta',
|
||||
created: 'Criado',
|
||||
createFailed: 'Falha ao criar',
|
||||
renamed: 'Renomeado',
|
||||
renameFailed: 'Falha ao renomear',
|
||||
uploadSuccess: '{count} arquivo(s) enviado(s)',
|
||||
uploadFailed: 'Falha ao enviar',
|
||||
saveFailed: 'Falha ao salvar',
|
||||
saved: 'Salvo',
|
||||
unsavedChanges: 'Voce tem alteracoes nao salvas. Descartar?',
|
||||
pathCopied: 'Caminho copiado',
|
||||
fileTooLarge: 'Arquivo muito grande (max 10MB)',
|
||||
permissionDenied: 'Nao e possivel modificar arquivo protegido',
|
||||
notFound: 'Arquivo ou diretorio nao encontrado',
|
||||
backendError: 'Falha na operacao de arquivo',
|
||||
dragDropHint: 'Arraste arquivos aqui para enviar',
|
||||
closeEditor: 'Fechar editor',
|
||||
closePreview: 'Fechar',
|
||||
saveFile: 'Salvar',
|
||||
},
|
||||
|
||||
// Download
|
||||
download: {
|
||||
downloading: 'Baixando...',
|
||||
downloadFailed: 'Falha no download',
|
||||
fileNotFound: 'Arquivo nao encontrado ou excluido',
|
||||
fileTooLarge: 'Arquivo muito grande (limite excedido)',
|
||||
backendError: 'Falha ao ler o arquivo, o ambiente remoto pode estar indisponivel',
|
||||
backendTimeout: 'Tempo esgotado para ler o arquivo',
|
||||
unsupportedBackend: 'O backend de terminal atual nao suporta download de arquivos',
|
||||
invalidPath: 'Caminho de arquivo invalido',
|
||||
download: 'Baixar',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -598,6 +598,7 @@ export default {
|
||||
backendError: '文件操作失败',
|
||||
dragDropHint: '拖拽文件到此处上传',
|
||||
closeEditor: '关闭编辑器',
|
||||
closePreview: '关闭',
|
||||
saveFile: '保存',
|
||||
},
|
||||
// 下载
|
||||
|
||||
@@ -63,6 +63,15 @@ export function isTextFile(name: string): boolean {
|
||||
return !binaryExts.has(getFileExt(name))
|
||||
}
|
||||
|
||||
// Returns true if `targetPath` is the same as `changedPath` or lives inside it
|
||||
// when `changedIsDir` is true. Used to invalidate preview/editor state when
|
||||
// the underlying file is deleted or renamed.
|
||||
function isAffected(targetPath: string, changedPath: string, changedIsDir: boolean): boolean {
|
||||
if (targetPath === changedPath) return true
|
||||
if (changedIsDir && targetPath.startsWith(changedPath + '/')) return true
|
||||
return false
|
||||
}
|
||||
|
||||
export const useFilesStore = defineStore('files', () => {
|
||||
const currentPath = ref('')
|
||||
const entries = ref<FileEntry[]>([])
|
||||
@@ -104,6 +113,12 @@ export const useFilesStore = defineStore('files', () => {
|
||||
})
|
||||
|
||||
async function fetchEntries(path?: string) {
|
||||
if (path !== undefined && path !== currentPath.value) {
|
||||
// Switching directory invalidates the current preview; close it so the
|
||||
// file list becomes visible again. The editor has its own dirty-check
|
||||
// (see hasUnsavedChanges), so we leave editingFile alone here.
|
||||
previewFile.value = null
|
||||
}
|
||||
if (path !== undefined) currentPath.value = path
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -167,6 +182,12 @@ export const useFilesStore = defineStore('files', () => {
|
||||
|
||||
async function deleteEntry(entry: FileEntry) {
|
||||
await filesApi.deleteFile(entry.path, entry.isDir)
|
||||
if (previewFile.value && isAffected(previewFile.value.path, entry.path, entry.isDir)) {
|
||||
previewFile.value = null
|
||||
}
|
||||
if (editingFile.value && isAffected(editingFile.value.path, entry.path, entry.isDir)) {
|
||||
editingFile.value = null
|
||||
}
|
||||
await fetchEntries()
|
||||
}
|
||||
|
||||
@@ -174,6 +195,12 @@ export const useFilesStore = defineStore('files', () => {
|
||||
const parentPath = entry.path.includes('/') ? entry.path.slice(0, entry.path.lastIndexOf('/')) : ''
|
||||
const newPath = parentPath ? `${parentPath}/${newName}` : newName
|
||||
await filesApi.renameFile(entry.path, newPath)
|
||||
if (previewFile.value && isAffected(previewFile.value.path, entry.path, entry.isDir)) {
|
||||
previewFile.value = null
|
||||
}
|
||||
if (editingFile.value && isAffected(editingFile.value.path, entry.path, entry.isDir)) {
|
||||
editingFile.value = null
|
||||
}
|
||||
await fetchEntries()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user