mirror of
https://github.com/Cccc-owo/CheckInApp.git
synced 2026-06-17 05:56:29 +00:00
5cdc8b2144
后端改进: - 添加统一异常处理系统 (exceptions.py, response.py) - 实现自定义异常类 (ValidationError, AuthorizationError, ResourceNotFoundError, BusinessLogicError) - 配置全局异常处理器,统一 API 错误响应格式 - 迁移业务逻辑错误到自定义异常 (users.py, auth.py) - 添加 SQL LIKE 通配符转义,防止通配符滥用 - 使用 EmailStr 进行邮箱格式验证 - 移除敏感字段暴露 (jwt_sub) 前端改进: - 配置 ESLint 9 (flat config) 和 Prettier - 修复所有 ESLint 错误和警告 - 移除未使用的变量和导入 - 为组件添加 PropTypes 默认值 - 统一代码格式和风格
146 lines
3.5 KiB
JavaScript
146 lines
3.5 KiB
JavaScript
/**
|
|
* 格式化日期时间
|
|
* @param {string|Date} date - 日期
|
|
* @param {boolean} includeTime - 是否包含时间
|
|
* @returns {string}
|
|
*/
|
|
export function formatDateTime(date, includeTime = true) {
|
|
if (!date) return '-';
|
|
|
|
const d = new Date(date);
|
|
if (isNaN(d.getTime())) return '-';
|
|
|
|
const year = d.getFullYear();
|
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
const day = String(d.getDate()).padStart(2, '0');
|
|
|
|
if (!includeTime) {
|
|
return `${year}-${month}-${day}`;
|
|
}
|
|
|
|
const hours = String(d.getHours()).padStart(2, '0');
|
|
const minutes = String(d.getMinutes()).padStart(2, '0');
|
|
const seconds = String(d.getSeconds()).padStart(2, '0');
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
}
|
|
|
|
/**
|
|
* 格式化相对时间(多久之前)
|
|
* @param {string|Date} date - 日期
|
|
* @returns {string}
|
|
*/
|
|
export function formatRelativeTime(date) {
|
|
if (!date) return '-';
|
|
|
|
const d = new Date(date);
|
|
if (isNaN(d.getTime())) return '-';
|
|
|
|
const now = new Date();
|
|
const diff = now - d; // 毫秒差
|
|
|
|
const seconds = Math.floor(diff / 1000);
|
|
const minutes = Math.floor(seconds / 60);
|
|
const hours = Math.floor(minutes / 60);
|
|
const days = Math.floor(hours / 24);
|
|
|
|
if (seconds < 60) return '刚刚';
|
|
if (minutes < 60) return `${minutes} 分钟前`;
|
|
if (hours < 24) return `${hours} 小时前`;
|
|
if (days < 7) return `${days} 天前`;
|
|
|
|
return formatDateTime(date, false);
|
|
}
|
|
|
|
/**
|
|
* 格式化文件大小
|
|
* @param {number} bytes - 字节数
|
|
* @returns {string}
|
|
*/
|
|
export function formatFileSize(bytes) {
|
|
if (!bytes || bytes === 0) return '0 B';
|
|
|
|
const k = 1024;
|
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
|
|
}
|
|
|
|
/**
|
|
* 防抖函数
|
|
* @param {Function} fn - 要防抖的函数
|
|
* @param {number} delay - 延迟时间(毫秒)
|
|
* @returns {Function}
|
|
*/
|
|
export function debounce(fn, delay = 300) {
|
|
let timer = null;
|
|
return function (...args) {
|
|
if (timer) clearTimeout(timer);
|
|
timer = setTimeout(() => {
|
|
fn.apply(this, args);
|
|
}, delay);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 节流函数
|
|
* @param {Function} fn - 要节流的函数
|
|
* @param {number} delay - 延迟时间(毫秒)
|
|
* @returns {Function}
|
|
*/
|
|
export function throttle(fn, delay = 300) {
|
|
let timer = null;
|
|
let lastTime = 0;
|
|
|
|
return function (...args) {
|
|
const now = Date.now();
|
|
|
|
if (now - lastTime < delay) {
|
|
if (timer) clearTimeout(timer);
|
|
timer = setTimeout(() => {
|
|
lastTime = now;
|
|
fn.apply(this, args);
|
|
}, delay);
|
|
} else {
|
|
lastTime = now;
|
|
fn.apply(this, args);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 复制文本到剪贴板
|
|
* @param {string} text - 要复制的文本
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
export async function copyToClipboard(text) {
|
|
try {
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
await navigator.clipboard.writeText(text);
|
|
return true;
|
|
} else {
|
|
// 降级方案
|
|
const textArea = document.createElement('textarea');
|
|
textArea.value = text;
|
|
textArea.style.position = 'fixed';
|
|
textArea.style.left = '-999999px';
|
|
document.body.appendChild(textArea);
|
|
textArea.focus();
|
|
textArea.select();
|
|
try {
|
|
document.execCommand('copy');
|
|
textArea.remove();
|
|
return true;
|
|
} catch (error) {
|
|
console.error('复制失败', error);
|
|
textArea.remove();
|
|
return false;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('复制失败', error);
|
|
return false;
|
|
}
|
|
}
|