/** * 公共JavaScript函数 */ /** * Ajax通信函数 * @param {string} url - 请求地址 * @param {Object} data - 请求数据 * @param {Function} callback - 成功回调函数 * @param {Function} errorCallback - 错误回调函数 * @param {string} method - 请求方法(GET或POST) */ function ajaxRequest(url, data, callback, errorCallback, method) { // 默认使用POST方法,除非act为get if (!method) { method = (data && data.act === 'get') ? 'GET' : 'POST'; } // 创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); // 准备发送请求 xhr.open(method, url, true); // 设置请求头 xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); if (method === 'POST') { xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } // 处理响应 xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { var response; try { response = JSON.parse(xhr.responseText); if (callback && typeof callback === 'function') { callback(response); } } catch (e) { console.error('解析JSON失败:', e); if (errorCallback && typeof errorCallback === 'function') { errorCallback('解析响应失败'); } } } else { console.error('请求失败,状态码:', xhr.status); if (errorCallback && typeof errorCallback === 'function') { errorCallback('请求失败,状态码: ' + xhr.status); } } } }; // 处理请求超时 xhr.ontimeout = function() { console.error('请求超时'); if (errorCallback && typeof errorCallback === 'function') { errorCallback('请求超时'); } }; // 处理网络错误 xhr.onerror = function() { console.error('网络错误'); if (errorCallback && typeof errorCallback === 'function') { errorCallback('网络错误'); } }; // 发送请求 if (method === 'POST' && data) { // 将对象转换为查询字符串 var params = Object.keys(data).map(function(key) { return encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); }).join('&'); xhr.send(params); } else if (method === 'GET' && data) { // 将查询参数添加到URL var queryString = Object.keys(data).map(function(key) { return encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); }).join('&'); var separator = url.indexOf('?') !== -1 ? '&' : '?'; xhr.send(); } else { xhr.send(); } } /** * 分页显示函数 * @param {string} containerId - 分页容器ID * @param {number} currentPage - 当前页码 * @param {number} totalPages - 总页数 * @param {Function} callback - 页码点击回调函数 */ function pagination(containerId, currentPage, totalPages, callback) { var container = document.getElementById(containerId); if (!container) return; // 清空容器 container.innerHTML = ''; // 如果没有数据或只有一页,不显示分页 if (totalPages <= 1) { container.classList.add('disabled'); return; } container.classList.remove('disabled'); // 创建分页元素 var paginationHtml = ''; // 首页按钮 var firstDisabled = currentPage === 1 ? ' disabled' : ''; paginationHtml += '首页'; // 上一页按钮 var prevDisabled = currentPage === 1 ? ' disabled' : ''; var prevPage = Math.max(1, currentPage - 1); paginationHtml += '上一页'; // 页码下拉选择 paginationHtml += ''; // 下一页按钮 var nextDisabled = currentPage === totalPages ? ' disabled' : ''; var nextPage = Math.min(totalPages, currentPage + 1); paginationHtml += '下一页'; // 尾页按钮 var lastDisabled = currentPage === totalPages ? ' disabled' : ''; paginationHtml += '尾页'; // 设置HTML container.innerHTML = paginationHtml; // 绑定事件 // 点击页码按钮 var pageItems = container.querySelectorAll('.page-item'); for (var j = 0; j < pageItems.length; j++) { var item = pageItems[j]; if (!item.classList.contains('disabled')) { item.addEventListener('click', function() { var page = parseInt(this.getAttribute('data-page')); if (callback && typeof callback === 'function') { callback(page); } }); } } // 下拉选择页码 var pageSelect = container.querySelector('.page-select'); if (pageSelect) { pageSelect.addEventListener('change', function() { var page = parseInt(this.value); if (callback && typeof callback === 'function') { callback(page); } }); } } /** * 表格排序函数 * @param {string} tableId - 表格ID * @param {number} colIndex - 排序列索引 * @param {string} type - 排序类型(string, number, date) */ function sortTable(tableId, colIndex, type) { var table = document.getElementById(tableId); if (!table) return; var tbody = table.getElementsByTagName('tbody')[0]; var rows = tbody.getElementsByTagName('tr'); var sortedRows = Array.prototype.slice.call(rows, 0); // 确定排序方向 var sortDirection = 1; // 1为升序,-1为降序 if (table.getAttribute('data-sort-col') == colIndex) { sortDirection = table.getAttribute('data-sort-dir') == 'asc' ? -1 : 1; } // 保存排序信息 table.setAttribute('data-sort-col', colIndex); table.setAttribute('data-sort-dir', sortDirection == 1 ? 'asc' : 'desc'); // 排序 sortedRows.sort(function(a, b) { var cellA = a.cells[colIndex].textContent.trim(); var cellB = b.cells[colIndex].textContent.trim(); if (type === 'number') { return sortDirection * (parseFloat(cellA) - parseFloat(cellB)); } else if (type === 'date') { var dateA = new Date(cellA); var dateB = new Date(cellB); return sortDirection * (dateA - dateB); } else { return sortDirection * cellA.localeCompare(cellB); } }); // 更新表格显示 for (var i = 0; i < sortedRows.length; i++) { tbody.appendChild(sortedRows[i]); } // 更新表格头部排序指示器 var headers = table.getElementsByTagName('th'); for (var j = 0; j < headers.length; j++) { headers[j].classList.remove('sort-asc', 'sort-desc'); } if (headers[colIndex]) { headers[colIndex].classList.add(sortDirection == 1 ? 'sort-asc' : 'sort-desc'); } } /** * 显示遮罩层 * @param {string} title - 标题 * @param {string} content - 内容 * @param {Array} buttons - 按钮配置数组,格式:[{text: '按钮文字', callback: 回调函数, class: 'btn-class'}] */ function showMask(title, content, buttons) { // 移除已存在的遮罩 closeMask(); // 创建遮罩层 var mask = document.createElement('div'); mask.className = 'mask-container'; // 创建对话框 var dialog = document.createElement('div'); dialog.className = 'mask-dialog'; // 创建标题栏 var titleBar = document.createElement('div'); titleBar.className = 'mask-title'; titleBar.innerHTML = '

' + title + '

×'; // 创建内容区 var contentArea = document.createElement('div'); contentArea.className = 'mask-content'; contentArea.innerHTML = content; // 创建按钮区 var buttonArea = document.createElement('div'); buttonArea.className = 'mask-buttons'; if (buttons && buttons.length > 0) { buttons.forEach(function(btn) { var button = document.createElement('button'); button.className = 'mask-button ' + (btn.class || ''); button.textContent = btn.text; if (btn.callback && typeof btn.callback === 'function') { button.addEventListener('click', function() { btn.callback(); }); } buttonArea.appendChild(button); }); } // 组装对话框 dialog.appendChild(titleBar); dialog.appendChild(contentArea); dialog.appendChild(buttonArea); mask.appendChild(dialog); // 添加到页面 document.body.appendChild(mask); // 绑定关闭事件 var closeBtn = mask.querySelector('.mask-close'); if (closeBtn) { closeBtn.addEventListener('click', closeMask); } // 绑定点击遮罩层关闭 mask.addEventListener('click', function(e) { if (e.target === mask) { closeMask(); } }); // 禁止页面滚动 document.body.style.overflow = 'hidden'; // 调整内容区域最大高度 var contentMaxHeight = window.innerHeight * 0.7; contentArea.style.maxHeight = contentMaxHeight + 'px'; } /** * 关闭遮罩层 */ function closeMask() { var mask = document.querySelector('.mask-container'); if (mask) { mask.parentNode.removeChild(mask); } // 恢复页面滚动 document.body.style.overflow = ''; } /** * 输入提示功能 * @param {string} inputId - 输入框ID * @param {string} url - 获取提示数据的URL * @param {Object} params - 附加参数 * @param {Function} callback - 选择项后的回调函数 */ function searchSuggest(inputId, url, params, callback) { var input = document.getElementById(inputId); if (!input) return; // 创建提示容器 var suggestContainer = document.createElement('div'); suggestContainer.className = 'suggest-container'; suggestContainer.style.display = 'none'; input.parentNode.appendChild(suggestContainer); // 定位提示容器 function positionSuggest() { var rect = input.getBoundingClientRect(); suggestContainer.style.top = (rect.bottom + window.scrollY) + 'px'; suggestContainer.style.left = (rect.left + window.scrollX) + 'px'; suggestContainer.style.width = rect.width + 'px'; } // 暂存上一次请求的关键词 var lastKeyword = ''; var debounceTimer = null; // 处理输入事件 input.addEventListener('input', function() { var keyword = input.value.trim(); // 清除上一次的定时器 if (debounceTimer) { clearTimeout(debounceTimer); } // 如果关键词为空,隐藏提示 if (!keyword) { suggestContainer.style.display = 'none'; return; } // 如果关键词与上一次相同,不重新请求 if (keyword === lastKeyword) { return; } // 设置300ms的防抖定时器 debounceTimer = setTimeout(function() { lastKeyword = keyword; // 准备请求参数 var requestParams = Object.assign({}, params || {}, { keyword: keyword }); // 发送请求获取提示数据 ajaxRequest(url, requestParams, function(response) { if (response.code === 0 && Array.isArray(response.data) && response.data.length > 0) { // 清空容器 suggestContainer.innerHTML = ''; // 添加关闭按钮 var closeButton = document.createElement('div'); closeButton.className = 'suggest-close'; closeButton.textContent = '关闭'; closeButton.addEventListener('click', function() { suggestContainer.style.display = 'none'; }); suggestContainer.appendChild(closeButton); // 限制最多显示10条 var maxItems = Math.min(10, response.data.length); // 添加提示项 for (var i = 0; i < maxItems; i++) { var item = response.data[i]; var suggestionItem = document.createElement('div'); suggestionItem.className = 'suggest-item'; suggestionItem.textContent = item.text || item.name || item; suggestionItem.setAttribute('data-value', item.value || item.id || item); // 绑定点击事件 suggestionItem.addEventListener('click', function() { var value = this.getAttribute('data-value'); var text = this.textContent; // 设置输入框值 input.value = text; // 隐藏提示 suggestContainer.style.display = 'none'; // 触发回调 if (callback && typeof callback === 'function') { callback(value, text); } }); suggestContainer.appendChild(suggestionItem); } // 显示提示容器 positionSuggest(); suggestContainer.style.display = 'block'; } else { suggestContainer.style.display = 'none'; } }, function() { suggestContainer.style.display = 'none'; }); }, 300); }); // 点击输入框时,如果有数据则显示提示 input.addEventListener('click', function() { if (lastKeyword && suggestContainer.childElementCount > 1) { positionSuggest(); suggestContainer.style.display = 'block'; } }); // 点击页面其他区域隐藏提示 document.addEventListener('click', function(e) { if (e.target !== input && !suggestContainer.contains(e.target)) { suggestContainer.style.display = 'none'; } }); // 窗口调整大小时重新定位 window.addEventListener('resize', function() { if (suggestContainer.style.display === 'block') { positionSuggest(); } }); }