572 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			572 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
{% extends 'layout/base.html' %}
 | 
						|
 | 
						|
{% block title %}考勤详情 - SmartDSP考勤管理系统{% endblock %}
 | 
						|
 | 
						|
{% block content %}
 | 
						|
<div class="container-fluid mt-4">
 | 
						|
    <!-- 页面标题 -->
 | 
						|
    <div class="d-flex justify-content-between align-items-center mb-4">
 | 
						|
        <h1 class="h3 mb-0">
 | 
						|
            <i class="fas fa-calendar-check me-2"></i>考勤详情
 | 
						|
        </h1>
 | 
						|
        <div>
 | 
						|
            <a href="{{ url_for('admin.attendance_management') }}" class="btn btn-secondary">
 | 
						|
                <i class="fas fa-arrow-left me-2"></i>返回列表
 | 
						|
            </a>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <!-- 基本信息卡片 -->
 | 
						|
    <div class="row mb-4">
 | 
						|
        <div class="col-md-6">
 | 
						|
            <div class="card shadow">
 | 
						|
                <div class="card-header py-3">
 | 
						|
                    <h6 class="m-0 font-weight-bold text-primary">
 | 
						|
                        <i class="fas fa-user me-2"></i>学生信息
 | 
						|
                    </h6>
 | 
						|
                </div>
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row">
 | 
						|
                        <div class="col-6">
 | 
						|
                            <p><strong>学号:</strong> {{ weekly_record.student_number }}</p>
 | 
						|
                            <p><strong>姓名:</strong> {{ weekly_record.name }}</p>
 | 
						|
                            {% if student %}
 | 
						|
                            <p><strong>年级:</strong> {{ student.grade }}</p>
 | 
						|
                            <p><strong>学院:</strong> {{ student.college or '未设置' }}</p>
 | 
						|
                            {% endif %}
 | 
						|
                        </div>
 | 
						|
                        <div class="col-6">
 | 
						|
                            {% if student %}
 | 
						|
                            <p><strong>专业:</strong> {{ student.major or '未设置' }}</p>
 | 
						|
                            <p><strong>导师:</strong> {{ student.supervisor or '未设置' }}</p>
 | 
						|
                            <p><strong>学位类型:</strong> {{ student.degree_type or '未设置' }}</p>
 | 
						|
                            <p><strong>状态:</strong>
 | 
						|
                                <span class="badge bg-{{ 'success' if student.status == '在读' else 'secondary' }}">
 | 
						|
                                    {{ student.status }}
 | 
						|
                                </span>
 | 
						|
                            </p>
 | 
						|
                            {% endif %}
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div class="col-md-6">
 | 
						|
            <div class="card shadow">
 | 
						|
                <div class="card-header py-3">
 | 
						|
                    <h6 class="m-0 font-weight-bold text-primary">
 | 
						|
                        <i class="fas fa-calendar-week me-2"></i>考勤周期
 | 
						|
                    </h6>
 | 
						|
                </div>
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row">
 | 
						|
                        <div class="col-6">
 | 
						|
                            <p><strong>开始日期:</strong> {{ weekly_record.week_start_date.strftime('%Y年%m月%d日') }}</p>
 | 
						|
                            <p><strong>结束日期:</strong> {{ weekly_record.week_end_date.strftime('%Y年%m月%d日') }}</p>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-6">
 | 
						|
                            <p><strong>创建时间:</strong> {{ weekly_record.created_at.strftime('%Y-%m-%d %H:%M') }}</p>
 | 
						|
                            <p><strong>更新时间:</strong> {{ weekly_record.updated_at.strftime('%Y-%m-%d %H:%M') }}</p>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <!-- 统计数据卡片 -->
 | 
						|
    <div class="row mb-4">
 | 
						|
        <div class="col-md-3">
 | 
						|
            <div class="card border-left-primary shadow h-100 py-2">
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row no-gutters align-items-center">
 | 
						|
                        <div class="col mr-2">
 | 
						|
                            <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
 | 
						|
                                实际出勤时长
 | 
						|
                            </div>
 | 
						|
                            <div class="h5 mb-0 font-weight-bold text-gray-800">
 | 
						|
                                {{ "%.1f"|format(weekly_record.actual_work_hours) }}小时
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-auto">
 | 
						|
                            <i class="fas fa-clock fa-2x text-gray-300"></i>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div class="col-md-3">
 | 
						|
            <div class="card border-left-success shadow h-100 py-2">
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row no-gutters align-items-center">
 | 
						|
                        <div class="col mr-2">
 | 
						|
                            <div class="text-xs font-weight-bold text-success text-uppercase mb-1">
 | 
						|
                                班内工作时长
 | 
						|
                            </div>
 | 
						|
                            <div class="h5 mb-0 font-weight-bold text-gray-800">
 | 
						|
                                {{ "%.1f"|format(weekly_record.class_work_hours) }}小时
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-auto">
 | 
						|
                            <i class="fas fa-briefcase fa-2x text-gray-300"></i>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div class="col-md-3">
 | 
						|
            <div class="card border-left-warning shadow h-100 py-2">
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row no-gutters align-items-center">
 | 
						|
                        <div class="col mr-2">
 | 
						|
                            <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
 | 
						|
                                旷工天数
 | 
						|
                            </div>
 | 
						|
                            <div class="h5 mb-0 font-weight-bold text-gray-800">
 | 
						|
                                {{ weekly_record.absent_days }}天
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-auto">
 | 
						|
                            <i class="fas fa-exclamation-triangle fa-2x text-gray-300"></i>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div class="col-md-3">
 | 
						|
            <div class="card border-left-info shadow h-100 py-2">
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row no-gutters align-items-center">
 | 
						|
                        <div class="col mr-2">
 | 
						|
                            <div class="text-xs font-weight-bold text-info text-uppercase mb-1">
 | 
						|
                                加班时长
 | 
						|
                            </div>
 | 
						|
                            <div class="h5 mb-0 font-weight-bold text-gray-800">
 | 
						|
                                {{ "%.1f"|format(weekly_record.overtime_hours) }}小时
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-auto">
 | 
						|
                            <i class="fas fa-moon fa-2x text-gray-300"></i>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <!-- 每日考勤明细 -->
 | 
						|
    <div class="card shadow mb-4">
 | 
						|
        <div class="card-header py-3">
 | 
						|
            <h6 class="m-0 font-weight-bold text-primary">
 | 
						|
                <i class="fas fa-list me-2"></i>每日考勤明细
 | 
						|
                <small class="text-muted">(点击日期查看详细时段信息)</small>
 | 
						|
            </h6>
 | 
						|
        </div>
 | 
						|
        <div class="card-body">
 | 
						|
            {% if daily_details %}
 | 
						|
            <div class="table-responsive">
 | 
						|
                <table class="table table-hover">
 | 
						|
                    <thead class="table-light">
 | 
						|
                        <tr>
 | 
						|
                            <th>日期</th>
 | 
						|
                            <th>星期</th>
 | 
						|
                            <th>考勤状态</th>
 | 
						|
                            <th>签到时间</th>
 | 
						|
                            <th>签退时间</th>
 | 
						|
                            <th>工作时长</th>
 | 
						|
                            <th>备注</th>
 | 
						|
                            <th>操作</th>
 | 
						|
                        </tr>
 | 
						|
                    </thead>
 | 
						|
                    <tbody>
 | 
						|
                        {% for detail in daily_details %}
 | 
						|
                        <tr>
 | 
						|
                            <td>{{ detail.attendance_date.strftime('%m-%d') }}</td>
 | 
						|
                            <td>
 | 
						|
                                {% set weekday = detail.attendance_date.weekday() %}
 | 
						|
                                {% if weekday == 0 %}周一
 | 
						|
                                {% elif weekday == 1 %}周二
 | 
						|
                                {% elif weekday == 2 %}周三
 | 
						|
                                {% elif weekday == 3 %}周四
 | 
						|
                                {% elif weekday == 4 %}周五
 | 
						|
                                {% elif weekday == 5 %}周六
 | 
						|
                                {% else %}周日
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.status == '正常' %}
 | 
						|
                                    <span class="badge bg-success">{{ detail.status }}</span>
 | 
						|
                                {% elif '迟到' in detail.status %}
 | 
						|
                                    <span class="badge bg-warning">{{ detail.status }}</span>
 | 
						|
                                {% elif detail.status == '缺勤' %}
 | 
						|
                                    <span class="badge bg-danger">{{ detail.status }}</span>
 | 
						|
                                {% elif detail.status == '请假' %}
 | 
						|
                                    <span class="badge bg-orange">{{ detail.status }}</span>
 | 
						|
                                {% elif detail.status == '休息' %}
 | 
						|
                                    <span class="badge bg-info">{{ detail.status }}</span>
 | 
						|
                                {% elif detail.status == '加班' %}
 | 
						|
                                    <span class="badge bg-primary">{{ detail.status }}</span>
 | 
						|
                                {% else %}
 | 
						|
                                    <span class="badge bg-secondary">{{ detail.status }}</span>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.check_in_time %}
 | 
						|
                                    {{ detail.check_in_time.strftime('%H:%M') }}
 | 
						|
                                {% else %}
 | 
						|
                                    <span class="text-muted">未打卡</span>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.check_out_time %}
 | 
						|
                                    {{ detail.check_out_time.strftime('%H:%M') }}
 | 
						|
                                {% else %}
 | 
						|
                                    <span class="text-muted">未打卡</span>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.duration_hours %}
 | 
						|
                                    <span class="badge bg-primary">{{ detail.duration_hours }}h</span>
 | 
						|
                                {% else %}
 | 
						|
                                    <span class="text-muted">-</span>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.summary_remarks %}
 | 
						|
                                    <small class="text-muted">{{ detail.summary_remarks }}</small>
 | 
						|
                                {% else %}
 | 
						|
                                    <span class="text-muted">-</span>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                            <td>
 | 
						|
                                {% if detail.status not in ['休息', '缺勤'] and detail.detailed_info %}
 | 
						|
                                <button type="button" class="btn btn-sm btn-outline-primary"
 | 
						|
                                        onclick="showDetailModal('{{ detail.detail_id }}', '{{ detail.attendance_date.strftime('%Y-%m-%d') }}', '{{ detail.remarks|escape }}')"
 | 
						|
                                        title="查看详细时段">
 | 
						|
                                    <i class="fas fa-eye"></i>
 | 
						|
                                </button>
 | 
						|
                                {% endif %}
 | 
						|
                            </td>
 | 
						|
                        </tr>
 | 
						|
                        {% endfor %}
 | 
						|
                    </tbody>
 | 
						|
                </table>
 | 
						|
            </div>
 | 
						|
            {% else %}
 | 
						|
            <div class="text-center py-3">
 | 
						|
                <i class="fas fa-calendar-times fa-3x text-muted mb-3"></i>
 | 
						|
                <h5 class="text-muted">暂无每日考勤明细</h5>
 | 
						|
                <p class="text-muted">该考勤周期内没有详细的打卡记录</p>
 | 
						|
            </div>
 | 
						|
            {% endif %}
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <!-- 统计分析和历史对比的其他部分... -->
 | 
						|
    <div class="row mb-4">
 | 
						|
        <div class="col-md-6">
 | 
						|
            <div class="card shadow">
 | 
						|
                <div class="card-header py-3">
 | 
						|
                    <h6 class="m-0 font-weight-bold text-primary">
 | 
						|
                        <i class="fas fa-chart-pie me-2"></i>考勤统计分析
 | 
						|
                    </h6>
 | 
						|
                </div>
 | 
						|
                <div class="card-body">
 | 
						|
                    <div class="row text-center">
 | 
						|
                        <div class="col-3">
 | 
						|
                            <div class="border-end">
 | 
						|
                                <h6 class="text-success">{{ present_days }}</h6>
 | 
						|
                                <small class="text-muted">正常天数</small>
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-3">
 | 
						|
                            <div class="border-end">
 | 
						|
                                <h6 class="text-warning">{{ late_days }}</h6>
 | 
						|
                                <small class="text-muted">迟到天数</small>
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-3">
 | 
						|
                            <div class="border-end">
 | 
						|
                                <h6 class="text-danger">{{ absent_days }}</h6>
 | 
						|
                                <small class="text-muted">缺勤天数</small>
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                        <div class="col-3">
 | 
						|
                            <h6 class="text-info">{{ "%.1f"|format(avg_daily_hours) }}h</h6>
 | 
						|
                            <small class="text-muted">日均时长</small>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div class="col-md-6">
 | 
						|
            <div class="card shadow">
 | 
						|
                <div class="card-header py-3">
 | 
						|
                    <h6 class="m-0 font-weight-bold text-primary">
 | 
						|
                        <i class="fas fa-history me-2"></i>历史对比
 | 
						|
                    </h6>
 | 
						|
                </div>
 | 
						|
                <div class="card-body">
 | 
						|
                    {% if historical_records %}
 | 
						|
                    <div class="table-responsive">
 | 
						|
                        <table class="table table-sm">
 | 
						|
                            <thead>
 | 
						|
                                <tr>
 | 
						|
                                    <th>周期</th>
 | 
						|
                                    <th>出勤时长</th>
 | 
						|
                                    <th>旷工天数</th>
 | 
						|
                                </tr>
 | 
						|
                            </thead>
 | 
						|
                            <tbody>
 | 
						|
                                {% for record in historical_records %}
 | 
						|
                                <tr>
 | 
						|
                                    <td>
 | 
						|
                                        <small>{{ record.week_start_date.strftime('%m-%d') }}</small>
 | 
						|
                                    </td>
 | 
						|
                                    <td>
 | 
						|
                                        <span class="badge bg-primary">{{ "%.1f"|format(record.actual_work_hours) }}h</span>
 | 
						|
                                    </td>
 | 
						|
                                    <td>
 | 
						|
                                        {% if record.absent_days > 0 %}
 | 
						|
                                            <span class="badge bg-warning">{{ record.absent_days }}</span>
 | 
						|
                                        {% else %}
 | 
						|
                                            <span class="badge bg-success">0</span>
 | 
						|
                                        {% endif %}
 | 
						|
                                    </td>
 | 
						|
                                </tr>
 | 
						|
                                {% endfor %}
 | 
						|
                            </tbody>
 | 
						|
                        </table>
 | 
						|
                    </div>
 | 
						|
                    {% else %}
 | 
						|
                    <p class="text-muted text-center mb-0">暂无历史记录</p>
 | 
						|
                    {% endif %}
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<!-- 详细时段信息模态框 -->
 | 
						|
