| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958 |
- /**
- * 文档管理模块
- */
- // 文档列表
- let documents = [];
- // 当前正在编辑的文档
- let currentDocument = null;
- // Markdown编辑器实例
- let editorMd = null;
- // 创建documentManager对象
- const documentManager = {
- // 初始化文档管理
- init: function() {
- console.log('初始化文档管理模块...');
- // 渲染表头
- this.renderDocumentTableHeader();
- // 加载文档列表
- return this.loadDocuments().catch(err => {
- console.error('加载文档列表失败:', err);
- return Promise.resolve(); // 即使失败也继续初始化过程
- });
- },
- // 渲染文档表格头部
- renderDocumentTableHeader: function() {
- try {
- const documentTable = document.getElementById('documentTable');
- if (!documentTable) {
- console.warn('文档管理表格元素 (id=\"documentTable\") 未找到,无法渲染表头。');
- return;
- }
-
- // 查找或创建 thead
- let thead = documentTable.querySelector('thead');
- if (!thead) {
- thead = document.createElement('thead');
- documentTable.insertBefore(thead, documentTable.firstChild); // 确保 thead 在 tbody 之前
- console.log('创建了文档表格的 thead 元素。');
- }
-
- // 设置表头内容 (包含 ID 列)
- thead.innerHTML = `
- <tr>
- <th style="width: 5%">#</th>
- <th style="width: 25%">标题</th>
- <th style="width: 20%">创建时间</th>
- <th style="width: 20%">更新时间</th>
- <th style="width: 10%">状态</th>
- <th style="width: 20%">操作</th>
- </tr>
- `;
- console.log('文档表格表头已渲染。');
- } catch (error) {
- console.error('渲染文档表格表头时出错:', error);
- }
- },
- // 加载文档列表
- loadDocuments: async function() {
- try {
- // 显示加载状态
- const documentTableBody = document.getElementById('documentTableBody');
- if (documentTableBody) {
- documentTableBody.innerHTML = '<tr><td colspan="6" style="text-align: center;"><i class="fas fa-spinner fa-spin"></i> 正在加载文档列表...</td></tr>';
- }
-
- // 简化会话检查逻辑,只验证会话是否有效
- let sessionValid = true;
- try {
- const sessionResponse = await fetch('/api/check-session', {
- headers: {
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin'
- });
-
- if (sessionResponse.status === 401) {
- console.warn('会话已过期,无法加载文档');
- sessionValid = false;
- }
- } catch (sessionError) {
- console.warn('检查会话状态发生网络错误:', sessionError);
- // 发生网络错误时继续尝试加载文档
- }
-
- // 尝试不同的API路径
- const possiblePaths = [
- '/api/documents',
- '/api/documentation-list',
- '/api/documentation'
- ];
-
- let success = false;
- let authError = false;
-
- for (const path of possiblePaths) {
- try {
- console.log(`尝试从 ${path} 获取文档列表`);
- const response = await fetch(path, {
- credentials: 'same-origin',
- headers: {
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest'
- }
- });
-
- if (response.status === 401) {
- console.warn(`API路径 ${path} 返回未授权状态`);
- authError = true;
- continue;
- }
-
- if (response.ok) {
- const data = await response.json();
- documents = Array.isArray(data) ? data : [];
-
- // 确保每个文档都包含必要的时间字段
- documents = documents.map(doc => {
- if (!doc.createdAt && doc.updatedAt) {
- // 如果没有创建时间但有更新时间,使用更新时间
- doc.createdAt = doc.updatedAt;
- } else if (!doc.createdAt) {
- // 如果都没有,使用当前时间
- doc.createdAt = new Date().toISOString();
- }
-
- if (!doc.updatedAt) {
- // 如果没有更新时间,使用创建时间
- doc.updatedAt = doc.createdAt;
- }
-
- return doc;
- });
-
- // 先渲染表头,再渲染文档列表
- this.renderDocumentTableHeader();
- this.renderDocumentList();
- console.log(`成功从API路径 ${path} 加载文档列表`, documents);
- success = true;
- break;
- }
- } catch (e) {
- console.warn(`从 ${path} 加载文档失败:`, e);
- }
- }
-
- // 处理认证错误 - 只有当会话检查和API请求都明确失败时才强制登出
- if ((authError || !sessionValid) && !success && localStorage.getItem('isLoggedIn') === 'true') {
- console.warn('会话检查和API请求均指示会话已过期');
- core.showAlert('会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- // 如果API请求失败但不是认证错误,显示空文档列表
- if (!success) {
- console.log('API请求失败,显示空文档列表');
- documents = [];
- // 仍然需要渲染表头
- this.renderDocumentTableHeader();
- this.renderDocumentList();
- }
- } catch (error) {
- console.error('加载文档失败:', error);
- // 在UI上显示错误
- const documentTableBody = document.getElementById('documentTableBody');
- if (documentTableBody) {
- documentTableBody.innerHTML = `<tr><td colspan="6" style="text-align: center; color: red;">加载文档失败: ${error.message} <button onclick="documentManager.loadDocuments()">重试</button></td></tr>`;
- }
-
- // 设置为空文档列表
- documents = [];
- }
- },
- // 初始化编辑器
- initEditor: function() {
- try {
- const editorContainer = document.getElementById('editor');
- if (!editorContainer) {
- console.error('找不到编辑器容器元素');
- return;
- }
-
- // 检查 toastui 是否已加载
- console.log('检查编辑器依赖项:', typeof toastui);
-
- // 确保 toastui 对象存在
- if (typeof toastui === 'undefined') {
- console.error('Toast UI Editor 未加载');
- return;
- }
-
- // 创建编辑器实例
- editorMd = new toastui.Editor({
- el: editorContainer,
- height: '600px',
- initialValue: '',
- previewStyle: 'vertical',
- initialEditType: 'markdown',
- toolbarItems: [
- ['heading', 'bold', 'italic', 'strike'],
- ['hr', 'quote'],
- ['ul', 'ol', 'task', 'indent', 'outdent'],
- ['table', 'image', 'link'],
- ['code', 'codeblock']
- ]
- });
- console.log('编辑器初始化完成', editorMd);
- } catch (error) {
- console.error('初始化编辑器出错:', error);
- core.showAlert('初始化编辑器失败: ' + error.message, 'error');
- }
- },
- // 检查编辑器是否已初始化
- isEditorInitialized: function() {
- return editorMd !== null;
- },
- // 创建新文档
- newDocument: function() {
- // 首先确保编辑器已初始化
- if (!editorMd) {
- this.initEditor();
- // 等待编辑器初始化完成后再继续
- setTimeout(() => {
- currentDocument = null;
- document.getElementById('documentTitle').value = '';
- editorMd.setMarkdown('');
- this.showEditor();
- }, 500);
- } else {
- currentDocument = null;
- document.getElementById('documentTitle').value = '';
- editorMd.setMarkdown('');
- this.showEditor();
- }
- },
- // 显示编辑器
- showEditor: function() {
- document.getElementById('documentTable').style.display = 'none';
- document.getElementById('editorContainer').style.display = 'block';
- if (editorMd) {
- // 确保每次显示编辑器时都切换到编辑模式
- editorMd.focus();
- }
- },
- // 隐藏编辑器
- hideEditor: function() {
- document.getElementById('documentTable').style.display = 'table';
- document.getElementById('editorContainer').style.display = 'none';
- },
- // 取消编辑
- cancelEdit: function() {
- this.hideEditor();
- },
- // 保存文档
- saveDocument: async function() {
- const title = document.getElementById('documentTitle').value.trim();
- const content = editorMd.getMarkdown();
-
- if (!title) {
- core.showAlert('请输入文档标题', 'error');
- return;
- }
-
- // 显示保存中状态
- core.showLoading();
-
- try {
- // 简化会话检查逻辑,只验证会话是否有效
- let sessionValid = true;
- try {
- const sessionResponse = await fetch('/api/check-session', {
- headers: {
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin'
- });
-
- if (sessionResponse.status === 401) {
- console.warn('会话已过期,无法保存文档');
- sessionValid = false;
- }
- } catch (sessionError) {
- console.warn('检查会话状态发生网络错误:', sessionError);
- // 发生网络错误时继续尝试保存操作
- }
-
- // 只有在会话明确无效时才退出
- if (!sessionValid) {
- core.showAlert('您的会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- // 确保Markdown内容以标题开始
- let processedContent = content;
- if (!content.startsWith('# ')) {
- // 如果内容不是以一级标题开始,则在开头添加标题
- processedContent = `# ${title}\n\n${content}`;
- } else {
- // 如果已经有一级标题,替换为当前标题
- processedContent = content.replace(/^# .*$/m, `# ${title}`);
- }
-
- const apiUrl = currentDocument && currentDocument.id
- ? `/api/documents/${currentDocument.id}`
- : '/api/documents';
-
- const method = currentDocument && currentDocument.id ? 'PUT' : 'POST';
-
- console.log(`尝试${method === 'PUT' ? '更新' : '创建'}文档,标题: ${title}`);
-
- const response = await fetch(apiUrl, {
- method: method,
- headers: {
- 'Content-Type': 'application/json',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin',
- body: JSON.stringify({
- title,
- content: processedContent,
- published: currentDocument && currentDocument.published ? currentDocument.published : false
- })
- });
-
- // 处理响应
- if (response.status === 401) {
- // 明确的未授权响应
- console.warn('保存文档返回401未授权');
- core.showAlert('未登录或会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- if (!response.ok) {
- const errorText = await response.text();
- let errorData;
- try {
- errorData = JSON.parse(errorText);
- } catch (e) {
- // 如果不是有效的JSON,直接使用文本
- throw new Error(errorText || '保存失败,请重试');
- }
- throw new Error(errorData.error || errorData.message || '保存失败,请重试');
- }
-
- const savedDoc = await response.json();
- console.log('保存的文档:', savedDoc);
- // 确保savedDoc包含必要的时间字段
- if (savedDoc) {
- // 如果返回的保存文档中没有时间字段,从API获取完整文档信息
- if (!savedDoc.createdAt || !savedDoc.updatedAt) {
- try {
- const docId = savedDoc.id || (currentDocument ? currentDocument.id : null);
- if (docId) {
- const docResponse = await fetch(`/api/documents/${docId}`, {
- headers: { 'Cache-Control': 'no-cache' },
- credentials: 'same-origin'
- });
-
- if (docResponse.ok) {
- const fullDoc = await docResponse.json();
- Object.assign(savedDoc, {
- createdAt: fullDoc.createdAt,
- updatedAt: fullDoc.updatedAt
- });
- console.log('获取到完整的文档时间信息:', fullDoc);
- }
- }
- } catch (timeError) {
- console.warn('获取文档完整时间信息失败:', timeError);
- }
- }
-
- // 更新文档列表中的文档
- const existingIndex = documents.findIndex(d => d.id === savedDoc.id);
- if (existingIndex >= 0) {
- documents[existingIndex] = { ...documents[existingIndex], ...savedDoc };
- } else {
- documents.push(savedDoc);
- }
- }
- core.showAlert('文档保存成功', 'success');
- this.hideEditor();
- await this.loadDocuments(); // 重新加载文档列表
- } catch (error) {
- console.error('保存文档失败:', error);
- core.showAlert('保存文档失败: ' + error.message, 'error');
- } finally {
- core.hideLoading();
- }
- },
- // 渲染文档列表
- renderDocumentList: function() {
- const tbody = document.getElementById('documentTableBody');
- tbody.innerHTML = '';
-
- if (documents.length === 0) {
- tbody.innerHTML = '<tr><td colspan="6" style="text-align: center;">没有找到文档</td></tr>';
- return;
- }
-
- documents.forEach((doc, index) => {
- // 确保文档时间有合理默认值
- let createdAt = '未知';
- let updatedAt = '未知';
-
- try {
- // 尝试解析创建时间,如果失败则回退到默认值
- if (doc.createdAt) {
- const createdDate = new Date(doc.createdAt);
- if (!isNaN(createdDate.getTime())) {
- createdAt = createdDate.toLocaleString('zh-CN', {
- year: 'numeric',
- month: '2-digit',
- day: '2-digit',
- hour: '2-digit',
- minute: '2-digit',
- second: '2-digit'
- });
- }
- }
-
- // 尝试解析更新时间,如果失败则回退到默认值
- if (doc.updatedAt) {
- const updatedDate = new Date(doc.updatedAt);
- if (!isNaN(updatedDate.getTime())) {
- updatedAt = updatedDate.toLocaleString('zh-CN', {
- year: 'numeric',
- month: '2-digit',
- day: '2-digit',
- hour: '2-digit',
- minute: '2-digit',
- second: '2-digit'
- });
- }
- }
-
- // 简化时间显示逻辑 - 直接显示时间戳,不添加特殊标记
- if (createdAt === '未知' && updatedAt !== '未知') {
- // 如果没有创建时间但有更新时间
- createdAt = '未记录';
- } else if (updatedAt === '未知' && createdAt !== '未知') {
- // 如果没有更新时间但有创建时间
- updatedAt = '未更新';
- }
- } catch (error) {
- console.warn(`解析文档时间失败:`, error, doc);
- }
-
- const statusClasses = doc.published ? 'status-badge status-running' : 'status-badge status-stopped';
- const statusText = doc.published ? '已发布' : '未发布';
-
- const row = document.createElement('tr');
- row.innerHTML = `
- <td>${index + 1}</td>
- <td>${doc.title || '无标题文档'}</td>
- <td>${createdAt}</td>
- <td>${updatedAt}</td>
- <td><span class="${statusClasses}">${statusText}</span></td>
- <td class="action-buttons">
- <button class="action-btn edit-btn" title="编辑文档" onclick="documentManager.editDocument('${doc.id}')">
- <i class="fas fa-edit"></i>
- </button>
- <button class="action-btn ${doc.published ? 'unpublish-btn' : 'publish-btn'}"
- title="${doc.published ? '取消发布' : '发布文档'}"
- onclick="documentManager.togglePublish('${doc.id}')">
- <i class="fas ${doc.published ? 'fa-toggle-off' : 'fa-toggle-on'}"></i>
- </button>
- <button class="action-btn delete-btn" title="删除文档" onclick="documentManager.deleteDocument('${doc.id}')">
- <i class="fas fa-trash"></i>
- </button>
- </td>
- `;
-
- tbody.appendChild(row);
- });
- },
- // 编辑文档
- editDocument: async function(id) {
- try {
- console.log(`准备编辑文档,ID: ${id}`);
- core.showLoading();
-
- // 检查会话状态,优化会话检查逻辑
- let sessionValid = true;
- try {
- const sessionResponse = await fetch('/api/check-session', {
- headers: {
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin'
- });
-
- if (sessionResponse.status === 401) {
- console.warn('会话已过期,无法编辑文档');
- sessionValid = false;
- }
- } catch (sessionError) {
- console.warn('检查会话状态发生网络错误:', sessionError);
- // 发生网络错误时不立即判定会话失效,继续尝试编辑操作
- }
-
- // 只有在明确会话无效时才提示重新登录
- if (!sessionValid) {
- core.showAlert('您的会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- // 在本地查找文档
- currentDocument = documents.find(doc => doc.id === id);
-
- // 如果本地未找到,从API获取
- if (!currentDocument && id) {
- try {
- console.log('从API获取文档详情');
-
- // 尝试多个可能的API路径
- const apiPaths = [
- `/api/documents/${id}`,
- `/api/documentation/${id}`
- ];
-
- let docResponse = null;
- let authError = false;
-
- for (const apiPath of apiPaths) {
- try {
- console.log(`尝试从 ${apiPath} 获取文档`);
- const response = await fetch(apiPath, {
- credentials: 'same-origin',
- headers: {
- 'X-Requested-With': 'XMLHttpRequest'
- }
- });
-
- // 只有明确401错误才认定为会话过期
- if (response.status === 401) {
- console.warn(`API ${apiPath} 返回401未授权`);
- authError = true;
- continue;
- }
-
- if (response.ok) {
- docResponse = response;
- console.log(`成功从 ${apiPath} 获取文档`);
- break;
- }
- } catch (pathError) {
- console.warn(`从 ${apiPath} 获取文档失败:`, pathError);
- }
- }
-
- // 处理认证错误
- if (authError && !docResponse) {
- core.showAlert('未登录或会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- if (docResponse && docResponse.ok) {
- currentDocument = await docResponse.json();
- console.log('获取到文档详情:', currentDocument);
-
- // 确保文档包含必要的时间字段
- if (!currentDocument.createdAt && currentDocument.updatedAt) {
- // 如果没有创建时间但有更新时间,使用更新时间
- currentDocument.createdAt = currentDocument.updatedAt;
- } else if (!currentDocument.createdAt) {
- // 如果都没有,使用当前时间
- currentDocument.createdAt = new Date().toISOString();
- }
-
- if (!currentDocument.updatedAt) {
- // 如果没有更新时间,使用创建时间
- currentDocument.updatedAt = currentDocument.createdAt;
- }
-
- // 将获取到的文档添加到文档列表中
- const existingIndex = documents.findIndex(d => d.id === id);
- if (existingIndex >= 0) {
- documents[existingIndex] = currentDocument;
- } else {
- documents.push(currentDocument);
- }
- } else {
- throw new Error('所有API路径都无法获取文档');
- }
- } catch (apiError) {
- console.error('从API获取文档详情失败:', apiError);
- core.showAlert('获取文档详情失败: ' + apiError.message, 'error');
- }
- }
-
- // 如果仍然没有找到文档,显示错误
- if (!currentDocument) {
- core.showAlert('未找到指定的文档', 'error');
- return;
- }
-
- // 显示编辑器界面并设置内容
- this.showEditor();
-
- // 确保编辑器已初始化
- if (!editorMd) {
- await new Promise(resolve => setTimeout(resolve, 100));
- this.initEditor();
- await new Promise(resolve => setTimeout(resolve, 500));
- }
-
- // 设置文档内容
- if (editorMd) {
- document.getElementById('documentTitle').value = currentDocument.title || '';
-
- if (currentDocument.content) {
- console.log(`设置文档内容,长度: ${currentDocument.content.length}`);
- editorMd.setMarkdown(currentDocument.content);
- } else {
- console.log('文档内容为空,尝试额外获取内容');
-
- // 如果文档内容为空,尝试额外获取内容
- try {
- const contentResponse = await fetch(`/api/documents/${id}/content`, {
- credentials: 'same-origin',
- headers: {
- 'X-Requested-With': 'XMLHttpRequest'
- }
- });
-
- // 只有明确401错误才提示重新登录
- if (contentResponse.status === 401) {
- core.showAlert('会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- if (contentResponse.ok) {
- const contentData = await contentResponse.json();
- if (contentData.content) {
- currentDocument.content = contentData.content;
- editorMd.setMarkdown(contentData.content);
- console.log('成功获取额外内容');
- }
- }
- } catch (contentError) {
- console.warn('获取额外内容失败:', contentError);
- }
-
- // 如果仍然没有内容,设置为空
- if (!currentDocument.content) {
- editorMd.setMarkdown('');
- }
- }
- } else {
- console.error('编辑器初始化失败,无法设置内容');
- core.showAlert('编辑器初始化失败,请刷新页面重试', 'error');
- }
- } catch (error) {
- console.error('编辑文档时出错:', error);
- core.showAlert('编辑文档失败: ' + error.message, 'error');
- } finally {
- core.hideLoading();
- }
- },
- // 查看文档
- viewDocument: function(id) {
- const doc = documents.find(doc => doc.id === id);
- if (!doc) {
- core.showAlert('未找到指定的文档', 'error');
- return;
- }
- Swal.fire({
- title: doc.title,
- html: `<div class="document-preview">${marked.parse(doc.content || '')}</div>`,
- width: '70%',
- showCloseButton: true,
- showConfirmButton: false,
- customClass: {
- container: 'document-preview-container',
- popup: 'document-preview-popup',
- content: 'document-preview-content'
- }
- });
- },
- // 删除文档
- deleteDocument: async function(id) {
- Swal.fire({
- title: '确定要删除此文档吗?',
- text: "此操作无法撤销!",
- icon: 'warning',
- showCancelButton: true,
- confirmButtonColor: '#d33',
- cancelButtonColor: '#3085d6',
- confirmButtonText: '是,删除它',
- cancelButtonText: '取消'
- }).then(async (result) => {
- if (result.isConfirmed) {
- try {
- console.log(`尝试删除文档: ${id}`);
-
- // 检查会话状态
- const sessionResponse = await fetch('/api/check-session', {
- headers: { 'Cache-Control': 'no-cache' }
- });
-
- if (sessionResponse.status === 401) {
- // 会话已过期,提示用户并重定向到登录
- core.showAlert('您的会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- // 使用正确的API路径删除
- const response = await fetch(`/api/documents/${id}`, {
- method: 'DELETE',
- headers: {
- 'Content-Type': 'application/json',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin' // 确保发送cookie
- });
-
- if (response.status === 401) {
- // 处理未授权错误
- core.showAlert('未登录或会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- if (!response.ok) {
- const errorData = await response.json();
- throw new Error(errorData.error || '删除文档失败');
- }
-
- console.log('文档删除成功响应:', await response.json());
- core.showAlert('文档已成功删除', 'success');
- await this.loadDocuments(); // 重新加载文档列表
- } catch (error) {
- console.error('删除文档失败:', error);
- core.showAlert('删除文档失败: ' + error.message, 'error');
- }
- }
- });
- },
- // 切换文档发布状态
- togglePublish: async function(id) {
- try {
- const doc = documents.find(d => d.id === id);
- if (!doc) {
- throw new Error('找不到指定文档');
- }
-
- // 添加加载指示
- core.showLoading();
-
- // 检查会话状态
- const sessionResponse = await fetch('/api/check-session', {
- headers: { 'Cache-Control': 'no-cache' }
- });
-
- if (sessionResponse.status === 401) {
- // 会话已过期,提示用户并重定向到登录
- core.showAlert('您的会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- console.log(`尝试切换文档 ${id} 的发布状态,当前状态:`, doc.published);
-
- // 构建更新请求数据
- const updateData = {
- id: doc.id,
- title: doc.title,
- published: !doc.published // 切换发布状态
- };
-
- // 使用正确的API端点进行更新
- const response = await fetch(`/api/documentation/toggle-publish/${id}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- credentials: 'same-origin', // 确保发送cookie
- body: JSON.stringify(updateData)
- });
-
- if (response.status === 401) {
- // 处理未授权错误
- core.showAlert('未登录或会话已过期,请重新登录', 'warning');
- setTimeout(() => {
- localStorage.removeItem('isLoggedIn');
- window.location.reload();
- }, 1500);
- return;
- }
-
- if (!response.ok) {
- const errorData = await response.json();
- throw new Error(errorData.error || '更新文档状态失败');
- }
-
- // 更新成功
- const updatedDoc = await response.json();
- console.log('文档状态更新响应:', updatedDoc);
-
- // 更新本地文档列表
- const docIndex = documents.findIndex(d => d.id === id);
- if (docIndex >= 0) {
- documents[docIndex].published = updatedDoc.published;
- this.renderDocumentList();
- }
-
- core.showAlert('文档状态已更新', 'success');
- } catch (error) {
- console.error('更改发布状态失败:', error);
- core.showAlert('更改发布状态失败: ' + error.message, 'error');
- } finally {
- core.hideLoading();
- }
- }
- };
- // 全局公开文档管理模块
- window.documentManager = documentManager;
- /**
- * 显示指定文档的内容
- * @param {string} docId 文档ID
- */
- async function showDocument(docId) {
- try {
- console.log('正在获取文档内容,ID:', docId);
-
- // 显示加载状态
- const documentContent = document.getElementById('documentContent');
- if (documentContent) {
- documentContent.innerHTML = '<div class="loading-container"><i class="fas fa-spinner fa-spin"></i> 正在加载文档内容...</div>';
- }
-
- // 获取文档内容
- const response = await fetch(`/api/documentation/${docId}`);
- if (!response.ok) {
- throw new Error(`获取文档内容失败,状态码: ${response.status}`);
- }
-
- const doc = await response.json();
- console.log('获取到文档:', doc);
-
- // 更新文档内容区域
- if (documentContent) {
- if (doc.content) {
- // 使用marked渲染markdown内容
- documentContent.innerHTML = `
- <h1>${doc.title || '无标题'}</h1>
- ${doc.lastUpdated ? `<div class="doc-meta">最后更新: ${new Date(doc.lastUpdated).toLocaleDateString('zh-CN')}</div>` : ''}
- <div class="doc-content">${window.marked ? marked.parse(doc.content) : doc.content}</div>
- `;
- } else {
- documentContent.innerHTML = `
- <h1>${doc.title || '无标题'}</h1>
- <div class="empty-content">
- <i class="fas fa-file-alt fa-3x"></i>
- <p>该文档暂无内容</p>
- </div>
- `;
- }
- } else {
- console.error('找不到文档内容容器,ID: documentContent');
- }
-
- // 高亮当前选中的文档
- highlightSelectedDocument(docId);
- } catch (error) {
- console.error('获取文档内容失败:', error);
-
- // 显示错误信息
- const documentContent = document.getElementById('documentContent');
- if (documentContent) {
- documentContent.innerHTML = `
- <div class="error-container">
- <i class="fas fa-exclamation-triangle fa-3x"></i>
- <h2>加载失败</h2>
- <p>无法获取文档内容: ${error.message}</p>
- <button class="btn btn-retry" onclick="showDocument('${docId}')">重试</button>
- </div>
- `;
- }
- }
- }
- /**
- * 高亮选中的文档
- * @param {string} docId 文档ID
- */
- function highlightSelectedDocument(docId) {
- // 移除所有高亮
- const docLinks = document.querySelectorAll('.doc-list .doc-item');
- docLinks.forEach(link => link.classList.remove('active'));
-
- // 添加当前高亮
- const selectedLink = document.querySelector(`.doc-list .doc-item[data-id="${docId}"]`);
- if (selectedLink) {
- selectedLink.classList.add('active');
- // 确保选中项可见
- selectedLink.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
- }
- }
|