445 lines
11 KiB
JavaScript
Executable File
445 lines
11 KiB
JavaScript
Executable File
// 通用工具函数
|
|
|
|
// 显示通知消息
|
|
function showToast(message, type = 'info') {
|
|
// 创建通知元素
|
|
const toast = document.createElement('div');
|
|
toast.className = `toast fixed top-4 right-4 p-3 rounded-lg shadow-lg ${type === 'success' ? 'bg-green-500 text-white' : type === 'error' ? 'bg-red-500 text-white' : 'bg-blue-500 text-white'}`;
|
|
toast.innerHTML = message;
|
|
|
|
// 添加到页面
|
|
document.body.appendChild(toast);
|
|
|
|
// 3秒后自动消失
|
|
setTimeout(() => {
|
|
toast.style.opacity = '0';
|
|
toast.style.transition = 'opacity 0.5s ease';
|
|
setTimeout(() => {
|
|
document.body.removeChild(toast);
|
|
}, 500);
|
|
}, 3000);
|
|
}
|
|
|
|
// 格式化日期
|
|
function formatDate(date) {
|
|
return new Date(date).toLocaleString();
|
|
}
|
|
|
|
// 转换字节为可读格式
|
|
function formatBytes(bytes) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// 检查响应是否成功
|
|
function checkResponse(response) {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
return response;
|
|
}
|
|
|
|
// 生成随机字符串
|
|
function generateRandomString(length = 16) {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
let result = '';
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// 检查是否为有效的UUID
|
|
function isValidUUID(uuid) {
|
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
return uuidRegex.test(uuid);
|
|
}
|
|
|
|
// URL编码特殊字符
|
|
function urlEncodeParams(params) {
|
|
const encodedParams = {};
|
|
for (const key in params) {
|
|
encodedParams[key] = encodeURIComponent(params[key]);
|
|
}
|
|
return encodedParams;
|
|
}
|
|
|
|
// 将对象转换为查询字符串
|
|
function objectToQueryString(obj) {
|
|
return new URLSearchParams(obj).toString();
|
|
}
|
|
|
|
// 获取元素的DOM节点
|
|
function $(selector) {
|
|
return document.querySelector(selector);
|
|
}
|
|
|
|
// 显示元素
|
|
function showElement(element) {
|
|
element.style.display = 'block';
|
|
}
|
|
|
|
// 隐藏元素
|
|
function hideElement(element) {
|
|
element.style.display = 'none';
|
|
}
|
|
|
|
// 设置元素文本内容
|
|
function setTextContent(element, text) {
|
|
element.textContent = text;
|
|
}
|
|
|
|
// 获取元素文本内容
|
|
function getTextContent(element) {
|
|
return element.textContent;
|
|
}
|
|
|
|
// 添加事件监听器
|
|
function addEventListener(element, event, handler) {
|
|
element.addEventListener(event, handler);
|
|
}
|
|
|
|
// 移除事件监听器
|
|
function removeEventListener(element, event, handler) {
|
|
element.removeEventListener(event, handler);
|
|
}
|
|
|
|
// 滚动到页面顶部
|
|
function scrollToTop() {
|
|
window.scrollTo({
|
|
top: 0,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
|
|
// 滚动到元素
|
|
function scrollToElement(element) {
|
|
element.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'start'
|
|
});
|
|
}
|
|
|
|
// 创建DOM元素
|
|
function createElement(tagName, className = '', innerHTML = '') {
|
|
const element = document.createElement(tagName);
|
|
if (className) {
|
|
element.className = className;
|
|
}
|
|
if (innerHTML) {
|
|
element.innerHTML = innerHTML;
|
|
}
|
|
return element;
|
|
}
|
|
|
|
// 克隆DOM元素
|
|
function cloneElement(element) {
|
|
return element.cloneNode(true);
|
|
}
|
|
|
|
// 移除DOM元素
|
|
function removeElement(element) {
|
|
if (element && element.parentNode) {
|
|
element.parentNode.removeChild(element);
|
|
}
|
|
}
|
|
|
|
// 插入到DOM元素之前
|
|
function insertBefore(referenceNode, newNode) {
|
|
referenceNode.parentNode.insertBefore(newNode, referenceNode);
|
|
}
|
|
|
|
// 插入到DOM元素之后
|
|
function insertAfter(referenceNode, newNode) {
|
|
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
|
|
}
|
|
|
|
// 替换DOM元素
|
|
function replaceElement(oldNode, newNode) {
|
|
if (oldNode.parentNode) {
|
|
oldNode.parentNode.replaceChild(newNode, oldNode);
|
|
}
|
|
}
|
|
|
|
// 添加CSS类
|
|
function addClass(element, className) {
|
|
element.classList.add(className);
|
|
}
|
|
|
|
// 移除CSS类
|
|
function removeClass(element, className) {
|
|
element.classList.remove(className);
|
|
}
|
|
|
|
// 切换CSS类
|
|
function toggleClass(element, className) {
|
|
element.classList.toggle(className);
|
|
}
|
|
|
|
// 检查CSS类是否存在
|
|
function hasClass(element, className) {
|
|
return element.classList.contains(className);
|
|
}
|
|
|
|
// 设置CSS样式
|
|
function setStyle(element, style) {
|
|
for (const key in style) {
|
|
element.style[key] = style[key];
|
|
}
|
|
}
|
|
|
|
// 获取CSS样式
|
|
function getStyle(element, property) {
|
|
return window.getComputedStyle(element).getPropertyValue(property);
|
|
}
|
|
|
|
// 设置数据属性
|
|
function setData(element, key, value) {
|
|
element.dataset[key] = value;
|
|
}
|
|
|
|
// 获取数据属性
|
|
function getData(element, key) {
|
|
return element.dataset[key];
|
|
}
|
|
|
|
// 移除数据属性
|
|
function removeData(element, key) {
|
|
delete element.dataset[key];
|
|
}
|
|
|
|
// 获取或设置表单字段值
|
|
function getFieldValue(element) {
|
|
const type = element.type;
|
|
if (type === 'checkbox' || type === 'radio') {
|
|
return element.checked;
|
|
}
|
|
return element.value;
|
|
}
|
|
|
|
function setFieldValue(element, value) {
|
|
const type = element.type;
|
|
if (type === 'checkbox' || type === 'radio') {
|
|
element.checked = value;
|
|
} else {
|
|
element.value = value;
|
|
}
|
|
}
|
|
|
|
// 阻止事件冒泡
|
|
function stopEventPropagation(event) {
|
|
event.stopPropagation();
|
|
}
|
|
|
|
// 阻止事件默认行为
|
|
function preventEventDefault(event) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
// 检查元素是否在视口中
|
|
function isInViewport(element) {
|
|
const rect = element.getBoundingClientRect();
|
|
return (
|
|
rect.top >= 0 &&
|
|
rect.left >= 0 &&
|
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
);
|
|
}
|
|
|
|
// 观察元素变化
|
|
function observeElement(element, callback) {
|
|
const observer = new MutationObserver(callback);
|
|
observer.observe(element, {
|
|
attributes: true,
|
|
childList: true,
|
|
characterData: true,
|
|
subtree: true
|
|
});
|
|
|
|
return observer;
|
|
}
|
|
|
|
// 取消观察元素
|
|
function disconnectObserver(observer) {
|
|
if (observer) {
|
|
observer.disconnect();
|
|
}
|
|
}
|
|
|
|
// 加载外部CSS文件
|
|
function loadCSS(url) {
|
|
const link = document.createElement('link');
|
|
link.rel = 'stylesheet';
|
|
link.href = url;
|
|
document.head.appendChild(link);
|
|
}
|
|
|
|
// 加载外部JS文件
|
|
function loadJS(url, callback) {
|
|
const script = document.createElement('script');
|
|
script.src = url;
|
|
script.onload = callback;
|
|
document.head.appendChild(script);
|
|
}
|
|
|
|
// 获取浏览器窗口大小
|
|
function getWindowSize() {
|
|
return {
|
|
width: window.innerWidth,
|
|
height: window.innerHeight
|
|
};
|
|
}
|
|
|
|
// 监听窗口大小变化
|
|
function watchWindowSize(callback) {
|
|
window.addEventListener('resize', callback);
|
|
}
|
|
|
|
// 取消监听窗口大小变化
|
|
function unwatchWindowSize(callback) {
|
|
window.removeEventListener('resize', callback);
|
|
}
|
|
|
|
// 模拟点击
|
|
function simulateClick(element) {
|
|
const event = new MouseEvent('click', {
|
|
view: window,
|
|
bubbles: true,
|
|
cancelable: true
|
|
});
|
|
element.dispatchEvent(event);
|
|
}
|
|
|
|
// 创建并下载文件
|
|
function downloadFileBlob(blob, fileName) {
|
|
const url = window.URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.style.display = 'none';
|
|
a.href = url;
|
|
a.download = fileName;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
window.URL.revokeObjectURL(url);
|
|
document.body.removeChild(a);
|
|
}
|
|
|
|
// 复制文本到剪贴板
|
|
async function copyToClipboard(text) {
|
|
try {
|
|
await navigator.clipboard.writeText(text);
|
|
return true;
|
|
} catch (err) {
|
|
console.error('无法复制文本: ', err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 加载更多内容
|
|
function loadMoreContent(element, loadFn, params = {}) {
|
|
const loadMoreBtn = document.createElement('button');
|
|
loadMoreBtn.className = 'btn btn-primary w-full mt-4';
|
|
loadMoreBtn.textContent = '加载更多';
|
|
|
|
element.appendChild(loadMoreBtn);
|
|
|
|
loadMoreBtn.addEventListener('click', function() {
|
|
showLoadingModal();
|
|
loadFn(params)
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
if (data.status === 200) {
|
|
element.removeChild(loadMoreBtn);
|
|
// 处理加载的数据
|
|
// 这里需要根据具体需求实现
|
|
} else {
|
|
alert(`加载失败: ${data.message || '未知错误'}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('加载失败:', error);
|
|
alert('加载失败,请检查网络连接');
|
|
});
|
|
});
|
|
}
|
|
|
|
// 创建模态框
|
|
function createModal(title, content, footer = '') {
|
|
const modal = document.createElement('div');
|
|
modal.className = 'fixed top-0 left-0 w-full h-full bg-gray-900 bg-opacity-50 flex items-center justify-center';
|
|
modal.innerHTML = `
|
|
<div class="bg-white p-6 rounded-lg w-96 max-w-full">
|
|
<h2 class="text-2xl mb-4 text-center">${title}</h2>
|
|
<div class="mb-4">${content}</div>
|
|
${footer}
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(modal);
|
|
|
|
return modal;
|
|
}
|
|
|
|
// 关闭模态框
|
|
function closeModal(modal) {
|
|
if (modal && modal.parentNode) {
|
|
modal.parentNode.removeChild(modal);
|
|
}
|
|
}
|
|
|
|
// 创建确认框
|
|
function createConfirmModal(message, onConfirm, onCancel = null, title = '确认') {
|
|
const modal = createModal(title, message, `
|
|
<div class="flex justify-center gap-2">
|
|
<button id="confirmBtn" class="btn btn-primary">确认</button>
|
|
<button id="cancelBtn" class="btn btn-danger">取消</button>
|
|
</div>
|
|
`);
|
|
|
|
document.getElementById('confirmBtn').addEventListener('click', function() {
|
|
closeModal(modal);
|
|
if (typeof onConfirm === 'function') {
|
|
onConfirm();
|
|
}
|
|
});
|
|
|
|
document.getElementById('cancelBtn').addEventListener('click', function() {
|
|
closeModal(modal);
|
|
if (typeof onCancel === 'function') {
|
|
onCancel();
|
|
}
|
|
});
|
|
|
|
return modal;
|
|
}
|
|
|
|
// 创建加载提示
|
|
function createLoadingTip(message = '加载中...') {
|
|
const tip = document.createElement('div');
|
|
tip.className = 'fixed top-0 left-0 w-full h-full bg-gray-900 bg-opacity-50 flex items-center justify-center';
|
|
tip.innerHTML = `
|
|
<div class="bg-white p-6 rounded-lg">
|
|
<div class="animate-spin text-4xl text-blue-500 mb-4">
|
|
<i class="fas fa-spinner"></i>
|
|
</div>
|
|
<p class="text-center">${message}</p>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(tip);
|
|
|
|
return tip;
|
|
}
|
|
|
|
// 移除加载提示
|
|
function removeLoadingTip(tip) {
|
|
if (tip && tip.parentNode) {
|
|
tip.parentNode.removeChild(tip);
|
|
}
|
|
} |