// 公共工具函数和API调用
// API 基础 URL
const API_BASE_URL = '';
// 通用 API 调用函数
async function apiCall(url, options = {}) {
try {
const response = await fetch(`${API_BASE_URL}${url}`, {
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP error! status: ${response.status}`);
}
return data;
} catch (error) {
console.error('API调用失败:', error);
throw error;
}
}
// GET 请求
async function apiGet(url) {
return apiCall(url, { method: 'GET' });
}
// POST 请求
async function apiPost(url, data) {
return apiCall(url, {
method: 'POST',
body: JSON.stringify(data)
});
}
// PUT 请求
async function apiPut(url, data) {
return apiCall(url, {
method: 'PUT',
body: JSON.stringify(data)
});
}
// DELETE 请求
async function apiDelete(url) {
return apiCall(url, { method: 'DELETE' });
}
// 显示成功消息
function showSuccess(message) {
showNotification(message, 'success');
}
// 显示错误消息
function showError(message) {
showNotification(message, 'error');
}
// 显示通知
function showNotification(message, type = 'info') {
// 创建通知元素
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.innerHTML = `
${message}
`;
// 添加到页面
document.body.appendChild(notification);
// 自动隐藏
setTimeout(() => {
if (notification.parentElement) {
notification.remove();
}
}, 5000);
}
// 格式化日期
function formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
return date.toLocaleDateString('zh-CN');
}
// 格式化日期时间
function formatDateTime(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
return date.toLocaleString('zh-CN');
}
// 获取今天的日期字符串
function getTodayString() {
const today = new Date();
return today.toISOString().split('T')[0];
}
// 获取本周的开始和结束日期
function getThisWeekRange() {
const today = new Date();
const dayOfWeek = today.getDay();
const startOfWeek = new Date(today);
startOfWeek.setDate(today.getDate() - dayOfWeek + 1); // 周一
const endOfWeek = new Date(startOfWeek);
endOfWeek.setDate(startOfWeek.getDate() + 6); // 周日
return {
start: startOfWeek.toISOString().split('T')[0],
end: endOfWeek.toISOString().split('T')[0]
};
}
// 模态框控制
function showModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.add('show');
modal.style.display = 'flex';
}
}
function closeModal(modalId) {
const modal = document.getElementById(modalId);
if (modal) {
modal.classList.remove('show');
modal.style.display = 'none';
}
}
// 表单重置
function resetForm(formId) {
const form = document.getElementById(formId);
if (form) {
form.reset();
}
}
// 获取表单数据
function getFormData(formId) {
const form = document.getElementById(formId);
if (!form) return {};
const formData = new FormData(form);
const data = {};
for (let [key, value] of formData.entries()) {
data[key] = value;
}
return data;
}
// 填充表单数据
function fillForm(formId, data) {
const form = document.getElementById(formId);
if (!form) return;
Object.keys(data).forEach(key => {
const field = form.querySelector(`[name="${key}"]`);
if (field) {
field.value = data[key] || '';
}
});
}
// 工时格式化函数
function formatHours(hours) {
if (!hours || hours === '-' || hours === '0:00') {
return hours || '-';
}
// 如果包含冒号,直接返回
if (hours.includes(':')) {
return hours;
}
// 如果是小数格式,转换为时:分格式
const decimal = parseFloat(hours);
if (!isNaN(decimal)) {
const h = Math.floor(decimal);
const m = Math.round((decimal - h) * 60);
return `${h}:${m.toString().padStart(2, '0')}`;
}
return hours;
}
// 工时转换为小数
function hoursToDecimal(hours) {
if (!hours || hours === '-') return 0;
if (hours.includes(':')) {
const [h, m] = hours.split(':').map(Number);
return h + (m || 0) / 60;
}
return parseFloat(hours) || 0;
}
// 小数转换为工时格式
function decimalToHours(decimal) {
if (decimal === 0) return '0:00';
const hours = Math.floor(decimal);
const minutes = Math.round((decimal - hours) * 60);
return `${hours}:${minutes.toString().padStart(2, '0')}`;
}
// 计算工时
function calculateHours(startTime, endTime) {
if (!startTime || !endTime || startTime === '-' || endTime === '-') {
return '-';
}
try {
const [startH, startM] = startTime.split(':').map(Number);
const [endH, endM] = endTime.split(':').map(Number);
let startMinutes = startH * 60 + startM;
let endMinutes = endH * 60 + endM;
// 处理跨日情况
if (endMinutes < startMinutes) {
endMinutes += 24 * 60;
}
const diffMinutes = endMinutes - startMinutes;
const hours = Math.floor(diffMinutes / 60);
const minutes = diffMinutes % 60;
return `${hours}:${minutes.toString().padStart(2, '0')}`;
} catch (error) {
console.error('计算工时失败:', error);
return '0:00';
}
}
// 星期中文显示
function getDayOfWeekChinese(dateString) {
const date = new Date(dateString);
const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return days[date.getDay()];
}
// 判断是否为今天
function isToday(dateString) {
const today = new Date().toISOString().split('T')[0];
return dateString === today;
}
// 文件下载
function downloadFile(content, filename, type = 'text/plain') {
const blob = new Blob([content], { type });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// CSV 生成
function generateCSV(data, headers) {
const csvContent = [
headers.join(','),
...data.map(row => headers.map(header => {
const value = row[header] || '';
// 如果值包含逗号、引号或换行符,需要用引号包围
if (value.toString().includes(',') || value.toString().includes('"') || value.toString().includes('\n')) {
return `"${value.toString().replace(/"/g, '""')}"`;
}
return value;
}).join(','))
].join('\n');
return csvContent;
}
// 页面加载完成后的初始化
document.addEventListener('DOMContentLoaded', function() {
// 添加点击外部关闭模态框的功能
document.addEventListener('click', function(e) {
if (e.target.classList.contains('modal')) {
e.target.classList.remove('show');
e.target.style.display = 'none';
}
});
// 添加ESC键关闭模态框的功能
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
const openModal = document.querySelector('.modal.show');
if (openModal) {
openModal.classList.remove('show');
openModal.style.display = 'none';
}
}
});
});
// 添加通知样式到头部(如果不存在)
if (!document.querySelector('#notification-styles')) {
const style = document.createElement('style');
style.id = 'notification-styles';
style.textContent = `
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 20px;
border-radius: 5px;
color: white;
z-index: 10000;
display: flex;
align-items: center;
gap: 15px;
max-width: 400px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
animation: slideIn 0.3s ease-out;
}
.notification.success {
background-color: #27ae60;
}
.notification.error {
background-color: #e74c3c;
}
.notification.info {
background-color: #3498db;
}
.notification button {
background: none;
border: none;
color: white;
font-size: 18px;
cursor: pointer;
padding: 0;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
`;
document.head.appendChild(style);
}