Files
wushu/ht/inc/js.js
2026-03-30 02:35:31 +08:00

459 lines
15 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 公共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 += '<a href="javascript:;" class="page-item first' + firstDisabled + '" data-page="1">首页</a>';
// 上一页按钮
var prevDisabled = currentPage === 1 ? ' disabled' : '';
var prevPage = Math.max(1, currentPage - 1);
paginationHtml += '<a href="javascript:;" class="page-item prev' + prevDisabled + '" data-page="' + prevPage + '">上一页</a>';
// 页码下拉选择
paginationHtml += '<select class="page-select">';
for (var i = 1; i <= totalPages; i++) {
var selected = i === currentPage ? ' selected' : '';
paginationHtml += '<option value="' + i + '"' + selected + '>第 ' + i + ' 页</option>';
}
paginationHtml += '</select>';
// 下一页按钮
var nextDisabled = currentPage === totalPages ? ' disabled' : '';
var nextPage = Math.min(totalPages, currentPage + 1);
paginationHtml += '<a href="javascript:;" class="page-item next' + nextDisabled + '" data-page="' + nextPage + '">下一页</a>';
// 尾页按钮
var lastDisabled = currentPage === totalPages ? ' disabled' : '';
paginationHtml += '<a href="javascript:;" class="page-item last' + lastDisabled + '" data-page="' + totalPages + '">尾页</a>';
// 设置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 = '<h3>' + title + '</h3><span class="mask-close">&times;</span>';
// 创建内容区
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();
}
});
}