Refactor settings store to rename proModel to proThinking and update related logic; enhance CSS for energy efficiency and reduced motion preferences; improve i18n translations for better clarity and consistency; modify proBlock utility functions for clearer instruction handling; streamline Vite configuration by removing unnecessary Univer.js dependencies.

This commit is contained in:
“ydy0615”
2026-05-31 16:38:10 +08:00
parent 3a1fd1c5d7
commit b82c6d392d
42 changed files with 3909 additions and 2509 deletions
+198 -51
View File
@@ -82,6 +82,8 @@ export const translations = {
cancel: 'Cancel',
imgTooLarge: 'Image too large',
docTooLarge: 'Document too large, AI disabled',
exportDisabledHint: 'DOCX/PDF export is temporarily unavailable.',
disableAI: 'Disable AI',
initialMarkdown: '# Welcome to LLM-IN-TEXT\n\nAn instant LLM system\n\nStart your creative work below...',
view: 'View',
editor: 'Editor',
@@ -89,34 +91,33 @@ export const translations = {
docsManagement: 'Document Management',
docsEmptyDesc: 'Document management interface is under development...',
files: 'Files',
noFiles: '暂无文件',
newFile: '新建文件',
newFolder: '新建文件夹',
noFiles: 'No files yet',
newFile: 'New File',
newFolder: 'New Folder',
untitledFile: 'untitled.md',
untitledFolder: '新建文件夹',
rename: '重命名',
delete: '删除',
copy: '复制',
cut: '剪切',
paste: '粘贴',
confirmDelete: '确认删除',
confirmDeleteDesc: '确定要删除',
confirmDeleteFolderDesc: '此操作将删除文件夹内的所有内容。',
confirmDeleteFileDesc: '此操作不可撤销。',
cancel: '取消',
rootDir: '根目录',
expandSidebar: '展开侧边栏',
collapseSidebar: '收起侧边栏',
fileLimitReached: '文件数量已达上限',
folderLimitReached: '文件夹数量已达上限',
fileSizeLimit: '文件大小不能超过 50MB',
storageError: '存储空间不足',
selectFileToView: '选择一个文件以查看内容',
folderContains: '包含',
items: '个项目',
unsupportedPreview: '暂不支持预览此文件类型',
fileNamePlaceholder: '文件名.md',
folderNamePlaceholder: '文件夹名'
untitledFolder: 'New Folder',
rename: 'Rename',
delete: 'Delete',
copy: 'Copy',
cut: 'Cut',
paste: 'Paste',
confirmDelete: 'Confirm Delete',
confirmDeleteDesc: 'Are you sure to delete',
confirmDeleteFolderDesc: 'This will delete all contents in the folder.',
confirmDeleteFileDesc: 'This action cannot be undone.',
rootDir: 'Root',
expandSidebar: 'Expand Sidebar',
collapseSidebar: 'Collapse Sidebar',
fileLimitReached: 'Maximum number of files reached',
folderLimitReached: 'Maximum number of folders reached',
fileSizeLimit: 'File size cannot exceed 50MB',
storageError: 'Insufficient storage space',
selectFileToView: 'Select a file to view content',
folderContains: 'contains',
items: 'items',
unsupportedPreview: 'This file type is not supported for preview',
fileNamePlaceholder: 'filename.md',
folderNamePlaceholder: 'Folder name'
},
zh: {
settings: '设置',
@@ -201,6 +202,7 @@ export const translations = {
cancel: '取消',
imgTooLarge: '图片过大',
docTooLarge: '文档过大,AI已禁用',
exportDisabledHint: 'DOCX/PDF 导出暂不可用。',
initialMarkdown: '# 欢迎使用 LLM-IN-TEXT\n\n即时可用的 LLM 系统\n\n在下方开始创作吧...',
view: '视图',
editor: '编辑器',
@@ -260,6 +262,12 @@ export const translations = {
mediumDesc: '提案前に文脈を簡単に分析',
highDesc: '深く段階的に分析(遅いが最高品質)',
debounceTime: 'デバウンス時間',
proModeThinking: 'PRO 思考中',
proMode: 'PRO モード',
proModel: 'PRO モデル',
proModelPlaceholder: '例: qwen3:32b',
proModelDesc: 'PRO モードのみで使用されるオプションの強力なモデル名。',
proModelEmptyHint: '空白のままにするとバックエンドのデフォルト PRO モデルが使用されます。',
privacyPreferences: 'プライバシーと設定',
privacyMode: 'プライバシーモード',
privacyDesc: 'AIにIPアドレスと設定を送信しない',
@@ -267,21 +275,48 @@ export const translations = {
auto: '自動検出',
currency: '通貨',
about: '私たちについて',
template: 'テンプレート',
presetTemplates: 'プリセットテンプレート',
customTemplates: 'カスタムテンプレート',
newTemplate: '新しいテンプレート',
previewTemplate: 'プレビュー',
applyTemplate: '適用',
copyAsTemplate: 'カスタムテンプレートとしてコピー',
editTemplate: '編集',
saveTemplate: '保存',
templateName: 'テンプレート名',
templateContent: '内容',
templateNamePlaceholder: '例: 議事録',
templateContentPlaceholder: 'テンプレート内容を入力...',
noTemplates: 'カスタムテンプレートはありません',
templateNameRequired: 'テンプレート名を入力してください',
templateContentRequired: '内容を入力してください',
templateNameDuplicate: 'テンプレート名は既に存在します',
templateDeleteConfirm: 'このテンプレートを削除しますか?',
templateSaved: '保存しました',
templateUpdated: '更新しました',
templateDeleted: '削除しました',
importMd: 'Markdownをインポート',
exportMd: 'Markdownをエクスポート',
exportDocx: 'DOCXをエクスポート',
exportPdf: 'PDFをエクスポート',
upload: 'アップロード',
uploadImg: '画像をアップロード',
uploadFile: 'Upload File',
uploadFileTypeWarning: 'Unsupported file type. Supported: doc/docx/ppt/pptx/pdf/zip, images, txt/json.',
uploadMdTypeWarning: 'Only Markdown (.md) files and image files are supported.',
uploadFileError: 'File upload failed.',
uploadConvertError: 'File conversion failed.',
uploadBatchLimit: 'Maximum 10 files at once',
uploadSizeLimit: 'File exceeds 50MB limit',
uploading: 'Uploading files...',
enableAI: 'AIを有効化',
uploadFile: 'ファイルをアップロード',
uploadDoc: 'ドキュメントをアップロード',
exportDisabledHint: 'DOCX/PDFのエクスポートは一時的に利用できません。',
uploadDocTypeWarning: 'txt、json、toml、yaml、docx、pptx、pdf形式のみサポートされています。',
uploadDocSizeWarning: 'ファイルサイズは10MBを超えることはできません。',
uploadDocInBlockWarning: '既存のドキュメントブロック内に新しいドキュメントを挿入することはできません。',
uploadDocError: 'ドキュメントの変換に失敗しました:',
uploadFileTypeWarning: 'サポートされていないファイルタイプです。doc/docx/ppt/pptx/pdf/zip、画像、txt/jsonをサポートしています。',
uploadMdTypeWarning: 'Markdown(.md)ファイルと画像ファイルのみサポートされています。',
uploadFileError: 'アップロードに失敗しました。',
uploadConvertError: '変換に失敗しました。',
uploadBatchLimit: '一度にアップロードできるのは10ファイルまでです。',
uploadSizeLimit: '50MBの制限を超えています。',
uploading: 'アップロード中...',
enableAI: 'AIを有効化',
disableAI: 'AIを無効化',
insertUrl: 'URLから画像を挿入',
insert: '挿入',
@@ -347,6 +382,13 @@ export const translations = {
mediumDesc: '제안 전 문맥 간단 분석',
highDesc: '심층 단계별 분석 (가장 느리지만 최고 품질)',
debounceTime: '디바운스 시간',
proModeThinking: 'PRO 생각 중',
proMode: 'PRO 모드',
proModel: 'PRO 모델',
proModelPlaceholder: '예: qwen3:32b',
proModelDesc: 'PRO 모드에서만 사용되는 선택적 강력한 모델 이름.',
proModelEmptyHint: '비워두면 백엔드 기본 PRO 모델을 사용합니다.',
privacyPreferences: '개인정보 및 환경설정',
privacyMode: '개인정보 모드',
privacyDesc: 'AI에 IP 주소 및 설정 전송 안 함',
@@ -354,17 +396,48 @@ export const translations = {
auto: '자동 감지',
currency: '통화',
about: '회사 소개',
template: '템플릿',
presetTemplates: '사전 정의된 템플릿',
customTemplates: '사용자 정의 템플릿',
newTemplate: '새 템플릿',
previewTemplate: '미리보기',
applyTemplate: '적용',
copyAsTemplate: '사용자 정의 템플릿으로 복사',
editTemplate: '편집',
saveTemplate: '저장',
templateName: '템플릿 이름',
templateContent: '내용',
templateNamePlaceholder: '예: 회의록',
templateContentPlaceholder: '템플릿 내용을 입력...',
noTemplates: '사용자 정의 템플릿이 없습니다',
templateNameRequired: '템플릿 이름을 입력하세요',
templateContentRequired: '내용을 입력하세요',
templateNameDuplicate: '템플릿 이름이 이미 존재합니다',
templateDeleteConfirm: '이 템플릿을 삭제하시겠습니까?',
templateSaved: '저장되었습니다',
templateUpdated: '업데이트되었습니다',
templateDeleted: '삭제되었습니다',
importMd: 'Markdown 가져오기',
exportMd: 'Markdown 내보내기',
exportDocx: 'DOCX 내보내기',
exportPdf: 'PDF 내보내기',
upload: '업로드',
uploadImg: '이미지 업로드',
uploadFile: 'Upload File',
uploadFileTypeWarning: 'Unsupported file type. Supported: doc/docx/ppt/pptx/pdf/zip, images, txt/json.',
uploadMdTypeWarning: 'Only Markdown (.md) files and image files are supported.',
uploadFileError: 'File upload failed.',
uploadConvertError: 'File conversion failed.',
uploadFile: '파일 업로드',
exportDisabledHint: 'DOCX/PDF 내보내기는 일시적으로 사용할 수 없습니다.',
uploadDoc: '문서 업로드',
uploadDocTypeWarning: 'txt, json, toml, yaml, docx, pptx, pdf 형식만 지원됩니다.',
uploadDocSizeWarning: '파일 크기는 10MB를 초과할 수 없습니다.',
uploadDocInBlockWarning: '기존 문서 블록 내에 새 문서를 삽입할 수 없습니다.',
uploadDocError: '문서 변환 실패:',
uploadFileTypeWarning: '지원되지 않는 파일 유형입니다. doc/docx/ppt/pptx/pdf/zip, 이미지, txt/json을 지원합니다.',
uploadMdTypeWarning: 'Markdown(.md) 파일과 이미지 파일만 지원됩니다.',
uploadFileError: '업로드 실패',
uploadConvertError: '변환 실패',
uploadBatchLimit: '한 번에 최대 10개 파일까지 업로드할 수 있습니다.',
uploadSizeLimit: '50MB 제한을 초과합니다.',
uploading: '업로드 중...',
enableAI: 'AI 활성화',
disableAI: 'AI 비활성화',
insertUrl: 'URL로 이미지 삽입',
@@ -431,6 +504,13 @@ export const translations = {
mediumDesc: 'Kurze Analyse vor Vorschlag',
highDesc: 'Tiefe schrittweise Analyse (Langsam, aber höchste Qualität)',
debounceTime: 'Entprellzeit',
proModeThinking: 'PRO denkt nach',
proMode: 'PRO-Modus',
proModel: 'PRO-Modell',
proModelPlaceholder: 'z.B. qwen3:32b',
proModelDesc: 'Optional staerker Modellname, der nur im PRO-Modus verwendet wird.',
proModelEmptyHint: 'Leer lassen, um das Standard-PRO-Modell des Backends zu verwenden.',
privacyPreferences: 'Datenschutz & Einstellungen',
privacyMode: 'Datenschutzmodus',
privacyDesc: 'Sende keine IP und Einstellungen an KI',
@@ -438,17 +518,47 @@ export const translations = {
auto: 'Automatisch',
currency: 'Währung',
about: 'Über uns',
template: 'Vorlage',
presetTemplates: 'Vorgabe-Vorlagen',
customTemplates: 'Benutzerdefinierte Vorlagen',
newTemplate: 'Neue Vorlage',
previewTemplate: 'Vorschau',
applyTemplate: 'Anwenden',
copyAsTemplate: 'Als benutzerdefinierte Vorlage kopieren',
editTemplate: 'Bearbeiten',
saveTemplate: 'Speichern',
templateName: 'Vorlagenname',
templateContent: 'Inhalt',
templateNamePlaceholder: 'z.B. Protokoll',
templateContentPlaceholder: 'Vorlageninhalt eingeben...',
noTemplates: 'Keine benutzerdefinierten Vorlagen',
templateNameRequired: 'Bitte Vorlagennamen eingeben',
templateContentRequired: 'Bitte Inhalt eingeben',
templateNameDuplicate: 'Vorlagenname existiert bereits',
templateDeleteConfirm: 'Diese Vorlage löschen?',
templateSaved: 'Gespeichert',
templateUpdated: 'Aktualisiert',
templateDeleted: 'Gelöscht',
importMd: 'Markdown importieren',
exportMd: 'Markdown exportieren',
exportDocx: 'DOCX exportieren',
exportPdf: 'PDF exportieren',
upload: 'Hochladen',
uploadImg: 'Bild hochladen',
uploadFile: 'Upload File',
uploadFileTypeWarning: 'Unsupported file type. Supported: doc/docx/ppt/pptx/pdf/zip, images, txt/json.',
uploadMdTypeWarning: 'Only Markdown (.md) files and image files are supported.',
uploadFileError: 'File upload failed.',
uploadConvertError: 'File conversion failed.',
uploadFile: 'Datei hochladen',
uploadDoc: 'Dokument hochladen',
exportDisabledHint: 'DOCX/PDF-Export ist vorübergehend nicht verfügbar.',
uploadDocTypeWarning: 'Nur txt, json, toml, yaml, docx, pptx, pdf Formate werden unterstützt.',
uploadDocSizeWarning: 'Dateigröße darf 10MB nicht überschreiten.',
uploadDocInBlockWarning: 'Kann kein Dokument innerhalb eines bestehenden Dokuments einfügen.',
uploadDocError: 'Dokumentkonversion fehlgeschlagen:',
uploadFileTypeWarning: 'Nicht unterstützter Dateityp. Unterstützt: doc/docx/ppt/pptx/pdf/zip, Bilder, txt/json.',
uploadMdTypeWarning: 'Nur Markdown(.md) und Bilddateien werden unterstützt.',
uploadFileError: 'Hochladen fehlgeschlagen',
uploadConvertError: 'Konversion fehlgeschlagen',
uploadBatchLimit: 'Maximal 10 Dateien auf einmal.',
uploadSizeLimit: 'Datei überschreitet das Limit von 50MB.',
uploading: 'Wird hochgeladen...',
enableAI: 'KI aktivieren',
disableAI: 'KI deaktivieren',
insertUrl: 'Bild per URL einfügen',
@@ -515,6 +625,13 @@ export const translations = {
mediumDesc: 'Analyse brève avant suggestion',
highDesc: 'Analyse approfondie étape par étape (Le plus lent)',
debounceTime: 'Temps de rebond',
proModeThinking: 'PRO en réflexion',
proMode: 'Mode PRO',
proModel: 'Modèle PRO',
proModelPlaceholder: 'ex: qwen3:32b',
proModelDesc: 'Nom de modèle plus puissant utilisé uniquement par le mode PRO.',
proModelEmptyHint: 'Laissez vide pour utiliser le modèle PRO par défaut du backend.',
privacyPreferences: 'Confidentialité et préférences',
privacyMode: 'Mode confidentialité',
privacyDesc: 'Ne pas envoyer IP et préférences à l\'IA',
@@ -522,17 +639,47 @@ export const translations = {
auto: 'Détection auto',
currency: 'Devise',
about: 'À propos de nous',
template: 'Modèle',
presetTemplates: 'Modèles prédéfinis',
customTemplates: 'Modèles personnalisés',
newTemplate: 'Nouveau modèle',
previewTemplate: 'Aperçu',
applyTemplate: 'Appliquer',
copyAsTemplate: 'Copier comme modèle personnalisé',
editTemplate: 'Modifier',
saveTemplate: 'Enregistrer',
templateName: 'Nom du modèle',
templateContent: 'Contenu',
templateNamePlaceholder: 'ex: Compte-rendu',
templateContentPlaceholder: 'Entrez le contenu du modèle...',
noTemplates: 'Aucun modèle personnalisé',
templateNameRequired: 'Veuillez entrer un nom de modèle',
templateContentRequired: 'Veuillez entrer le contenu',
templateNameDuplicate: 'Le nom du modèle existe déjà',
templateDeleteConfirm: 'Supprimer ce modèle ?',
templateSaved: 'Enregistré',
templateUpdated: 'Mis à jour',
templateDeleted: 'Supprimé',
importMd: 'Importer Markdown',
exportMd: 'Exporter Markdown',
exportDocx: 'Exporter DOCX',
exportPdf: 'Exporter PDF',
upload: 'Télécharger',
uploadImg: 'Télécharger image',
uploadFile: 'Upload File',
uploadFileTypeWarning: 'Unsupported file type. Supported: doc/docx/ppt/pptx/pdf/zip, images, txt/json.',
uploadMdTypeWarning: 'Only Markdown (.md) files and image files are supported.',
uploadFileError: 'File upload failed.',
uploadConvertError: 'File conversion failed.',
uploadFile: 'Importer un fichier',
uploadDoc: 'Télécharger document',
exportDisabledHint: 'L\'export DOCX/PDF est temporairement indisponible.',
uploadDocTypeWarning: 'Seuls les formats txt, json, toml, yaml, docx, pptx, pdf sont pris en charge.',
uploadDocSizeWarning: 'La taille du fichier ne peut pas dépasser 10 Mo.',
uploadDocInBlockWarning: 'Impossible d\'insérer un document à l\'intérieur d\'un bloc existant.',
uploadDocError: 'Échec de la conversion du document :',
uploadFileTypeWarning: 'Type de fichier non pris en charge. Supporté : doc/docx/ppt/pptx/pdf/zip, images, txt/json.',
uploadMdTypeWarning: 'Seuls les fichiers Markdown(.md) et images sont pris en charge.',
uploadFileError: 'Échec du téléchargement',
uploadConvertError: 'Échec de la conversion',
uploadBatchLimit: 'Maximum 10 fichiers à la fois.',
uploadSizeLimit: 'Fichier dépasse la limite de 50 Mo.',
uploading: 'Téléchargement en cours...',
enableAI: 'Activer IA',
disableAI: 'Désactiver IA',
insertUrl: 'Insérer image via URL',
+14 -14
View File
@@ -1,9 +1,9 @@
export const PRO_BLOCK_NODE_TYPE = 'pro_block'
export const PRO_TRIGGER_TEXT = '[PRO]'
export const PRO_DISPLAY_LABEL = 'PRO模式思考'
export const PRO_DISPLAY_LABEL = 'PRO 模式'
const PRO_PENDING_PREFIX = '[Pro][{'
const PRO_PENDING_SUFFIX = '}]'
const PRO_INSTRUCTION_PREFIX = '[PRO]{'
const PRO_INSTRUCTION_SUFFIX = '}'
const PRO_TRIGGER_RE = /^\[pro\]$/i
function normalizeMarkdownText(value = '') {
@@ -41,10 +41,10 @@ export function unescapeProBlockContent(value = '') {
return result
}
export function serializeProBlockSyntax(content = '') {
const normalized = normalizeMarkdownText(content)
export function serializeProBlockSyntax(instruction = '') {
const normalized = normalizeMarkdownText(instruction).trim()
if (!normalized) return PRO_TRIGGER_TEXT
return `${PRO_PENDING_PREFIX}${escapeProBlockContent(normalized)}${PRO_PENDING_SUFFIX}`
return `${PRO_INSTRUCTION_PREFIX}${escapeProBlockContent(normalized)}${PRO_INSTRUCTION_SUFFIX}`
}
export function parseProBlockSyntax(value = '') {
@@ -53,20 +53,20 @@ export function parseProBlockSyntax(value = '') {
if (PRO_TRIGGER_RE.test(text)) {
return {
content: '',
autoStart: true,
instruction: '',
autoStart: false,
}
}
const prefix = text.slice(0, PRO_PENDING_PREFIX.length)
if (prefix.toLowerCase() === PRO_PENDING_PREFIX.toLowerCase() && text.endsWith(PRO_PENDING_SUFFIX)) {
const prefix = text.slice(0, PRO_INSTRUCTION_PREFIX.length)
if (prefix.toLowerCase() === PRO_INSTRUCTION_PREFIX.toLowerCase() && text.endsWith(PRO_INSTRUCTION_SUFFIX)) {
return {
content: unescapeProBlockContent(
text.slice(PRO_PENDING_PREFIX.length, text.length - PRO_PENDING_SUFFIX.length)
),
instruction: unescapeProBlockContent(
text.slice(PRO_INSTRUCTION_PREFIX.length, text.length - PRO_INSTRUCTION_SUFFIX.length)
).trim(),
autoStart: false,
}
}
return null
}
}