diff --git a/.gitignore b/.gitignore index fdd8268..dc9c2d4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ logs/ config/ test/ build/ +dist/ image_cache/ download/ text_cache/ diff --git a/LeonPan.spec b/LeonPan.spec new file mode 100644 index 0000000..6ffe5d9 --- /dev/null +++ b/LeonPan.spec @@ -0,0 +1,39 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[('D:\\Projects\\Python\\LeonPan PC\\_internal', '_internal'), ('D:\\Projects\\Python\\LeonPan PC\\logo.png', 'logo.png'), ('D:\\Projects\\Python\\LeonPan PC\\welcome_video.py', 'welcome_video.py'), ('D:\\Projects\\Python\\LeonPan PC\\app\\resource', 'app/resource')], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='LeonPan', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['D:\\Projects\\Python\\LeonPan PC\\logo.png'], +) diff --git a/LeonPan_Console.spec b/LeonPan_Console.spec new file mode 100644 index 0000000..a3eab02 --- /dev/null +++ b/LeonPan_Console.spec @@ -0,0 +1,39 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[('D:\\Projects\\Python\\LeonPan PC\\_internal', '_internal'), ('D:\\Projects\\Python\\LeonPan PC\\logo.png', 'logo.png'), ('D:\\Projects\\Python\\LeonPan PC\\welcome_video.py', 'welcome_video.py'), ('D:\\Projects\\Python\\LeonPan PC\\app\\resource', 'app/resource')], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='LeonPan_Console', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['D:\\Projects\\Python\\LeonPan PC\\logo.png'], +) diff --git a/Miaostars-0.0.2.txt b/Miaostars-0.0.2.txt deleted file mode 100644 index 8dc7d8b..0000000 --- a/Miaostars-0.0.2.txt +++ /dev/null @@ -1,101 +0,0 @@ - 1. 09-88-4069 - 2. 72-33-8317 - 3. 93-54-4878 - 4. 93-86-1869 - 5. 14-04-1203 - 6. 84-00-2929 - 7. 04-82-6399 - 8. 79-11-1229 - 9. 11-06-1474 - 10. 07-72-4607 - 11. 56-87-7920 - 12. 53-25-2426 - 13. 67-39-6157 - 14. 63-39-2233 - 15. 17-96-4158 - 16. 17-62-6178 - 17. 15-37-0827 - 18. 59-52-8112 - 19. 03-21-4560 - 20. 55-11-5109 - 21. 67-99-2556 - 22. 91-20-2424 - 23. 22-43-2052 - 24. 77-64-5252 - 25. 59-35-8073 - 26. 55-31-5493 - 27. 32-76-3175 - 28. 84-91-2685 - 29. 87-12-2589 - 30. 80-19-6183 - 31. 01-53-7563 - 32. 48-27-6989 - 33. 11-13-8688 - 34. 09-54-6589 - 35. 07-23-1493 - 36. 59-42-4357 - 37. 35-19-0434 - 38. 14-36-4400 - 39. 02-87-5750 - 40. 70-48-9729 - 41. 72-69-7715 - 42. 46-99-7577 - 43. 38-14-9272 - 44. 40-42-7732 - 45. 96-91-2081 - 46. 23-68-6080 - 47. 91-39-5462 - 48. 19-92-2732 - 49. 72-23-5102 - 50. 27-88-0690 - 51. 15-45-5394 - 52. 05-99-9553 - 53. 99-05-6922 - 54. 01-89-7062 - 55. 48-19-1418 - 56. 55-07-8466 - 57. 96-22-4957 - 58. 53-82-8031 - 59. 18-11-2941 - 60. 98-93-7633 - 61. 63-94-6925 - 62. 12-74-5129 - 63. 34-17-2602 - 64. 03-04-7664 - 65. 90-38-9969 - 66. 24-89-8276 - 67. 97-89-9536 - 68. 80-32-7705 - 69. 72-32-7795 - 70. 12-80-4790 - 71. 73-84-9545 - 72. 91-03-5053 - 73. 52-40-1281 - 74. 74-75-2213 - 75. 17-50-3710 - 76. 60-36-2783 - 77. 98-57-1091 - 78. 83-59-9231 - 79. 29-48-8192 - 80. 12-91-0807 - 81. 74-25-2849 - 82. 64-82-0610 - 83. 10-23-2036 - 84. 91-63-7704 - 85. 28-68-1631 - 86. 47-23-2650 - 87. 38-04-5634 - 88. 96-08-5695 - 89. 03-56-8427 - 90. 39-51-0578 - 91. 44-87-6122 - 92. 64-20-1925 - 93. 93-14-6077 - 94. 98-76-4163 - 95. 94-60-5635 - 96. 52-43-0973 - 97. 33-16-2106 - 98. 12-66-8985 - 99. 24-57-6007 - 100. 40-23-4384 -<##-##-####> diff --git a/app/resource/images/bg0.png b/_internal/backgrounds/bg0.png similarity index 100% rename from app/resource/images/bg0.png rename to _internal/backgrounds/bg0.png diff --git a/app/resource/images/bg1.png b/_internal/backgrounds/bg1.png similarity index 100% rename from app/resource/images/bg1.png rename to _internal/backgrounds/bg1.png diff --git a/app/resource/images/bg2.png b/_internal/backgrounds/bg2.png similarity index 100% rename from app/resource/images/bg2.png rename to _internal/backgrounds/bg2.png diff --git a/app/resource/images/bg3.png b/_internal/backgrounds/bg3.png similarity index 100% rename from app/resource/images/bg3.png rename to _internal/backgrounds/bg3.png diff --git a/app/resource/images/bg4.png b/_internal/backgrounds/bg4.png similarity index 100% rename from app/resource/images/bg4.png rename to _internal/backgrounds/bg4.png diff --git a/app/resource/images/bg5.png b/_internal/backgrounds/bg5.png similarity index 100% rename from app/resource/images/bg5.png rename to _internal/backgrounds/bg5.png diff --git a/app/resource/images/bg6.png b/_internal/backgrounds/bg6.png similarity index 100% rename from app/resource/images/bg6.png rename to _internal/backgrounds/bg6.png diff --git a/_internal/editor_main/index.html b/_internal/editor_main/index.html index 5b46257..837971b 100644 --- a/_internal/editor_main/index.html +++ b/_internal/editor_main/index.html @@ -68,7 +68,7 @@ let tempFilePath = ''; // 初始化Monaco Editor - require(['vs/editor/editor.main'], function () { + require(['vs/editor/editor.main'], function() { // 从URL参数获取内容和语言 const urlParams = new URLSearchParams(window.location.search); const contentParam = urlParams.get('content'); @@ -82,6 +82,7 @@ initialContent = Base.decode(contentParam); } catch (e) { console.error('解码内容失败:', e); + initialContent = contentParam; // 如果解码失败,使用原始内容 } } @@ -89,28 +90,33 @@ editor = monaco.editor.create(document.getElementById('container'), { value: initialContent, language: languageParam, - theme: 'vs-dark', automaticLayout: true, minimap: { enabled: true }, - scrollBeyondLastLine: false, fontSize: 14, - wordWrap: 'on', + fontFamily: 'Consolas, "Courier New", monospace', + scrollBeyondLastLine: false, lineNumbers: 'on', - readOnly: false, - fontFamily: 'Consolas, "Microsoft YaHei", monospace' + roundedSelection: true, + scrollbar: { + useShadows: false, + verticalScrollbarSize: 10, + horizontalScrollbarSize: 10 + } }); - // 添加内容变化监听器 - editor.onDidChangeModelContent(function() { - // 内容变化处理 - }); - - // 窗口大小改变时重新布局 - window.onresize = function () { + // 监听窗口大小变化 + window.addEventListener('resize', function() { if (editor) { editor.layout(); } - }; + }); + + // 延迟执行,确保编辑器已初始化 + setTimeout(function() { + if (editor) { + editor.focus(); + } + }, 100); }); // 暴露获取内容的方法给QWebEngineView调用 @@ -151,10 +157,7 @@ language: editor && editor.getModel() ? editor.getModel().getLanguageId() : 'text' }; - // 方法1: 保存到localStorage - localStorage.setItem('leonpan_editor_content', JSON.stringify(saveData)); - - // 方法2: 直接向本地服务器发送POST请求(主要方式) + // 直接向本地服务器发送POST请求(主要方式) try { // 获取当前端口号 const currentPort = window.location.port; @@ -167,53 +170,38 @@ xhr.onload = function() { if (xhr.status === 200) { console.log('服务器接收保存成功'); + alert('内容已成功保存并返回应用程序'); + + // 尝试使用自定义协议返回应用程序 + try { + window.location.href = 'leonpan:save-success'; + } catch (e) { + console.error('无法通过协议返回应用程序:', e); + } + + // 尝试关闭窗口(某些浏览器可能阻止此操作) + setTimeout(function() { + window.close(); + }, 500); + } else { + console.error('服务器返回错误状态:', xhr.status); + alert('保存失败,请重试'); } }; xhr.onerror = function() { console.error('向服务器发送保存请求失败'); + alert('保存请求发送失败,请检查网络连接'); }; xhr.send(JSON.stringify(saveData)); } catch (e) { console.error('发送保存请求时出错:', e); + alert('保存过程中发生错误: ' + e.message); } - // 方法3: 创建一个下载链接作为备用方式 - const blob = new Blob([JSON.stringify(saveData)], {type: 'application/json'}); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - - // 设置文件名和下载路径 - a.download = 'editor_content.json'; - - // 如果提供了临时文件路径,尝试使用该路径 - if (tempFilePath) { - // 对于Windows路径,需要进行特殊处理 - if (navigator.platform.indexOf('Win') !== -1) { - // 在Windows中,我们不能直接设置文件系统路径,但可以提示用户 - console.log('建议保存路径:', tempFilePath); - } - } - - a.href = url; - - // 显示成功提示 - alert('内容已成功保存!应用程序将自动检测到您的更改。'); - - // 自动触发下载(作为备用机制) - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(url); - - // 尝试通过协议处理程序返回应用程序 - try { - // 使用自定义协议打开应用程序 - window.location.href = 'leonpan:save-success'; - } catch (e) { - console.error('无法返回应用程序:', e); - } + // 备用: 保存到localStorage,以便应用程序在POST失败时可以尝试读取 + localStorage.setItem('leonpan_editor_content', JSON.stringify(saveData)); } // 获取系统临时目录路径(用于显示给用户) @@ -228,56 +216,28 @@ } } - // 从URL参数获取初始化数据 + // 初始化函数(根据URL参数) function initFromUrl() { const urlParams = new URLSearchParams(window.location.search); + const contentParam = urlParams.get('content'); + const languageParam = urlParams.get('language'); - // 获取并设置内容 - const encodedContent = urlParams.get('content'); - if (encodedContent) { + if (contentParam) { try { - const decodedContent = Base.decode(encodedContent); + const decodedContent = Base.decode(contentParam); setEditorContent(decodedContent); } catch (e) { - console.error('解码内容失败:', e); + console.error('从URL初始化内容失败:', e); } } - // 获取并设置语言 - const language = urlParams.get('language') || 'text'; - setEditorLanguage(language); - - // 保存文件ID到本地存储 - const fileId = urlParams.get('fileId'); - if (fileId) { - localStorage.setItem('currentFileId', fileId); + if (languageParam) { + setEditorLanguage(languageParam); } - - // 获取临时文件路径 - tempFilePath = urlParams.get('temp_file') || ''; } - // 初始化时从URL参数加载数据 + // 页面加载完成后执行初始化 window.addEventListener('load', function() { - // 从localStorage中加载可能保存的内容 - const savedContent = localStorage.getItem('leonpan_editor_content'); - if (savedContent) { - try { - const parsed = JSON.parse(savedContent); - if (parsed.saved && parsed.content) { - // 延迟执行,确保编辑器已初始化 - setTimeout(() => { - if (editor) { - const decodedContent = Base.decode(parsed.content); - editor.setValue(decodedContent); - } - }, 1000); - } - } catch (e) { - console.error('解析保存的内容失败:', e); - } - } - // 延迟执行,确保编辑器已初始化 setTimeout(initFromUrl, 1000); }); diff --git a/app/resource/lang/en.json b/_internal/lang/en.json similarity index 100% rename from app/resource/lang/en.json rename to _internal/lang/en.json diff --git a/app/resource/lang/zh.json b/_internal/lang/zh.json similarity index 100% rename from app/resource/lang/zh.json rename to _internal/lang/zh.json diff --git a/app/core/utils/morelang.py b/app/core/utils/morelang.py index 074689d..5f546ee 100644 --- a/app/core/utils/morelang.py +++ b/app/core/utils/morelang.py @@ -12,7 +12,7 @@ _current_language = "zh" # 翻译词典 _translations = {} # 语言文件目录 -_LANG_DIR = Path("app/resource/lang").absolute() +_LANG_DIR = Path("_internal/lang").absolute() # print(Path("app/resource/lang").absolute()) diff --git a/app/view/widgets/preview_box.py b/app/view/widgets/preview_box.py index 999feb0..1351e44 100644 --- a/app/view/widgets/preview_box.py +++ b/app/view/widgets/preview_box.py @@ -268,6 +268,12 @@ class PreviewTextBox(MessageBoxBase): self._id = _id self.isChanged = False + # 初始化关键变量 + self.isContentSaved = False # 明确初始化保存状态 + self.httpd = None # 服务器实例引用 + self.server_thread = None # 服务器线程引用 + self.tempFilePath = None # 临时文件路径 + # 设置编辑器HTML文件路径 - 修正为项目根目录的_internal文件夹 project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) self.editor_index = os.path.join(project_root, "_internal/editor_main/index.html") @@ -348,7 +354,10 @@ class PreviewTextBox(MessageBoxBase): ) # 隐藏进度条 self.saveProgressBar.hide() - QTimer.singleShot(700, self.accept) + + # 直接调用accept()关闭窗口,不再使用定时器延迟 + # 确保窗口立即关闭并返回成功结果 + self.accept() def _errorSave(self, msg): logger.error(f"文本文件保存失败,文件ID: {self._id}, 错误: {msg}") @@ -432,14 +441,9 @@ class PreviewTextBox(MessageBoxBase): def setTextContent(self, content): """设置文本内容并在外部浏览器中打开""" - # 检查内容是否已保存,如果已保存则不允许再次编辑 - if hasattr(self, 'isContentSaved') and self.isContentSaved: - logger.warning("内容已保存,不允许再次编辑") - self.placeholderLabel.setText('''
该内容已经保存,不再允许编辑
-内容已从浏览器同步到应用并已保存
-该内容将不再允许编辑
+重要提示:完成编辑后,请点击浏览器中的"保存并返回"按钮
+应用正在自动检测...