<div class="modal fade" id="detailModal" tabindex="-1" aria-labelledby="detailModalLabel" aria-hidden="true">
 | 
						|
    <div class="modal-dialog modal-lg modal-dialog-centered">  <!-- 添加 modal-dialog-centered -->
 | 
						|
        <div class="modal-content">
 | 
						|
            <div class="modal-header">
 | 
						|
                <h5 class="modal-title" id="detailModalLabel">
 | 
						|
                    <i class="fas fa-clock me-2"></i>详细打卡时段 - <span id="modalDate"></span>
 | 
						|
                </h5>
 | 
						|
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
						|
            </div>
 | 
						|
            <div class="modal-body">
 | 
						|
                <div id="detailContent">
 | 
						|
                    <!-- 内容将通过JavaScript动态填充 -->
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <div class="modal-footer">
 | 
						|
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
 | 
						|
            </div>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
{% endblock %}
 | 
						|
 | 
						|
{% block extra_css %}
 | 
						|
<style>
 | 
						|
.border-left-primary {
 | 
						|
    border-left: 0.25rem solid #4e73df !important;
 | 
						|
}
 | 
						|
 | 
						|
.border-left-success {
 | 
						|
    border-left: 0.25rem solid #1cc88a !important;
 | 
						|
}
 | 
						|
 | 
						|
