agent/static/file_manager/editor.js
2025-11-14 16:44:12 +08:00

136 lines
4.4 KiB
JavaScript

(() => {
const API_BASE = '/api/gui/files';
const params = new URLSearchParams(window.location.search);
const path = params.get('path');
const editorArea = document.getElementById('editorArea');
const filePathEl = document.getElementById('filePath');
const statusInfo = document.getElementById('statusInfo');
const saveBtn = document.getElementById('btnSave');
const downloadBtn = document.getElementById('btnDownload');
const backBtn = document.getElementById('btnBack');
const fontIncreaseBtn = document.getElementById('btnIncreaseFont');
const fontDecreaseBtn = document.getElementById('btnDecreaseFont');
let originalContent = '';
let dirty = false;
let fontSize = 14;
if (!path) {
editorArea.value = '缺少 path 参数,无法加载文件。';
editorArea.disabled = true;
saveBtn.disabled = true;
downloadBtn.disabled = true;
statusInfo.textContent = '缺少路径';
return;
}
filePathEl.textContent = path;
function setDirty(value) {
dirty = value;
statusInfo.textContent = dirty ? '有未保存的更改' : '已保存';
saveBtn.disabled = !dirty;
}
async function request(url, options = {}) {
const response = await fetch(url, options);
const data = await response.json().catch(() => ({}));
if (!response.ok || data.success === false) {
const message = data.error || data.message || `请求失败 (${response.status})`;
throw new Error(message);
}
return data;
}
async function loadFile() {
statusInfo.textContent = '加载中...';
try {
const result = await request(`${API_BASE}/text?path=${encodeURIComponent(path)}`);
originalContent = result.content || '';
editorArea.value = originalContent;
setDirty(false);
statusInfo.textContent = `最后修改时间:${result.modified_at}`;
} catch (err) {
editorArea.value = `文件加载失败:${err.message}`;
editorArea.disabled = true;
saveBtn.disabled = true;
statusInfo.textContent = '无法加载文件';
}
}
async function saveFile() {
statusInfo.textContent = '保存中...';
try {
await request(`${API_BASE}/text`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path, content: editorArea.value }),
});
originalContent = editorArea.value;
setDirty(false);
statusInfo.textContent = '已保存';
} catch (err) {
statusInfo.textContent = `保存失败:${err.message}`;
}
}
editorArea.addEventListener('input', () => {
if (editorArea.disabled) return;
setDirty(editorArea.value !== originalContent);
});
saveBtn.addEventListener('click', () => {
if (!dirty) return;
saveFile();
});
downloadBtn.addEventListener('click', () => {
window.open(`${API_BASE}/download?path=${encodeURIComponent(path)}`, '_blank');
});
const getParentDirectory = () => {
const segments = path.split('/').filter(Boolean);
if (segments.length <= 1) {
return '';
}
segments.pop();
return segments.join('/');
};
const navigateToManager = () => {
const parentDir = getParentDirectory();
const target = parentDir ? `/file-manager?path=${encodeURIComponent(parentDir)}` : '/file-manager';
window.location.href = target;
};
backBtn.addEventListener('click', () => {
if (dirty) {
const confirmLeave = window.confirm('有未保存的更改,确认要离开吗?');
if (!confirmLeave) return;
}
navigateToManager();
});
fontIncreaseBtn.addEventListener('click', () => {
fontSize = Math.min(fontSize + 1, 28);
editorArea.style.fontSize = `${fontSize}px`;
});
fontDecreaseBtn.addEventListener('click', () => {
fontSize = Math.max(fontSize - 1, 10);
editorArea.style.fontSize = `${fontSize}px`;
});
window.addEventListener('beforeunload', (event) => {
if (!dirty) return;
event.preventDefault();
event.returnValue = '';
});
loadFile().catch((err) => {
console.error(err);
statusInfo.textContent = err.message;
});
})();