You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.7 KiB

// 文本控制器
export class TextController {
constructor() {
this.init();
}
init() {
this.setupTextEditor();
}
setupTextEditor() {
const editor = document.getElementById('textEditor');
// 监听文本变化
editor.addEventListener('input', () => {
this.onTextChange();
});
// 监听粘贴事件
editor.addEventListener('paste', (e) => {
this.handlePaste(e);
});
// 监听拖拽文件
editor.addEventListener('dragover', (e) => {
e.preventDefault();
editor.classList.add('drag-over');
});
editor.addEventListener('dragleave', () => {
editor.classList.remove('drag-over');
});
editor.addEventListener('drop', (e) => {
e.preventDefault();
editor.classList.remove('drag-over');
this.handleFileDrop(e);
});
// 监听窗口大小变化,保持文本格式
window.addEventListener('resize', () => {
this.preserveTextFormat();
});
}
handleFileImport(event) {
const file = event.target.files[0];
if (!file) return;
if (!file.name.toLowerCase().endsWith('.txt')) {
alert('请选择.txt格式的文本文件');
return;
}
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result;
this.setText(text);
};
reader.readAsText(file, 'utf-8');
}
handleFileDrop(event) {
const files = event.dataTransfer.files;
if (files.length > 0) {
const file = files[0];
if (file.name.toLowerCase().endsWith('.txt')) {
const reader = new FileReader();
reader.onload = (e) => {
const text = e.target.result;
this.setText(text);
};
reader.readAsText(file, 'utf-8');
} else {
alert('请拖拽.txt格式的文本文件');
}
}
}
handlePaste(event) {
// 处理粘贴的纯文本,保持换行格式
event.preventDefault();
const text = (event.clipboardData || window.clipboardData).getData('text');
// 保持原有的换行符
const formattedText = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
range.deleteContents();
// 创建文本节点并插入,保持换行
const lines = formattedText.split('\n');
for (let i = 0; i < lines.length; i++) {
if (i > 0) {
range.insertNode(document.createElement('br'));
}
if (lines[i]) {
range.insertNode(document.createTextNode(lines[i]));
}
}
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
this.onTextChange();
}
setText(text) {
const editor = document.getElementById('textEditor');
// 保持换行格式
const formattedText = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
const lines = formattedText.split('\n');
editor.innerHTML = '';
for (let i = 0; i < lines.length; i++) {
if (i > 0) {
editor.appendChild(document.createElement('br'));
}
if (lines[i]) {
editor.appendChild(document.createTextNode(lines[i]));
}
}
this.onTextChange();
}
getText() {
const editor = document.getElementById('textEditor');
return editor.innerText || editor.textContent;
}
preserveTextFormat() {
// 在窗口大小变化时保持文本格式
const editor = document.getElementById('textEditor');
const currentText = this.getText();
// 重新设置文本以保持格式
setTimeout(() => {
this.setText(currentText);
}, 100);
}
onTextChange() {
// 更新滚动条
if (window.app && window.app.updateScrollbar) {
setTimeout(() => window.app.updateScrollbar(), 100);
}
// 如果启用了自动计算时长,重新计算
if (window.scrollController && window.scrollController.autoCalculateDuration) {
window.scrollController.calculateOptimalSpeed();
}
// 保存到本地存储
this.saveToLocalStorage();
}
saveToLocalStorage() {
const text = this.getText();
localStorage.setItem('teleprompter-text', text);
}
loadFromLocalStorage() {
const savedText = localStorage.getItem('teleprompter-text');
if (savedText) {
this.setText(savedText);
return true;
}
return false;
}
exportText() {
const text = this.getText();
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `teleprompter-text-${new Date().toISOString().slice(0, 10)}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
clearText() {
if (confirm('确定要清空所有文本吗?')) {
this.setText('');
}
}
insertAtCursor(text) {
const editor = document.getElementById('textEditor');
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(text));
range.collapse(false);
} else {
editor.appendChild(document.createTextNode(text));
}
this.onTextChange();
}
getWordCount() {
const text = this.getText();
return {
characters: text.length,
charactersNoSpaces: text.replace(/\s/g, '').length,
words: text.trim().split(/\s+/).filter(word => word.length > 0).length,
lines: text.split('\n').length,
paragraphs: text.split(/\n\s*\n/).filter(para => para.trim().length > 0).length
};
}
}