.border-left-info {
 | 
						|
    border-left: 0.25rem solid #36b9cc !important;
 | 
						|
}
 | 
						|
 | 
						|
.border-left-warning {
 | 
						|
    border-left: 0.25rem solid #f6c23e !important;
 | 
						|
}
 | 
						|
 | 
						|
.border-end {
 | 
						|
    border-right: 1px solid #dee2e6;
 | 
						|
}
 | 
						|
 | 
						|
.text-xs {
 | 
						|
    font-size: 0.7rem;
 | 
						|
}
 | 
						|
 | 
						|
.card {
 | 
						|
    border: 0;
 | 
						|
    box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15) !important;
 | 
						|
}
 | 
						|
 | 
						|
.period-card {
 | 
						|
    border: 1px solid #e3e6f0;
 | 
						|
    border-radius: 0.35rem;
 | 
						|
    padding: 1rem;
 | 
						|
    margin-bottom: 1rem;
 | 
						|
}
 | 
						|
 | 
						|
.period-header {
 | 
						|
    font-weight: 600;
 | 
						|
    color: #5a5c69;
 | 
						|
    margin-bottom: 0.5rem;
 | 
						|
}
 | 
						|
 | 
						|
.badge.bg-orange {
 | 
						|
    background-color: #fd7e14 !important;
 | 
						|
}
 | 
						|
 | 
						|
