286 lines
9.1 KiB
HTML
286 lines
9.1 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html>
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>文件编辑器</title>
|
|||
|
|
<style type="text/css">
|
|||
|
|
html, body {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 0;
|
|||
|
|
overflow: hidden;
|
|||
|
|
font-family: 'Microsoft YaHei', Arial, sans-serif;
|
|||
|
|
}
|
|||
|
|
#header {
|
|||
|
|
background-color: #333;
|
|||
|
|
color: white;
|
|||
|
|
padding: 10px 20px;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
#saveBtn {
|
|||
|
|
background-color: #4CAF50;
|
|||
|
|
color: white;
|
|||
|
|
border: none;
|
|||
|
|
padding: 8px 16px;
|
|||
|
|
text-align: center;
|
|||
|
|
text-decoration: none;
|
|||
|
|
display: inline-block;
|
|||
|
|
font-size: 16px;
|
|||
|
|
margin: 4px 2px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
}
|
|||
|
|
#container {
|
|||
|
|
width: 100%;
|
|||
|
|
height: calc(100% - 50px);
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
|
|||
|
|
<div id="header">
|
|||
|
|
<h3>文件编辑器</h3>
|
|||
|
|
<button id="saveBtn" onclick="saveAndReturn()">保存并返回</button>
|
|||
|
|
</div>
|
|||
|
|
<div id="container"></div>
|
|||
|
|
|
|||
|
|
<!-- 引入Monaco Editor的loader.js -->
|
|||
|
|
<script src="../editor/min/vs/loader.js"></script>
|
|||
|
|
<script>
|
|||
|
|
// 简单的Base64编解码函数
|
|||
|
|
const Base = {
|
|||
|
|
encode: function(str) {
|
|||
|
|
return btoa(unescape(encodeURIComponent(str)));
|
|||
|
|
},
|
|||
|
|
decode: function(str) {
|
|||
|
|
return decodeURIComponent(escape(atob(str)));
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 配置Monaco Editor路径
|
|||
|
|
require.config({paths: {'vs': '../editor/min/vs'}});
|
|||
|
|
|
|||
|
|
let editor;
|
|||
|
|
let tempFilePath = '';
|
|||
|
|
|
|||
|
|
// 初始化Monaco Editor
|
|||
|
|
require(['vs/editor/editor.main'], function () {
|
|||
|
|
// 从URL参数获取内容和语言
|
|||
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|||
|
|
const contentParam = urlParams.get('content');
|
|||
|
|
const languageParam = urlParams.get('language') || 'text';
|
|||
|
|
tempFilePath = urlParams.get('temp_file') || '';
|
|||
|
|
|
|||
|
|
// 解码内容
|
|||
|
|
let initialContent = '';
|
|||
|
|
if (contentParam) {
|
|||
|
|
try {
|
|||
|
|
initialContent = Base.decode(contentParam);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('解码内容失败:', e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建编辑器实例
|
|||
|
|
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',
|
|||
|
|
lineNumbers: 'on',
|
|||
|
|
readOnly: false,
|
|||
|
|
fontFamily: 'Consolas, "Microsoft YaHei", monospace'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 添加内容变化监听器
|
|||
|
|
editor.onDidChangeModelContent(function() {
|
|||
|
|
// 内容变化处理
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 窗口大小改变时重新布局
|
|||
|
|
window.onresize = function () {
|
|||
|
|
if (editor) {
|
|||
|
|
editor.layout();
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 暴露获取内容的方法给QWebEngineView调用
|
|||
|
|
function getEditorContent() {
|
|||
|
|
return editor ? editor.getValue() : '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 暴露设置内容的方法
|
|||
|
|
function setEditorContent(content) {
|
|||
|
|
if (editor) {
|
|||
|
|
editor.setValue(content);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 暴露设置语言的方法
|
|||
|
|
function setEditorLanguage(language) {
|
|||
|
|
if (editor && monaco) {
|
|||
|
|
const model = editor.getModel();
|
|||
|
|
if (model) {
|
|||
|
|
monaco.editor.setModelLanguage(model, language);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 保存并返回应用程序
|
|||
|
|
function saveAndReturn() {
|
|||
|
|
// 获取编辑器内容
|
|||
|
|
const content = getEditorContent();
|
|||
|
|
|
|||
|
|
// 对内容进行Base64编码
|
|||
|
|
const encodedContent = Base.encode(content);
|
|||
|
|
|
|||
|
|
// 创建保存数据对象
|
|||
|
|
const saveData = {
|
|||
|
|
content: encodedContent,
|
|||
|
|
saved: true,
|
|||
|
|
timestamp: new Date().getTime(),
|
|||
|
|
language: editor && editor.getModel() ? editor.getModel().getLanguageId() : 'text'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 方法1: 保存到localStorage
|
|||
|
|
localStorage.setItem('leonpan_editor_content', JSON.stringify(saveData));
|
|||
|
|
|
|||
|
|
// 方法2: 直接向本地服务器发送POST请求(主要方式)
|
|||
|
|
try {
|
|||
|
|
// 获取当前端口号
|
|||
|
|
const currentPort = window.location.port;
|
|||
|
|
const xhr = new XMLHttpRequest();
|
|||
|
|
|
|||
|
|
// 向本地服务器发送保存请求
|
|||
|
|
xhr.open('POST', `http://127.0.0.1:${currentPort}/save`, true);
|
|||
|
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
|||
|
|
|
|||
|
|
xhr.onload = function() {
|
|||
|
|
if (xhr.status === 200) {
|
|||
|
|
console.log('服务器接收保存成功');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
xhr.onerror = function() {
|
|||
|
|
console.error('向服务器发送保存请求失败');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
xhr.send(JSON.stringify(saveData));
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('发送保存请求时出错:', e);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 方法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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取系统临时目录路径(用于显示给用户)
|
|||
|
|
function getSystemTempDir() {
|
|||
|
|
// 根据不同操作系统返回临时目录路径格式
|
|||
|
|
if (navigator.platform.indexOf('Win') !== -1) {
|
|||
|
|
return '%TEMP%';
|
|||
|
|
} else if (navigator.platform.indexOf('Mac') !== -1) {
|
|||
|
|
return '/tmp';
|
|||
|
|
} else {
|
|||
|
|
return '/tmp';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从URL参数获取初始化数据
|
|||
|
|
function initFromUrl() {
|
|||
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|||
|
|
|
|||
|
|
// 获取并设置内容
|
|||
|
|
const encodedContent = urlParams.get('content');
|
|||
|
|
if (encodedContent) {
|
|||
|
|
try {
|
|||
|
|
const decodedContent = Base.decode(encodedContent);
|
|||
|
|
setEditorContent(decodedContent);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('解码内容失败:', e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取并设置语言
|
|||
|
|
const language = urlParams.get('language') || 'text';
|
|||
|
|
setEditorLanguage(language);
|
|||
|
|
|
|||
|
|
// 保存文件ID到本地存储
|
|||
|
|
const fileId = urlParams.get('fileId');
|
|||
|
|
if (fileId) {
|
|||
|
|
localStorage.setItem('currentFileId', fileId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取临时文件路径
|
|||
|
|
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);
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|