林名赫 3 months ago
commit cb209da04e

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 KiB

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

@ -411,7 +411,7 @@
<!-- 用户信息区域 -->
<div class="p-4 border-t border-gray-700 flex items-center justify-between">
<div class="flex items-center gap-3">
<img src=".\tubiao.png" alt="用户头像" class="w-8 h-8 rounded-full"> <!-- 替换绝对路径 -->
<img src=".\touxiang.png" alt="用户头像" class="w-8 h-8 rounded-full"> <!-- 替换绝对路径 -->
<div>
<div class="text-sm font-medium" id="user-name">昵称</div>
<div class="text-xs text-text-muted" id="user-grade-major">年级 | 专业</div>
@ -432,23 +432,6 @@
<div class="bg-white p-4 border-b border-gray-200 flex items-center justify-between">
<h1 class="text-xl font-semibold">笔记管理</h1>
<div class="flex items-center gap-3">
<div class="relative mr-3">
<select id="categoryFilter" class="input-field pl-3 pr-8 w-48 border border-gray-300 rounded-md py-2 focus:outline-none focus:ring-2 focus:ring-primary/50 appearance-none bg-white">
<!-- 选项将通过JS动态生成 -->
</select>
<i class="fa fa-chevron-down absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none"></i>
</div>
<div class="relative">
<input
type="text"
id="noteSearch"
placeholder="搜索笔记..."
class="input-field pl-9 w-64 border border-gray-300 rounded-md py-2 px-3 focus:outline-none focus:ring-2 focus:ring-primary/50"
>
</div>
<button class="btn-action btn-primary bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors" id="newNoteBtn">
<i class="fa fa-plus mr-1"></i> 新建笔记
</button>
<button class="btn-action btn-secondary border border-gray-300 px-4 py-2 rounded-md hover:bg-gray-100 transition-colors" id="importNoteBtn">
<i class="fa fa-upload mr-1"></i> 导入
</button>
@ -459,17 +442,9 @@
<div class="p-6 border-b border-gray-200 bg-white">
<h2 class="text-lg font-semibold mb-4">已上传文件</h2>
<div id="documents-container" class="border rounded-lg p-4 bg-gray-50">
<!-- 文件列表将通过JS动态生成 -->
</div>
</div>
<!-- 笔记列表区域(删除了"我的笔记"标题) -->
<div class="p-6 flex-1">
<!-- 删除了原来的 <h2 class="text-lg font-semibold mb-4">我的笔记</h2> -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" id="notes-container">
<!-- 笔记卡片将通过JS动态生成 -->
</div>
</div>
</div>
@ -484,7 +459,7 @@
<!-- 系统消息示例 -->
<div class="max-w-[80%]">
<div class="flex items-center gap-2 mb-1">
<img src=".\tubiao.png" alt="AI" class="w-6 h-6 rounded-full">
<img src=".\touxiang.png" alt="AI" class="w-6 h-6 rounded-full">
<span class="text-sm font-medium text-gray-700">知记助手--KnowNo</span>
</div>
<div class="bg-gray-100 p-3 rounded-lg rounded-tl-none">
@ -613,224 +588,6 @@
</div>
</div>
<!-- 新建/编辑笔记模态框 -->
<div id="newNoteModal" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50 hidden transition-opacity duration-300">
<div class="w-full max-w-2xl bg-white rounded-xl p-8 shadow-lg transform transition-transform duration-300 scale-95">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-semibold text-dark" id="noteModalTitle">新建笔记</h2>
<button id="closeNewNoteModal" class="text-gray-400 hover:text-gray-600">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<form id="newNoteForm" class="space-y-5">
<input type="hidden" id="noteId"> <!-- 用于编辑模式存储笔记ID -->
<!-- 笔记标题 -->
<div>
<label for="noteTitle" class="block text-sm font-medium text-gray-700 mb-1">笔记标题</label>
<input
type="text"
id="noteTitle"
class="login-input"
placeholder="请输入笔记标题"
required
>
<p id="noteTitleError" class="text-red-500 text-xs mt-1 hidden">请输入笔记标题</p>
</div>
<!-- 笔记分类(修正后) -->
<div>
<label for="noteCategory" class="block text-sm font-medium text-gray-700 mb-1">笔记分类</label>
<input
type="text"
id="noteCategory"
class="login-input"
placeholder="请输入笔记分类(例如:高等数学、计算机网络)"
>
<p id="noteCategoryError" class="text-red-500 text-xs mt-1 hidden">请输入笔记分类</p>
</div>
<!-- 笔记内容(富文本编辑器) -->
<div>
<label for="noteContent" class="block text-sm font-medium text-gray-700 mb-1">笔记内容</label>
<div class="border border-gray-200 rounded-md mb-2 overflow-hidden">
<!-- 富文本工具栏 -->
<div class="flex items-center gap-1 p-2 border-b border-gray-200 bg-gray-50 flex-wrap">
<button type="button" class="toolbar-btn" data-command="bold" title="加粗 (Ctrl+B)">
<i class="fa fa-bold"></i>
</button>
<button type="button" class="toolbar-btn" data-command="italic" title="斜体 (Ctrl+I)">
<i class="fa fa-italic"></i>
</button>
<button type="button" class="toolbar-btn" data-command="underline" title="下划线 (Ctrl+U)">
<i class="fa fa-underline"></i>
</button>
<span class="h-4 w-px bg-gray-300 mx-1"></span>
<button type="button" class="toolbar-btn" data-command="insertUnorderedList" title="无序列表">
<i class="fa fa-list-ul"></i>
</button>
<button type="button" class="toolbar-btn" data-command="insertOrderedList" title="有序列表">
<i class="fa fa-list-ol"></i>
</button>
<button type="button" class="toolbar-btn" data-command="outdent" title="减少缩进">
<i class="fa fa-outdent"></i>
</button>
<button type="button" class="toolbar-btn" data-command="indent" title="增加缩进">
<i class="fa fa-indent"></i>
</button>
<span class="h-4 w-px bg-gray-300 mx-1"></span>
<button type="button" class="toolbar-btn" data-command="justifyLeft" title="左对齐">
<i class="fa fa-align-left"></i>
</button>
<button type="button" class="toolbar-btn" data-command="justifyCenter" title="居中对齐">
<i class="fa fa-align-center"></i>
</button>
<button type="button" class="toolbar-btn" data-command="justifyRight" title="右对齐">
<i class="fa fa-align-right"></i>
</button>
<span class="h-4 w-px bg-gray-300 mx-1"></span>
<button type="button" class="toolbar-btn" id="insertImageBtn" title="插入图片">
<i class="fa fa-image"></i>
</button>
<button type="button" class="toolbar-btn" title="插入公式">
<i class="fa fa-superscript"></i>
</button>
<button type="button" class="toolbar-btn" data-command="createLink" title="插入链接">
<i class="fa fa-link"></i>
</button>
<button type="button" class="toolbar-btn" data-command="unlink" title="移除链接">
<i class="fa fa-unlink"></i>
</button>
</div>
<!-- 富文本编辑区域 -->
<div
id="noteContent"
class="note-editor min-h-[300px]"
contenteditable="true"
placeholder="请输入笔记内容..."
></div>
</div>
<p id="noteContentError" class="text-red-500 text-xs mt-1 hidden">请输入笔记内容</p>
</div>
<!-- 笔记封面 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">笔记封面</label>
<div class="flex items-center gap-3">
<div class="w-20 h-20 bg-gray-100 rounded-md flex items-center justify-center border border-dashed border-gray-300">
<img id="noteCoverPreview" src="" alt="封面预览" class="w-full h-full object-cover hidden">
<i class="fa fa-picture-o text-gray-400" id="coverPlaceholder"></i>
</div>
<div>
<label for="noteCover" class="btn-action btn-secondary cursor-pointer inline-flex items-center">
<i class="fa fa-upload mr-1"></i> 选择图片
</label>
<input type="file" id="noteCover" accept="image/*" class="hidden">
<p class="text-xs text-gray-500 mt-1">支持JPG、PNG格式建议尺寸400×200</p>
</div>
</div>
</div>
<!-- 提交按钮 -->
<div class="flex gap-3 pt-2">
<button type="button" id="cancelNewNote" class="flex-1 btn-action btn-secondary">
取消
</button>
<button type="submit" class="flex-1 login-btn">
<span id="noteSubmitBtnText">保存笔记</span>
<i class="fa fa-check"></i>
</button>
</div>
</form>
</div>
</div>
<!-- 插入图片模态框 -->
<div id="insertImageModal" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50 hidden transition-opacity duration-300">
<div class="w-full max-w-md bg-white rounded-xl p-6 shadow-lg transform transition-transform duration-300 scale-95">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-dark">插入图片</h2>
<button id="closeInsertImageModal" class="text-gray-400 hover:text-gray-600">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="space-y-5">
<!-- 上传选项卡 -->
<div class="border-b border-gray-200">
<div class="flex">
<button class="px-4 py-2 text-sm font-medium text-primary border-b-2 border-primary" id="uploadTabBtn">
本地上传
</button>
<button class="px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700" id="urlTabBtn">
图片链接
</button>
</div>
</div>
<!-- 其他表单内容(如笔记内容、封面上传等) -->
<!-- ... -->
</form>
</div>
</div>
<!-- 本地上传区域 -->
<div id="uploadTab" class="space-y-4">
<div class="file-drop-area" id="imageDropArea">
<input type="file" id="imageUpload" accept="image/*" class="hidden">
<i class="fa fa-cloud-upload text-2xl text-gray-400 mb-2"></i>
<p class="text-sm text-gray-600 mb-1">点击或拖拽图片到此处</p>
<p class="text-xs text-gray-500">支持JPG、PNG格式最大5MB</p>
</div>
<!-- 预览区域 -->
<div id="imagePreviewContainer" class="hidden">
<p class="text-sm font-medium text-gray-700 mb-2">预览:</p>
<div class="relative">
<img id="imagePreview" src="" alt="图片预览" class="max-w-full max-h-60 rounded-md border border-gray-200">
<button id="removeImage" class="absolute top-2 right-2 w-6 h-6 bg-black/50 text-white rounded-full flex items-center justify-center hover:bg-black/70 transition-colors">
<i class="fa fa-times text-xs"></i>
</button>
</div>
</div>
</div>
<!-- 图片链接区域 -->
<div id="urlTab" class="hidden space-y-4">
<div>
<label for="imageUrl" class="block text-sm font-medium text-gray-700 mb-1">图片URL</label>
<input
type="url"
id="imageUrl"
class="login-input"
placeholder="https://example.com/image.jpg"
>
<p class="text-xs text-gray-500 mt-1">请输入有效的图片链接</p>
</div>
<div class="bg-gray-50 p-3 rounded-md">
<label class="flex items-center gap-2 text-sm">
<input type="checkbox" id="imageResponsive" checked>
<span>自适应宽度</span>
</label>
</div>
</div>
<!-- 按钮 -->
<div class="flex gap-3 pt-2">
<button type="button" id="cancelInsertImage" class="flex-1 bg-gray-200 text-dark py-2 rounded-md font-medium hover:bg-gray-300 transition-colors">
取消
</button>
<button type="button" id="confirmInsertImage" class="flex-1 bg-primary text-white py-2 rounded-md font-medium hover:bg-primary/90 transition-colors flex items-center justify-center gap-2">
<span>插入图片</span>
<i class="fa fa-arrow-right"></i>
</button>
</div>
</div>
</div>
</div>
<!-- 导入笔记模态框 -->
<div id="importNoteModal" class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50 hidden transition-opacity duration-300">
@ -962,44 +719,6 @@
const userName = document.getElementById('user-name');
const userGradeMajor = document.getElementById('user-grade-major');
// 笔记相关元素
const categoryFilter = document.getElementById('categoryFilter');
const newNoteBtn = document.getElementById('newNoteBtn');
const importNoteBtn = document.getElementById('importNoteBtn');
const newNoteModal = document.getElementById('newNoteModal');
const closeNewNoteModal = document.getElementById('closeNewNoteModal');
const cancelNewNote = document.getElementById('cancelNewNote');
const newNoteForm = document.getElementById('newNoteForm');
const noteModalTitle = document.getElementById('noteModalTitle');
const noteId = document.getElementById('noteId');
const noteTitle = document.getElementById('noteTitle');
const noteCategory = document.getElementById('noteCategory');
const noteContent = document.getElementById('noteContent');
const noteCover = document.getElementById('noteCover');
const noteCoverPreview = document.getElementById('noteCoverPreview');
const coverPlaceholder = document.getElementById('coverPlaceholder');
const noteSubmitBtnText = document.getElementById('noteSubmitBtnText');
const notesContainer = document.getElementById('notes-container');
let currentSelectedCategory = 'all';
// 富文本编辑器元素
const toolbarButtons = document.querySelectorAll('.toolbar-btn[data-command]');
const insertImageBtn = document.getElementById('insertImageBtn');
const insertImageModal = document.getElementById('insertImageModal');
const closeInsertImageModal = document.getElementById('closeInsertImageModal');
const cancelInsertImage = document.getElementById('cancelInsertImage');
const confirmInsertImage = document.getElementById('confirmInsertImage');
const uploadTabBtn = document.getElementById('uploadTabBtn');
const urlTabBtn = document.getElementById('urlTabBtn');
const uploadTab = document.getElementById('uploadTab');
const urlTab = document.getElementById('urlTab');
const imageDropArea = document.getElementById('imageDropArea');
const imageUpload = document.getElementById('imageUpload');
const imagePreviewContainer = document.getElementById('imagePreviewContainer');
const imagePreview = document.getElementById('imagePreview');
const removeImage = document.getElementById('removeImage');
const imageUrl = document.getElementById('imageUrl');
const imageResponsive = document.getElementById('imageResponsive');
// 导入相关元素
const importNoteModal = document.getElementById('importNoteModal');
@ -1261,491 +980,8 @@ document.querySelectorAll('.sidebar-item[data-view]').forEach(item => {
});
});
// 搜索笔记 + 分类筛选 联合功能
const noteSearchInput = document.getElementById('noteSearch');
// 搜索框输入事件
if (noteSearchInput) {
noteSearchInput.addEventListener('input', function () {
const searchTerm = this.value.trim().toLowerCase();
// 调用联合筛选函数(分类+关键词)
filterNotesByCategoryAndSearch(searchTerm);
});
}
// 分类筛选下拉框切换事件(新增)
if (categoryFilter) {
categoryFilter.addEventListener('change', function () {
currentSelectedCategory = this.value; // 更新当前选中分类
const searchTerm = noteSearchInput.value.trim().toLowerCase();
// 调用联合筛选函数(分类+关键词)
filterNotesByCategoryAndSearch(searchTerm);
});
}
// 新增:联合筛选函数(同时处理分类和搜索关键词)
function filterNotesByCategoryAndSearch(searchTerm) {
let filteredNotes = notesData;
// 第一步:按分类筛选(非“全部分类”时过滤)
if (currentSelectedCategory !== 'all') {
filteredNotes = filteredNotes.filter(note => note.category === currentSelectedCategory);
}
// 第二步:按关键词筛选(搜索框有内容时过滤)
if (searchTerm !== '') {
filteredNotes = filteredNotes.filter(note => {
const titleMatch = note.title.toLowerCase().includes(searchTerm);
const contentMatch = stripHtml(note.content).toLowerCase().includes(searchTerm);
return titleMatch || contentMatch;
});
}
// 渲染筛选后的笔记列表
renderNotes(filteredNotes);
}
// 富文本编辑器功能实现
// 文本格式化按钮
toolbarButtons.forEach(button => {
button.addEventListener('click', () => {
const command = button.getAttribute('data-command');
// 特殊处理链接插入
if (command === 'createLink') {
const url = prompt('请输入链接地址:');
if (url) {
document.execCommand(command, false, url);
}
return;
}
// 执行命令
document.execCommand(command, false, null);
// 聚焦回编辑区域
noteContent.focus();
// 更新按钮状态(如粗体按钮是否激活)
updateToolbarState();
});
});
// 更新工具栏按钮状态
function updateToolbarState() {
toolbarButtons.forEach(button => {
const command = button.getAttribute('data-command');
if (document.queryCommandState(command)) {
button.classList.add('active');
} else {
button.classList.remove('active');
}
});
}
// 监听编辑区域选择变化,更新工具栏状态
noteContent.addEventListener('mouseup', updateToolbarState);
noteContent.addEventListener('keyup', updateToolbarState);
// 插入图片模态框控制
insertImageBtn.addEventListener('click', () => {
insertImageModal.classList.remove('hidden');
setTimeout(() => {
insertImageModal.querySelector('div').classList.add('scale-100');
insertImageModal.querySelector('div').classList.remove('scale-95');
}, 10);
resetInsertImageForm();
});
closeInsertImageModal.addEventListener('click', () => {
closeInsertImageModalHandler();
});
cancelInsertImage.addEventListener('click', () => {
closeInsertImageModalHandler();
});
function closeInsertImageModalHandler() {
insertImageModal.querySelector('div').classList.add('scale-95');
insertImageModal.querySelector('div').classList.remove('scale-100');
setTimeout(() => {
insertImageModal.classList.add('hidden');
}, 300);
}
// 重置插入图片表单
function resetInsertImageForm() {
imageUpload.value = '';
imagePreviewContainer.classList.add('hidden');
imagePreview.src = '';
imageUrl.value = '';
imageResponsive.checked = true;
showTab('upload');
}
// 切换上传/URL选项卡
uploadTabBtn.addEventListener('click', () => {
showTab('upload');
});
urlTabBtn.addEventListener('click', () => {
showTab('url');
});
function showTab(tabName) {
if (tabName === 'upload') {
uploadTab.classList.remove('hidden');
urlTab.classList.add('hidden');
uploadTabBtn.classList.add('text-primary', 'border-b-2', 'border-primary');
uploadTabBtn.classList.remove('text-gray-500');
urlTabBtn.classList.remove('text-primary', 'border-b-2', 'border-primary');
urlTabBtn.classList.add('text-gray-500');
} else {
uploadTab.classList.add('hidden');
urlTab.classList.remove('hidden');
uploadTabBtn.classList.remove('text-primary', 'border-b-2', 'border-primary');
uploadTabBtn.classList.add('text-gray-500');
urlTabBtn.classList.add('text-primary', 'border-b-2', 'border-primary');
urlTabBtn.classList.remove('text-gray-500');
}
}
// 图片上传处理
imageDropArea.addEventListener('click', () => {
imageUpload.click();
});
imageUpload.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
handleImageUpload(file);
}
});
// 拖拽图片处理
imageDropArea.addEventListener('dragover', (e) => {
e.preventDefault();
imageDropArea.classList.add('border-primary', 'bg-primary/5');
});
imageDropArea.addEventListener('dragleave', () => {
imageDropArea.classList.remove('border-primary', 'bg-primary/5');
});
imageDropArea.addEventListener('drop', (e) => {
e.preventDefault();
imageDropArea.classList.remove('border-primary', 'bg-primary/5');
const file = e.dataTransfer.files[0];
if (file) {
handleImageUpload(file);
}
});
// 处理图片上传
function handleImageUpload(file) {
// 检查文件类型
if (!file.type.startsWith('image/')) {
alert('请选择图片文件JPG、PNG格式');
return;
}
// 检查文件大小
if (file.size > 5 * 1024 * 1024) {
alert('图片大小不能超过5MB');
return;
}
// 预览图片
const reader = new FileReader();
reader.onload = (event) => {
imagePreview.src = event.target.result;
imagePreviewContainer.classList.remove('hidden');
};
reader.readAsDataURL(file);
}
// 移除已选择的图片
removeImage.addEventListener('click', () => {
imageUpload.value = '';
imagePreviewContainer.classList.add('hidden');
imagePreview.src = '';
});
// 确认插入图片
confirmInsertImage.addEventListener('click', () => {
let imageSrc = '';
// 检查是上传还是URL
if (!uploadTab.classList.contains('hidden')) {
// 上传方式
if (!imagePreview.src) {
alert('请先选择图片');
return;
}
imageSrc = imagePreview.src;
} else {
// URL方式
if (!imageUrl.value.trim()) {
alert('请输入图片URL');
return;
}
imageSrc = imageUrl.value.trim();
}
// 在编辑器中插入图片
const isResponsive = imageResponsive.checked;
const img = document.createElement('img');
img.src = imageSrc;
img.alt = '插入的图片';
if (isResponsive) {
img.style.maxWidth = '100%';
img.style.height = 'auto';
}
// 获取选择对象
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(img);
// 在图片后添加一个空格,方便继续输入
range.setStartAfter(img);
range.setEndAfter(img);
range.insertNode(document.createTextNode(' '));
selection.removeAllRanges();
selection.addRange(range);
} else {
// 如果没有选择范围,直接添加到末尾
noteContent.appendChild(img);
noteContent.appendChild(document.createTextNode(' '));
}
// 关闭模态框
closeInsertImageModalHandler();
// 聚焦回编辑区域
noteContent.focus();
});
// 新建笔记模态框控制
newNoteBtn.addEventListener('click', () => {
// 切换到新建模式
noteModalTitle.textContent = '新建笔记';
noteSubmitBtnText.textContent = '保存笔记';
noteId.value = '';
newNoteModal.classList.remove('hidden');
setTimeout(() => {
newNoteModal.querySelector('div').classList.add('scale-100');
newNoteModal.querySelector('div').classList.remove('scale-95');
}, 10);
resetNewNoteForm();
});
closeNewNoteModal.addEventListener('click', () => {
closeNewNoteModalHandler();
});
cancelNewNote.addEventListener('click', () => {
closeNewNoteModalHandler();
});
function closeNewNoteModalHandler() {
newNoteModal.querySelector('div').classList.add('scale-95');
newNoteModal.querySelector('div').classList.remove('scale-100');
setTimeout(() => {
newNoteModal.classList.add('hidden');
}, 300);
}
// 重置新建笔记表单
function resetNewNoteForm() {
newNoteForm.reset();
noteTitleError.classList.add('hidden');
noteCategoryError.classList.add('hidden');
noteContentError.classList.add('hidden');
noteContent.innerHTML = '';
noteCoverPreview.classList.add('hidden');
coverPlaceholder.classList.remove('hidden');
noteCover.value = '';
}
// 笔记封面预览
noteCover.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
noteCoverPreview.src = event.target.result;
noteCoverPreview.classList.remove('hidden');
coverPlaceholder.classList.add('hidden');
};
reader.readAsDataURL(file);
}
});
// 编辑笔记功能
notesContainer.addEventListener('click', (e) => {
const editBtn = e.target.closest('.edit-note');
if (editBtn) {
const noteId = editBtn.getAttribute('data-id');
openEditNoteModal(noteId);
}
});
// 打开编辑笔记模态框
function openEditNoteModal(id) {
const note = notesData.find(n => n.id == id);
if (!note) return;
// 切换到编辑模式
noteModalTitle.textContent = '编辑笔记';
noteSubmitBtnText.textContent = '更新笔记';
noteId.value = note.id;
// 填充表单数据
noteTitle.value = note.title;
noteCategory.value = note.category;
noteContent.innerHTML = note.content;
// 显示封面
if (note.cover) {
noteCoverPreview.src = note.cover;
noteCoverPreview.classList.remove('hidden');
coverPlaceholder.classList.add('hidden');
} else {
noteCoverPreview.classList.add('hidden');
coverPlaceholder.classList.remove('hidden');
}
// 显示模态框
newNoteModal.classList.remove('hidden');
setTimeout(() => {
newNoteModal.querySelector('div').classList.add('scale-100');
newNoteModal.querySelector('div').classList.remove('scale-95');
}, 10);
}
// 删除笔记功能
notesContainer.addEventListener('click', (e) => {
const deleteBtn = e.target.closest('.delete-note');
if (deleteBtn) {
const noteId = deleteBtn.getAttribute('data-id');
const note = notesData.find(n => n.id == noteId);
if (confirm(`确定要删除“${note.title}”吗?`)) {
// 从内存中移除笔记
notesData = notesData.filter(n => n.id != noteId);
// 同步保存到 LocalStorage
localStorage.setItem('notesData', JSON.stringify(notesData));
// 重新渲染笔记列表
const searchTerm = noteSearchInput.value.trim().toLowerCase();
filterNotesByCategoryAndSearch(searchTerm);
}
}
});
// 新建/编辑笔记表单提交
if (newNoteForm) { // 确保表单元素存在
newNoteForm.addEventListener('submit', (e) => {
e.preventDefault();
let isValid = true;
// 验证表单(先检查元素是否存在,避免报错)
if (noteTitle && noteTitleError) {
if (!noteTitle.value.trim()) {
noteTitleError.classList.remove('hidden');
isValid = false;
} else {
noteTitleError.classList.add('hidden');
}
}
// 分类验证假设分类输入框id为"noteCategory"错误提示id为"noteCategoryError"
if (noteCategory && noteCategoryError) {
// 允许分类为空时可改为if (noteCategory.value.trim() === '')
// 验证笔记分类
if (!noteCategory.value) {
noteCategoryError.classList.remove('hidden');
isValid = false;
} else {
noteCategoryError.classList.add('hidden');
}
}
// 内容验证
if (noteContent && noteContentError) {
if (!noteContent.innerHTML.trim()) {
noteContentError.classList.remove('hidden');
isValid = false;
} else {
noteContentError.classList.add('hidden');
}
}
if (isValid) {
const isEditMode = !!noteId?.value; // 安全访问noteId
// 确保notesData是数组避免未初始化导致的错误
if (!Array.isArray(notesData)) {
notesData = [];
}
if (isEditMode) {
// 更新现有笔记
const index = notesData.findIndex(n => n.id == noteId.value);
if (index !== -1) {
notesData[index] = {
...notesData[index],
title: noteTitle.value.trim(),
category: noteCategory?.value || '', // 安全访问分类值
content: noteContent.innerHTML,
date: new Date().toISOString().split('T')[0]
};
// 若上传新封面,更新封面
if (noteCoverPreview && noteCoverPreview.src && !noteCoverPreview.classList.contains('hidden')) {
notesData[index].cover = noteCoverPreview.src;
}
}
} else {
// 生成新笔记ID处理空数组情况
const maxId = notesData.length > 0
? Math.max(...notesData.map(n => Number(n.id) || 0))
: 0;
const newNoteId = maxId + 1;
// 创建新笔记
const newNote = {
id: newNoteId,
title: noteTitle.value.trim(),
category: noteCategory?.value || '', // 分类为空时用空字符串
content: noteContent.innerHTML,
cover: noteCoverPreview?.src || `https://picsum.photos/id/${30 + notesData.length}/400/200`,
date: new Date().toISOString().split('T')[0],
type: 'Text',
views: 0
};
notesData.unshift(newNote); // 添加到数组开头(最新的在前面)
}
// 同步保存到LocalStorage
localStorage.setItem('notesData', JSON.stringify(notesData));
// 刷新列表(确保搜索框元素存在)
const searchTerm = noteSearchInput?.value.trim().toLowerCase() || '';
filterNotesByCategoryAndSearch(searchTerm);
// 关闭模态框 + 提示成功
closeNewNoteModalHandler();
alert(isEditMode ? '笔记更新成功!' : '笔记创建成功!');
// 更新分类下拉框
renderDynamicCategoryFilter();
}
});
}
// 导入笔记模态框控制
importNoteBtn.addEventListener('click', () => {
importNoteModal.classList.remove('hidden');
@ -2239,8 +1475,7 @@ function fetchNotesFromServer() {
notesData = validNotes;
localStorage.setItem('notesData', JSON.stringify(notesData));
renderNotes();
// 新增:获取数据后渲染分类下拉框
renderDynamicCategoryFilter();
})
.catch(err => {
console.error('刷新失败:', err);
@ -2432,19 +1667,7 @@ document.getElementById('documents-container').addEventListener('click', async f
}
// 填充笔记编辑区域并打开模态框
function fillNoteWithContent(title, content, type) {
const noteTitle = document.getElementById('noteTitle');
const noteContent = document.getElementById('noteContent');
const noteType = document.getElementById('noteType'); // 假设笔记有“类型”字段需在HTML中添加隐藏输入
noteTitle.value = title;
noteContent.innerHTML = content;
if (noteType) noteType.value = type; // 可选:标记笔记类型
// 打开“新建笔记”模态框(模拟点击按钮)
document.getElementById('newNoteBtn').click();
}
// 单独渲染PDF文件用PDF.js
function openPdfViewer(pdfUrl) {
@ -2485,100 +1708,8 @@ function openPdfViewer(pdfUrl) {
});
}
// 动态渲染分类下拉框(根据用户输入的分类自动生成选项)
function renderDynamicCategoryFilter() {
const categoryFilter = document.getElementById('categoryFilter');
if (!categoryFilter) return;
// 清空现有选项
categoryFilter.innerHTML = '';
// 添加“全部分类”默认选项
const allOption = document.createElement('option');
allOption.value = 'all';
allOption.textContent = '全部分类';
categoryFilter.appendChild(allOption);
// 提取所有非空分类(去重)
const categories = new Set();
if (Array.isArray(notesData)) {
notesData.forEach(note => {
if (note.category && note.category.trim() !== '') {
categories.add(note.category.trim());
}
});
}
// 排序并生成选项
const sortedCategories = Array.from(categories).sort((a, b) => a.localeCompare(b));
sortedCategories.forEach(category => {
const option = document.createElement('option');
option.value = category;
option.textContent = category;
categoryFilter.appendChild(option);
});
// 保持当前选中分类
if (currentSelectedCategory && categoryFilter.querySelector(`option[value="${currentSelectedCategory}"]`)) {
categoryFilter.value = currentSelectedCategory;
}
}
// 渲染笔记列表(支持传入过滤后的笔记数据)
function renderNotes(notesToRender = notesData) {
// 1. 确保能找到笔记容器元素
const notesContainer = document.getElementById('notes-container');
if (!notesContainer) {
console.error('页面中未找到笔记容器元素 #notes-container请检查DOM结构');
return;
}
// 2. 处理「无数据」或「数据格式错误」的情况
if (!Array.isArray(notesToRender) || notesToRender.length === 0) {
notesContainer.innerHTML = `
<div class="text-center py-12 text-gray-500">
<i class="fa fa-book-open text-4xl mb-4"></i>
</div>
`;
return;
}
notesContainer.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
${notesToRender.map(note => `
<div class="bg-white rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow border border-gray-200">
<div class="h-40 bg-gray-100 flex items-center justify-center">
<img src="${note.cover}" alt="${note.title}预览" class="w-full h-full object-cover">
</div>
<div class="p-4">
<div class="flex items-center justify-between mb-2">
<span class="text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded">${note.category}</span>
<span class="text-xs text-gray-500">${note.date}</span>
</div>
<h3 class="font-medium mb-2 line-clamp-1">${note.title}</h3>
<p class="text-sm text-gray-600 mb-3 line-clamp-2">${stripHtml(note.content.substring(0, 100))}...</p>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<span class="text-xs text-gray-500 flex items-center">
<i class="fa fa-file-${note.type === 'PDF' ? 'pdf' : note.type === 'Word' ? 'word' : 'text'}-o mr-1"></i> ${note.type}
</span>
<span class="text-xs text-gray-500 flex items-center">
<i class="fa fa-eye mr-1"></i> ${note.views}
</span>
</div>
<div class="flex items-center gap-3">
<button class="text-gray-500 hover:text-primary edit-note" title="编辑" data-id="${note.id}">
<i class="fa fa-pencil text-lg"></i>
</button>
<button class="text-gray-500 hover:text-red-500 delete-note" title="删除" data-id="${note.id}">
<i class="fa fa-trash text-lg"></i>
</button>
</div>
</div>
</div>
</div>
`).join('')}
</div>
`;
}
// 辅助函数去除HTML标签
function stripHtml(html) {
@ -2780,7 +1911,6 @@ document.addEventListener('DOMContentLoaded', () => {
fetchAllDocuments();
document.getElementById('notes-view').classList.remove('hidden');
document.getElementById('qa-view').classList.add('hidden');
renderDynamicCategoryFilter();
renderGraphCategoryFilter(); // 新增:初始化知识图谱分类选择框
const searchTerm = noteSearchInput.value.trim().toLowerCase();
filterNotesByCategoryAndSearch(searchTerm);

Loading…
Cancel
Save