.time-info {
 | 
						|
    display: flex;
 | 
						|
    justify-content: space-between;
 | 
						|
    align-items: center;
 | 
						|
}
 | 
						|
</style>
 | 
						|
{% endblock %}
 | 
						|
 | 
						|
{% block extra_js %}
 | 
						|
<script>
 | 
						|
function showDetailModal(detailId, date, remarksJson) {
 | 
						|
    document.getElementById('modalDate').textContent = date;
 | 
						|
 | 
						|
    console.log('调用showDetailModal', detailId, date, remarksJson); // 调试信息
 | 
						|
 | 
						|
    let detailsData = null;
 | 
						|
 | 
						|
    try {
 | 
						|
        if (remarksJson && remarksJson.startsWith('{')) {
 | 
						|
            const parsed = JSON.parse(remarksJson);
 | 
						|
            detailsData = parsed.details;
 | 
						|
            console.log('解析的详细数据:', detailsData); // 调试信息
 | 
						|
        }
 | 
						|
    } catch (e) {
 | 
						|
        console.error('解析详细信息失败:', e);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!detailsData) {
 | 
						|
        document.getElementById('detailContent').innerHTML =
 | 
						|
            '<p class="text-muted">暂无详细时段信息</p><p class="text-muted">原始数据: ' + remarksJson + '</p>';
 | 
						|
    } else {
 | 
						|
        let html = '';
 | 
						|
 | 
						|
        // 显示各个时段的详情
 | 
						|
        const periods = [
 | 
						|
            { key: 'morning', name: '早上时段', time: '09:45-11:30' },
 | 
						|
            { key: 'afternoon', name: '下午时段', time: '13:30-18:30' },
 | 
						|
            { key: 'evening', name: '晚上时段', time: '19:00-23:30' }
 | 
						|
        ];
 | 
						|
 | 
						|
        periods.forEach(period => {
 | 
						|
            if (detailsData[period.key]) {
 | 
						|
                const data = detailsData[period.key];
 | 
						|
                html += `
 | 
						|
                    <div class="period-card">
 | 
						|
                        <div class="period-header">
 | 
						|
                            <i class="fas fa-clock me-2"></i>${period.name} (${period.time})
 | 
						|
                        </div>
 | 
						|
                        <div class="time-info">
 | 
						|
                            <div>
 | 
						|
                                <strong>签到:</strong>
 | 
						|
                                <span class="badge ${getStatusClass(data.status, 'in')}">
 | 
						|
                                    ${data.in || '未打卡'}
 | 
						|
                                </span>
 | 
						|
                                ${data.late_minutes ? `<small class="text-warning">(迟到${data.late_minutes}分钟)</small>` : ''}
 | 
						|
                            </div>
 | 
						|
                            <div>
 | 
						|
                                <strong>签退:</strong>
 | 
						|
                                <span class="badge ${getStatusClass(data.status, 'out')}">
 | 
						|
                                    ${data.out || '未打卡'}
 | 
						|
                                </span>
 | 
						|
                                ${data.early_minutes ? `<small class="text-warning">(早退${data.early_minutes}分钟)</small>` : ''}
 | 
						|
                            </div>
 | 
						|
                            <div>
 | 
						|
                                <strong>工时:</strong>
 | 
						|
                                ${calculatePeriodHours(data.in, data.out)}
 | 
						|
                            </div>
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                `;
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        // 如果是周末加班
 | 
						|
        if (detailsData.overtime) {
 | 
						|
            html += `
 | 
						|
                <div class="period-card">
 | 
						|
                    <div class="period-header">
 | 
						|
                        <i class="fas fa-moon me-2"></i>周末加班
 | 
						|
                    </div>
 | 
						|
                    <div class="time-info">
 | 
						|
                        <div>
 | 
						|
                            <strong>开始:</strong>
 | 
						|
                            <span class="badge bg-info">${detailsData.overtime.in || '未记录'}</span>
 | 
						|
                        </div>
 | 
						|
                        <div>
 | 
						|
                            <strong>结束:</strong>
 | 
						|
                            <span class="badge bg-info">${detailsData.overtime.out || '未记录'}</span>
 | 
						|
                        </div>
 | 
						|
                        <div>
 | 
						|
                            <strong>加班时长:</strong>
 | 
						|
                            ${calculatePeriodHours(detailsData.overtime.in, detailsData.overtime.out)}
 | 
						|
                        </div>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            `;
 | 
						|
        }
 | 
						|
 | 
						|
        if (html === '') {
 | 
						|
            html = '<p class="text-muted">该日期没有详细的时段打卡信息</p>';
 | 
						|
        }
 | 
						|
 | 
						|
        document.getElementById('detailContent').innerHTML = html;
 | 
						|
    }
 | 
						|
 | 
						|
    const modal = new bootstrap.Modal(document.getElementById('detailModal'));
 | 
						|
    modal.show();
 | 
						|
}
 | 
						|
 | 
						|
function getStatusClass(status, type) {
 | 
						|
    if (status === 'normal') return 'bg-success';
 | 
						|
    if (status === 'late' && type === 'in') return 'bg-warning';
 | 
						|
    if (status === 'early_leave' && type === 'out') return 'bg-warning';
 | 
						|
    if (status === 'missing') return 'bg-secondary';
 | 
						|
    return 'bg-secondary';
 | 
						|
}
 | 
						|
 | 
						|
function calculatePeriodHours(startTime, endTime) {
 | 
						|
    if (!startTime || !endTime) return '<span class="text-muted">-</span>';
 | 
						|
 | 
						|
    try {
 | 
						|
        const start = new Date(`2000-01-01 ${startTime}:00`);
 | 
						|
        const end = new Date(`2000-01-01 ${endTime}:00`);
 | 
						|
        const diff = (end - start) / (1000 * 60 * 60);
 | 
						|
 | 
						|
        if (diff > 0) {
 | 
						|
            return `<span class="badge bg-primary">${diff.toFixed(1)}h</span>`;
 | 
						|
        }
 | 
						|
    } catch (e) {
 | 
						|
        console.error('计算时长失败:', e);
 | 
						|
    }
 | 
						|
 | 
						|
    return '<span class="text-muted">-</span>';
 | 
						|
}
 | 
						|
 | 
						|
// 测试函数
 | 
						|
function testModal() {
 | 
						|
    console.log('测试模态框');
 | 
						|
    document.getElementById('modalDate').textContent = '测试日期';
 | 
						|
    document.getElementById('detailContent').innerHTML = '<p>测试内容</p>';
 | 
						|
    const modal = new bootstrap.Modal(document.getElementById('detailModal'));
 | 
						|
    modal.show();
 | 
						|
}
 | 
						|
</script>
 | 
						|
{% endblock %}
 |