/** * 资源分类管理相关功能 */ let categories = []; // 所有分类 let parentCategories = []; // 父分类选项 let categoryCurrentPage = 1; let categoryPageSize = 10; let categoryTotalPages = 0; let categoryTotalCount = 0; document.addEventListener('DOMContentLoaded', function () { // 加载分类列表 loadCategories(); // 分类级别变更事件 document.getElementById('category-level').addEventListener('change', function () { const level = parseInt(this.value); const parentCategoryGroup = document.getElementById('parent-category-group'); const versionHelpText = document.getElementById('version-help-text'); if (level > 1) { // 二级或三级分类,显示父分类选择框 parentCategoryGroup.style.display = 'block'; // 加载父分类选项 loadParentCategoryOptions(level); if (level === 2) { // 二级分类时禁用版本选择并显示父分类版本 setVersionCheckboxDisabled(true); versionHelpText.textContent = '二级分类自动继承父分类的版本'; // 如果已经选择了父分类,立即显示父分类的版本 const parentId = document.getElementById('parent-category').value; if (parentId) { setVersionFromParent(parentId); } } else { // 三级分类时启用版本选择 setVersionCheckboxDisabled(false); versionHelpText.textContent = '选择要关联的版本'; } } else { // 一级分类,隐藏父分类选择框 parentCategoryGroup.style.display = 'none'; setVersionCheckboxDisabled(false); versionHelpText.textContent = '选择要关联的版本'; } }); // 保存分类按钮点击事件 document.getElementById('btn-save-category').addEventListener('click', saveCategory); // 父分类变更事件 document.getElementById('parent-category').addEventListener('change', function() { const level = parseInt(document.getElementById('category-level').value); if (level === 2) { // 二级分类时,根据父分类自动设置版本 const parentId = this.value; if (parentId) { setVersionFromParent(parentId); } } }); }); /** * 根据父分类设置版本(支持多版本) * @param {number} parentId - 父分类ID */ async function setVersionFromParent(parentId) { try { const params = { "token": localStorage.getItem('token') }; // 获取父分类详情 const parentCategory = await Api.get(`/api/categories/${parentId}`, params); // 先清空所有checkbox const boxes = document.querySelectorAll('#category-versions-checkbox-group input[type=checkbox]'); boxes.forEach(cb => cb.checked = false); // 设置父分类的版本 if (parentCategory && parentCategory.versionIds && Array.isArray(parentCategory.versionIds)) { parentCategory.versionIds.forEach(id => { const cb = document.getElementById('version-checkbox-' + id); if (cb) cb.checked = true; }); } } catch (error) { console.error('获取父分类版本失败:', error); // 出错时清空所有checkbox const boxes = document.querySelectorAll('#category-versions-checkbox-group input[type=checkbox]'); boxes.forEach(cb => cb.checked = false); } } /** * 加载分类列表 */ async function loadCategories() { try { const params = { "token": localStorage.getItem('token'), page: categoryCurrentPage, pageSize: categoryPageSize }; const response = await Api.get('/api/categories', params); categories = Array.isArray(response.items) ? response.items : (Array.isArray(response) ? response : []); categoryTotalCount = response.total || categories.length; categoryTotalPages = Math.ceil(categoryTotalCount / categoryPageSize); renderCategoryList(categories); renderCategoryPagination(); } catch (error) { showToast(error.message, 'danger'); } } /** * 渲染分类列表 * @param {Array} categories - 分类列表 */ function renderCategoryList(categories) { const categoryList = document.getElementById('category-list'); categoryList.innerHTML = ''; // 扁平化分类树 const flatCategories = flattenCategories(categories); if (flatCategories.length === 0) { categoryList.innerHTML = '暂无数据'; // 更新总数 const totalCountEl = document.getElementById('category-total-count'); if (totalCountEl) totalCountEl.textContent = categoryTotalCount; return; } // 渲染分类列表 flatCategories.forEach(category => { const tr = document.createElement('tr'); // 根据级别添加缩进 const namePrefix = ' '.repeat((category.level - 1) * 4); const levelName = ['一级', '二级', '三级'][category.level - 1] || ''; // 显示所有版本名称 const versionInfo = (category.versionNames && category.versionNames.length > 0) ? category.versionNames.join(', ') : '-'; tr.innerHTML = ` ${category.id} ${namePrefix}${category.name} ${levelName}分类 ${category.parentName || '-'} ${versionInfo} ${category.description || '-'} ${formatDateTime(category.createTime)} `; categoryList.appendChild(tr); }); // 更新总数 const totalCountEl = document.getElementById('category-total-count'); if (totalCountEl) totalCountEl.textContent = categoryTotalCount; } /** * 扁平化分类树,并添加父分类名称 * @param {Array} categories - 分类树 * @param {Object} parent - 父分类 * @returns {Array} - 扁平化的分类列表 */ function flattenCategories(categories, parent = null) { let result = []; categories.forEach(category => { // 添加父分类名称 const categoryWithParent = { ...category, parentName: parent ? parent.name : null }; result.push(categoryWithParent); // 递归处理子分类 if (category.children && category.children.length > 0) { result = result.concat(flattenCategories(category.children, category)); } }); return result; } /** * 加载父分类选项 * @param {number} level - 当前分类级别 */ function loadParentCategoryOptions(level) { const parentCategorySelect = document.getElementById('parent-category'); parentCategorySelect.innerHTML = ''; // 获取可选的父分类(级别小于当前级别的分类) parentCategories = []; // 扁平化分类树 const flatCategories = flattenCategories(categories); // 筛选可作为父分类的分类 parentCategories = flatCategories.filter(category => category.level < level); // 渲染父分类选项 parentCategories.forEach(category => { const option = document.createElement('option'); option.value = category.id; // 根据级别添加缩进 const namePrefix = ' '.repeat(category.level - 1); option.textContent = `${namePrefix}${category.name}`; parentCategorySelect.appendChild(option); }); } /** * 加载版本选项(渲染checkbox组) */ async function loadVersionOptions() { try { const params = { "token": localStorage.getItem('token') }; const response = await Api.get('/api/versions', params); const group = document.getElementById('category-versions-checkbox-group'); group.innerHTML = ''; const versions = response.items || response; versions.forEach(version => { const div = document.createElement('div'); div.className = 'form-check form-check-inline'; div.innerHTML = ` `; group.appendChild(div); }); } catch (error) { console.error('加载版本选项失败:', error); } } /** * 设置checkbox组禁用/启用 * @param {boolean} disabled - 是否禁用 */ function setVersionCheckboxDisabled(disabled) { const boxes = document.querySelectorAll('#category-versions-checkbox-group input[type=checkbox]'); boxes.forEach(cb => cb.disabled = disabled); } /** * 打开新增分类模态框 */ function openAddCategoryModal() { // 重置表单 document.getElementById('category-form').reset(); document.getElementById('category-id').value = ''; document.getElementById('parent-category-group').style.display = 'none'; // 重置版本选择状态 setVersionCheckboxDisabled(false); document.getElementById('version-help-text').textContent = '选择要关联的版本'; // 设置模态框标题 document.getElementById('categoryModalLabel').textContent = '新增分类'; // 加载版本选项 loadVersionOptions(); // 显示模态框 const categoryModal = new bootstrap.Modal(document.getElementById('categoryModal')); categoryModal.show(); } /** * 编辑分类 * @param {number} id - 分类ID */ async function editCategory(id) { try { const params = { "token": localStorage.getItem('token') }; // 获取分类详情 const category = await Api.get(`/api/categories/${id}`, params); // 填充表单 document.getElementById('category-id').value = category.id; document.getElementById('category-name').value = category.name; document.getElementById('category-level').value = category.level; document.getElementById('category-description').value = category.description || ''; // 处理父分类 if (category.level > 1) { document.getElementById('parent-category-group').style.display = 'block'; loadParentCategoryOptions(category.level); if (category.parentId) { document.getElementById('parent-category').value = category.parentId; } // 二级分类时显示父分类版本并禁用修改 if (category.level === 2) { document.getElementById('version-help-text').textContent = '二级分类自动继承父分类的版本'; } else { document.getElementById('version-help-text').textContent = '选择要关联的版本'; } } else { document.getElementById('parent-category-group').style.display = 'none'; document.getElementById('version-help-text').textContent = '选择要关联的版本'; } // 先加载版本选项 await loadVersionOptions(); // 然后处理版本选择 if (category.level === 2) { // 二级分类:显示父分类版本并禁用修改 if (category.parentId) { await setVersionFromParent(category.parentId); } setVersionCheckboxDisabled(true); } else { // 非二级分类:显示当前版本 if (category.versionIds && Array.isArray(category.versionIds)) { category.versionIds.forEach(id => { const cb = document.getElementById('version-checkbox-' + id); if (cb) cb.checked = true; }); } setVersionCheckboxDisabled(false); } // 设置模态框标题 document.getElementById('categoryModalLabel').textContent = '编辑分类'; // 显示模态框 const categoryModal = new bootstrap.Modal(document.getElementById('categoryModal')); categoryModal.show(); } catch (error) { showToast(error.message, 'danger'); } } async function debugResponse(response) { try { if (response.ok) { console.log('debugResponse:', response.json()); } else { const error = await response.text(); console.log('debugResponse:', error); } } catch (e) { console.log('debugResponse:', e.message); } } /** * 保存分类 */ async function saveCategory() { try { // 获取表单数据 const categoryData = { name: document.getElementById('category-name').value.trim(), level: parseInt(document.getElementById('category-level').value), description: document.getElementById('category-description').value.trim(), versionId: null // 新增字段 }; // 获取父分类ID const parentCategory = document.getElementById('parent-category'); if (parentCategory.style.display !== 'none' && parentCategory.value) { categoryData.parentId = parseInt(parentCategory.value); } // 获取多选版本ID(checkbox) let selectedVersionIds = Array.from(document.querySelectorAll('#category-versions-checkbox-group input[type=checkbox]:checked')).map(cb => parseInt(cb.value)); // 二级分类时,如果禁用,则继承父级 if (categoryData.level === 2) { const parentId = categoryData.parentId; if (parentId) { try { const parentParams = { "token": localStorage.getItem('token') }; const parentCategory = await Api.get(`/api/categories/${parentId}`, parentParams); if (parentCategory && parentCategory.versionIds && Array.isArray(parentCategory.versionIds)) { selectedVersionIds = parentCategory.versionIds; } else { selectedVersionIds = []; } } catch (error) { selectedVersionIds = []; } } else { selectedVersionIds = []; } } // 验证表单 if (!categoryData.name) { showToast('请输入分类名称', 'danger'); return; } // 检查同级分类名称是否重复(排除当前编辑的分类) const currentId = document.getElementById('category-id').value; const sameLevelCategories = categories.filter(c => c.level === categoryData.level); // const isNameDuplicate = sameLevelCategories.some(c => // c.name === categoryData.name && // c.id !== parseInt(currentId) // ); // if (isNameDuplicate) { // showToast('同级分类名称不能重复', 'danger'); // return; // } // 检查二级分类名称不能与一级分类重名 // if (categoryData.level === 2) { // const isDuplicateWithLevel1 = categories.some(c => c.level === 1 && c.name === categoryData.name); // if (isDuplicateWithLevel1) { // showToast('二级分类名称不能与一级分类重名', 'danger'); // return; // } // } // 构建请求数据 const data = { name: categoryData.name, level: categoryData.level, description: categoryData.description || null, versionIds: selectedVersionIds }; // 如果是二级或三级分类,添加父分类ID if (categoryData.level > 1) { const parentId = categoryData.parentId; if (!parentId) { showToast('请选择父分类', 'danger'); return; } data.parentId = parentId; } // 发送请求 if (document.getElementById('category-id').value) { // 更新分类 const response = await Api.put(`/api/categories/${document.getElementById('category-id').value}`, data); debugResponse(response); showToast('分类更新成功', 'success'); } else { // 新增分类 const response = await Api.post('/api/categories', data); debugResponse(response); showToast('分类创建成功', 'success'); } // 关闭模态框 const categoryModal = bootstrap.Modal.getInstance(document.getElementById('categoryModal')); categoryModal.hide(); // 重新加载分类列表 loadCategories(); } catch (error) { showToast(error.message, 'danger'); } } /** * 删除分类 * @param {number} id - 分类ID * @param {string} name - 分类名称 */ function deleteCategory(id, name) { // 设置确认删除模态框内容 document.getElementById('delete-type').textContent = `分类"${name}"`; // 设置确认删除按钮点击事件 document.getElementById('btn-confirm-delete').onclick = async function () { try { // 发送删除请求 await Api.delete(`/api/categories/${id}`); // 关闭确认删除模态框 const confirmDeleteModal = bootstrap.Modal.getInstance(document.getElementById('confirmDeleteModal')); confirmDeleteModal.hide(); // 显示成功消息 showToast('分类删除成功', 'success'); // 重新加载分类列表 loadCategories(); } catch (error) { showToast(error.message, 'danger'); } }; // 显示确认删除模态框 const confirmDeleteModal = new bootstrap.Modal(document.getElementById('confirmDeleteModal')); confirmDeleteModal.show(); } /** * 获取所有分类的扁平列表(用于资源管理中的分类选择) * @returns {Array} - 分类列表 */ function getAllCategories() { return flattenCategories(categories); } function renderCategoryPagination() { const pagination = document.getElementById('category-pagination'); if (!pagination) return; pagination.innerHTML = ''; if (categoryTotalPages <= 1) return; // 上一页 const prevLi = document.createElement('li'); prevLi.className = `page-item ${categoryCurrentPage === 1 ? 'disabled' : ''}`; const prevLink = document.createElement('a'); prevLink.className = 'page-link'; prevLink.href = '#'; prevLink.setAttribute('aria-label', '上一页'); prevLink.innerHTML = ''; if (categoryCurrentPage > 1) { prevLink.addEventListener('click', function (event) { event.preventDefault(); categoryCurrentPage--; loadCategories(); }); } prevLi.appendChild(prevLink); pagination.appendChild(prevLi); // 页码 const startPage = Math.max(1, categoryCurrentPage - 2); const endPage = Math.min(categoryTotalPages, startPage + 4); for (let i = startPage; i <= endPage; i++) { const pageLi = document.createElement('li'); pageLi.className = `page-item ${i === categoryCurrentPage ? 'active' : ''}`; const pageLink = document.createElement('a'); pageLink.className = 'page-link'; pageLink.href = '#'; pageLink.textContent = i; if (i !== categoryCurrentPage) { pageLink.addEventListener('click', function (event) { event.preventDefault(); categoryCurrentPage = i; loadCategories(); }); } pageLi.appendChild(pageLink); pagination.appendChild(pageLi); } // 下一页 const nextLi = document.createElement('li'); nextLi.className = `page-item ${categoryCurrentPage === categoryTotalPages ? 'disabled' : ''}`; const nextLink = document.createElement('a'); nextLink.className = 'page-link'; nextLink.href = '#'; nextLink.setAttribute('aria-label', '下一页'); nextLink.innerHTML = ''; if (categoryCurrentPage < categoryTotalPages) { nextLink.addEventListener('click', function (event) { event.preventDefault(); categoryCurrentPage++; loadCategories(); }); } nextLi.appendChild(nextLink); pagination.appendChild(nextLi); }