Files
time-tracking-system/static/js/timerecords.js
bf1942 8938ce2708 refactor(api): 重构数据库访问为SQLAlchemy绑定的session
- 统一移除手动创建的数据库session,统一使用models模块中的db.session
- 修正项目创建接口,增加开始和结束日期的格式验证与处理
- 更新导入项目接口,使用枚举类型校验项目类型并优化异常处理
- 更新统计接口,避免多次查询假期数据,优化日期字符串处理
- 删除回滚前多余的session关闭调用,改为使用db.session.rollback()
- app.py中重构数据库初始化:统一配置SQLAlchemy,动态创建数据库路径和表
- 项目模型新增开始日期和结束日期字段支持
- 添加导入批次历史记录模型支持
- 优化工具函数中日期类型提示,移除无用导入
- 更新requirements.txt依赖版本回退,确保兼容性
- 前端菜单添加导入历史导航入口,实现页面访问路由绑定
2025-09-04 18:12:24 +08:00

347 lines
11 KiB
JavaScript
Raw 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
let timeRecords = [];
let projects = [];
let currentEditingRecord = null;
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', function() {
initializePage();
setupEventListeners();
});
// 初始化页面
async function initializePage() {
await Promise.all([
loadProjects(),
loadTimeRecords()
]);
// 设置默认筛选日期为本周
const weekRange = getThisWeekRange();
document.getElementById('filter-start-date').value = weekRange.start;
document.getElementById('filter-end-date').value = weekRange.end;
// 设置默认记录日期为今天
document.getElementById('record_date').value = getTodayString();
}
// 设置事件监听器
function setupEventListeners() {
// 工时记录表单提交
const recordForm = document.getElementById('timerecord-form');
if (recordForm) {
recordForm.addEventListener('submit', handleRecordSubmit);
}
// 时间输入变化时自动计算工时
const startTimeInput = document.getElementById('start_time');
const endTimeInput = document.getElementById('end_time');
if (startTimeInput) {
startTimeInput.addEventListener('change', calculateHours);
}
if (endTimeInput) {
endTimeInput.addEventListener('change', calculateHours);
}
}
// 加载项目列表
async function loadProjects() {
try {
const response = await apiGet('/api/projects');
projects = response.data;
populateProjectSelect();
} catch (error) {
showError('加载项目失败: ' + error.message);
console.error('加载项目失败:', error);
}
}
// 填充项目选择框
function populateProjectSelect() {
const selects = ['project_id', 'filter-project'];
selects.forEach(selectId => {
const select = document.getElementById(selectId);
if (!select) return;
// 清空现有选项(保留第一个默认选项)
const firstOption = select.querySelector('option');
select.innerHTML = '';
if (firstOption) {
select.appendChild(firstOption);
}
// 添加项目选项
projects.forEach(project => {
const option = document.createElement('option');
option.value = project.id;
option.textContent = project.project_name;
select.appendChild(option);
});
});
}
// 加载工时记录
async function loadTimeRecords() {
try {
const params = new URLSearchParams();
const startDate = document.getElementById('filter-start-date').value;
const endDate = document.getElementById('filter-end-date').value;
const projectId = document.getElementById('filter-project').value;
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
if (projectId) params.append('project_id', projectId);
const url = `/api/timerecords${params.toString() ? '?' + params.toString() : ''}`;
const response = await apiGet(url);
timeRecords = response.data;
renderTimeRecordsTable();
} catch (error) {
showError('加载工时记录失败: ' + error.message);
console.error('加载工时记录失败:', error);
}
}
// 渲染工时记录表格
function renderTimeRecordsTable() {
const tbody = document.getElementById('timerecords-tbody');
if (!tbody) return;
if (timeRecords.length === 0) {
tbody.innerHTML = '<tr><td colspan="9" class="text-center">暂无工时记录</td></tr>';
return;
}
tbody.innerHTML = timeRecords.map(record => {
const projectDisplay = record.project ? record.project.project_name : '-';
const rowClass = getRowClass(record);
return `
<tr class="${rowClass}">
<td>${formatDate(record.date)}</td>
<td>${record.day_of_week || getDayOfWeekChinese(record.date)}</td>
<td>${escapeHtml(record.event_description || '-')}</td>
<td>${escapeHtml(projectDisplay)}</td>
<td>${record.start_time || '-'}</td>
<td>${record.end_time || '-'}</td>
<td>${escapeHtml(record.activity_num || '-')}</td>
<td>${record.hours || '-'}</td>
<td>
<button class="btn btn-sm btn-outline" onclick="editRecord(${record.id})">编辑</button>
<button class="btn btn-sm btn-danger" onclick="deleteRecord(${record.id})">删除</button>
</td>
</tr>
`;
}).join('');
}
// 获取行的CSS类名根据是否为休息日
function getRowClass(record) {
if (record.is_holiday) {
if (record.is_working_on_holiday) {
return 'working-holiday-row'; // 休息日工作
} else {
return 'holiday-row'; // 休息日休息
}
}
return '';
}
// 重置筛选条件
function resetFilters() {
document.getElementById('filter-start-date').value = '';
document.getElementById('filter-end-date').value = '';
document.getElementById('filter-project').value = '';
loadTimeRecords();
}
// 显示创建记录模态框
function showCreateRecordModal() {
currentEditingRecord = null;
resetForm('timerecord-form');
document.getElementById('timerecord-modal-title').textContent = '新建工时记录';
// 设置默认日期为今天
document.getElementById('record_date').value = getTodayString();
// 设置默认时间
document.getElementById('start_time').value = '09:00';
document.getElementById('end_time').value = '17:00';
// 自动计算工时
updateHoursInput();
// 隐藏休息日信息和警告
document.getElementById('holiday-info').style.display = 'none';
document.getElementById('holiday-warning').style.display = 'none';
showModal('timerecord-modal');
// 检查今天是否为休息日
checkHoliday();
}
// 检查休息日
async function checkHoliday() {
const dateInput = document.getElementById('record_date');
const date = dateInput.value;
if (!date) return;
try {
const response = await apiGet(`/api/timerecords/check_holiday/${date}`);
const holidayInfo = response.data;
updateHolidayInfo(holidayInfo);
} catch (error) {
console.error('检查休息日失败:', error);
// 如果API调用失败使用本地判断
const dayOfWeek = new Date(date).getDay();
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
updateHolidayInfo({
is_holiday: isWeekend,
holiday_type: isWeekend ? 'weekend' : null,
holiday_name: null,
day_of_week: getDayOfWeekChinese(date)
});
}
}
// 更新休息日信息显示
function updateHolidayInfo(holidayInfo) {
const holidayInfoDiv = document.getElementById('holiday-info');
const holidayBadge = document.getElementById('holiday-badge');
const holidayText = document.getElementById('holiday-text');
const holidayWarning = document.getElementById('holiday-warning');
if (holidayInfo.is_holiday) {
// 显示休息日信息
holidayInfoDiv.style.display = 'flex';
holidayWarning.style.display = 'block';
// 设置徽章样式和文本
if (holidayInfo.holiday_type === 'weekend') {
holidayBadge.className = 'badge weekend';
holidayBadge.textContent = '周末';
} else if (holidayInfo.holiday_type === 'national_holiday') {
holidayBadge.className = 'badge national-holiday';
holidayBadge.textContent = '节假日';
} else {
holidayBadge.className = 'badge weekend';
holidayBadge.textContent = '休息日';
}
holidayText.textContent = holidayInfo.holiday_name || `${holidayInfo.day_of_week} 休息日`;
} else {
// 隐藏休息日信息
holidayInfoDiv.style.display = 'none';
holidayWarning.style.display = 'none';
}
}
// 更新工时输入框
function updateHoursInput() {
const startTime = document.getElementById('start_time').value;
const endTime = document.getElementById('end_time').value;
const hoursField = document.getElementById('hours');
if (startTime && endTime) {
const calculated = calculateHours(startTime, endTime); // 调用 common.js 中的全局函数
hoursField.value = calculated;
} else {
hoursField.value = '';
}
}
// 处理记录表单提交
async function handleRecordSubmit(e) {
e.preventDefault();
const formData = getFormData('timerecord-form');
// 验证必填字段
if (!formData.date) {
showError('请选择日期');
return;
}
try {
let response;
if (currentEditingRecord) {
// 更新记录
response = await apiPut(`/api/timerecords/${currentEditingRecord.id}`, formData);
} else {
// 创建新记录
response = await apiPost('/api/timerecords', formData);
}
showSuccess(currentEditingRecord ? '工时记录更新成功' : '工时记录创建成功');
closeModal('timerecord-modal');
location.reload(); // 刷新页面以显示最新数据
} catch (error) {
showError(error.message);
}
}
// 编辑记录
function editRecord(recordId) {
const record = timeRecords.find(r => r.id === recordId);
if (!record) {
showError('记录不存在');
return;
}
currentEditingRecord = record;
document.getElementById('timerecord-modal-title').textContent = '编辑工时记录';
// 填充表单数据
fillForm('timerecord-form', {
date: record.date,
event_description: record.event_description || '',
project_id: record.project_id || '',
start_time: record.start_time || '',
end_time: record.end_time || '',
activity_num: record.activity_num || '',
hours: record.hours || ''
});
showModal('timerecord-modal');
// 检查是否为休息日
checkHoliday();
}
// 删除记录
async function deleteRecord(recordId) {
const record = timeRecords.find(r => r.id === recordId);
if (!record) {
showError('记录不存在');
return;
}
if (!confirm(`确定要删除这条工时记录吗?`)) {
return;
}
try {
await apiDelete(`/api/timerecords/${recordId}`);
showSuccess('工时记录删除成功');
location.reload(); // 刷新页面以显示最新数据
} catch (error) {
showError('删除工时记录失败: ' + error.message);
}
}
// HTML转义函数
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}