657 lines
28 KiB
HTML
657 lines
28 KiB
HTML
{% extends 'layout/base.html' %}
|
|
|
|
{% block title %}考勤管理 - CHM考勤管理系统{% 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.upload_attendance') }}" class="btn btn-primary me-2">
|
|
<i class="fas fa-upload me-2"></i>上传数据
|
|
</a>
|
|
<a href="{{ url_for('admin.dashboard') }}" class="btn btn-secondary">
|
|
<i class="fas fa-home me-2"></i>返回首页
|
|
</a>
|
|
</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-search me-2"></i>搜索筛选
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="GET" class="row g-3" id="searchForm">
|
|
<div class="col-md-2">
|
|
<label for="start_date" class="form-label">开始日期</label>
|
|
<input type="date" class="form-control" id="start_date" name="start_date"
|
|
value="{{ start_date or '' }}">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="end_date" class="form-label">结束日期</label>
|
|
<input type="date" class="form-control" id="end_date" name="end_date"
|
|
value="{{ end_date or '' }}">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label for="student_search" class="form-label">学生姓名/学号</label>
|
|
<input type="text" class="form-control" id="student_search" name="student_search"
|
|
placeholder="输入姓名或学号" value="{{ student_search or '' }}">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="sort_by" class="form-label">排序方式</label>
|
|
<select class="form-select" id="sort_by" name="sort_by">
|
|
<option value="created_at_desc" {{ 'selected' if sort_by == 'created_at_desc' else '' }}>最新记录</option>
|
|
<option value="created_at_asc" {{ 'selected' if sort_by == 'created_at_asc' else '' }}>最早记录</option>
|
|
<option value="actual_work_hours_desc" {{ 'selected' if sort_by == 'actual_work_hours_desc' else '' }}>出勤时长↓</option>
|
|
<option value="actual_work_hours_asc" {{ 'selected' if sort_by == 'actual_work_hours_asc' else '' }}>出勤时长↑</option>
|
|
<option value="class_work_hours_desc" {{ 'selected' if sort_by == 'class_work_hours_desc' else '' }}>班内工作↓</option>
|
|
<option value="class_work_hours_asc" {{ 'selected' if sort_by == 'class_work_hours_asc' else '' }}>班内工作↑</option>
|
|
<option value="absent_days_desc" {{ 'selected' if sort_by == 'absent_days_desc' else '' }}>旷工天数↓</option>
|
|
<option value="absent_days_asc" {{ 'selected' if sort_by == 'absent_days_asc' else '' }}>旷工天数↑</option>
|
|
<option value="late_count_desc" {{ 'selected' if sort_by == 'late_count_desc' else '' }}>迟到次数↓</option>
|
|
<option value="late_count_asc" {{ 'selected' if sort_by == 'late_count_asc' else '' }}>迟到次数↑</option>
|
|
<option value="overtime_hours_desc" {{ 'selected' if sort_by == 'overtime_hours_desc' else '' }}>加班时长↓</option>
|
|
<option value="overtime_hours_asc" {{ 'selected' if sort_by == 'overtime_hours_asc' else '' }}>加班时长↑</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-3 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary me-2">
|
|
<i class="fas fa-search me-1"></i>搜索
|
|
</button>
|
|
<a href="{{ url_for('admin.attendance_management') }}" class="btn btn-outline-secondary me-2">
|
|
<i class="fas fa-refresh"></i>
|
|
</a>
|
|
<button type="button" class="btn btn-outline-info" onclick="toggleAdvancedSearch()" title="高级搜索">
|
|
<i class="fas fa-cog"></i>
|
|
</button>
|
|
</div>
|
|
<!-- 隐藏字段保持分页状态 -->
|
|
<input type="hidden" name="page" value="{{ pagination.page if pagination else 1 }}">
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 考勤记录表格 -->
|
|
<div class="card shadow mb-4">
|
|
<div class="card-header py-3 d-flex justify-content-between align-items-center">
|
|
<h6 class="m-0 font-weight-bold text-primary">
|
|
<i class="fas fa-table me-2"></i>考勤记录
|
|
</h6>
|
|
{% if attendance_records %}
|
|
<span class="badge bg-info">
|
|
共 {{ pagination.total }} 条记录
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-body">
|
|
{% if attendance_records %}
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>学号</th>
|
|
<th>姓名</th>
|
|
<th>考勤周期</th>
|
|
<th class="sortable" data-sort="actual_work_hours">
|
|
出勤时长
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="sortable" data-sort="class_work_hours">
|
|
班内工作
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="sortable" data-sort="absent_days">
|
|
旷工天数
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="sortable" data-sort="late_count">
|
|
迟到次数
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="sortable" data-sort="overtime_hours">
|
|
加班时长
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="sortable" data-sort="created_at">
|
|
记录时间
|
|
<i class="fas fa-sort ms-1 text-muted sort-icon"></i>
|
|
</th>
|
|
<th class="text-center">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for record in attendance_records %}
|
|
<tr>
|
|
<td>
|
|
<a href="{{ url_for('admin.student_detail', student_number=record.student_number) }}"
|
|
class="text-decoration-none">
|
|
{{ record.student_number }}
|
|
</a>
|
|
</td>
|
|
<td>{{ record.name }}</td>
|
|
<td>
|
|
<small>
|
|
{{ record.week_start_date.strftime('%Y-%m-%d') }}<br>
|
|
至 {{ record.week_end_date.strftime('%Y-%m-%d') }}
|
|
</small>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-primary">
|
|
{{ "%.1f"|format(record.actual_work_hours) }}h
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-success">
|
|
{{ "%.1f"|format(record.class_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>
|
|
<td>
|
|
{% set late_count = record.late_count if record.late_count is defined else 0 %}
|
|
{% if late_count > 0 %}
|
|
<span class="badge bg-warning">{{ late_count }}次</span>
|
|
{% else %}
|
|
<span class="badge bg-success">0次</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if record.overtime_hours > 0 %}
|
|
<span class="badge bg-info">
|
|
{{ "%.1f"|format(record.overtime_hours) }}h
|
|
</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary">0h</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<small class="text-muted">
|
|
{{ record.created_at.strftime('%m-%d %H:%M') }}
|
|
</small>
|
|
</td>
|
|
<td class="text-center">
|
|
<div class="btn-group btn-group-sm">
|
|
<button type="button" class="btn btn-outline-primary"
|
|
onclick="viewDetails({{ record.record_id }})"
|
|
title="查看详情">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-outline-danger"
|
|
onclick="deleteRecord({{ record.record_id }}, '{{ record.name }}')"
|
|
title="删除">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- 分页 -->
|
|
{% if pagination.pages > 1 %}
|
|
<nav aria-label="考勤记录分页">
|
|
<ul class="pagination justify-content-center">
|
|
{% if pagination.has_prev %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="{{ url_for('admin.attendance_management',
|
|
page=pagination.prev_num,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
student_search=student_search,
|
|
sort_by=sort_by) }}">
|
|
<i class="fas fa-chevron-left"></i>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
|
|
{% for page_num in pagination.iter_pages() %}
|
|
{% if page_num %}
|
|
{% if page_num != pagination.page %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="{{ url_for('admin.attendance_management',
|
|
page=page_num,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
student_search=student_search,
|
|
sort_by=sort_by) }}">
|
|
{{ page_num }}
|
|
</a>
|
|
</li>
|
|
{% else %}
|
|
<li class="page-item active">
|
|
<span class="page-link">{{ page_num }}</span>
|
|
</li>
|
|
{% endif %}
|
|
{% else %}
|
|
<li class="page-item disabled">
|
|
<span class="page-link">…</span>
|
|
</li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if pagination.has_next %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="{{ url_for('admin.attendance_management',
|
|
page=pagination.next_num,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
student_search=student_search,
|
|
sort_by=sort_by) }}">
|
|
<i class="fas fa-chevron-right"></i>
|
|
</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</nav>
|
|
{% endif %}
|
|
|
|
{% else %}
|
|
<!-- 空状态 -->
|
|
<div class="text-center py-5">
|
|
<i class="fas fa-inbox fa-4x text-muted mb-3"></i>
|
|
<h5 class="text-muted">暂无考勤记录</h5>
|
|
<p class="text-muted mb-4">还没有上传任何考勤数据</p>
|
|
<a href="{{ url_for('admin.upload_attendance') }}" class="btn btn-primary">
|
|
<i class="fas fa-upload me-2"></i>立即上传考勤数据
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 统计信息卡片 -->
|
|
{% if attendance_records %}
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<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-chart-bar me-2"></i>当前筛选统计
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row text-center">
|
|
<div class="col-2">
|
|
<div class="border-end">
|
|
<h6 class="text-primary">{{ pagination.total }}</h6>
|
|
<small class="text-muted">总记录</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<div class="border-end">
|
|
<h6 class="text-success">
|
|
{{ attendance_records|sum(attribute='actual_work_hours')|round(1) }}h
|
|
</h6>
|
|
<small class="text-muted">总出勤</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-1">
|
|
<div class="border-end">
|
|
<h6 class="text-danger">
|
|
{{ attendance_records|sum(attribute='absent_days') }}
|
|
</h6>
|
|
<small class="text-muted">旷工</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-1">
|
|
<div class="border-end">
|
|
<h6 class="text-warning">
|
|
{% set total_leave = statistics.total_leave_days if statistics and statistics.total_leave_days else 0 %}
|
|
{{ total_leave }}
|
|
</h6>
|
|
<small class="text-muted">请假</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<div class="border-end">
|
|
<h6 class="text-warning">
|
|
{% set total_late = attendance_records|sum(attribute='late_count') if attendance_records[0].late_count is defined else 0 %}
|
|
{{ total_late }}
|
|
</h6>
|
|
<small class="text-muted">迟到次数</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<div class="border-end">
|
|
<h6 class="text-info">
|
|
{{ attendance_records|sum(attribute='overtime_hours')|round(1) }}h
|
|
</h6>
|
|
<small class="text-muted">总加班</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<h6 class="text-secondary">
|
|
{{ "%.1f"|format((attendance_records|sum(attribute='actual_work_hours')) / (attendance_records|length) if attendance_records|length > 0 else 0) }}h
|
|
</h6>
|
|
<small class="text-muted">平均出勤</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<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-tools me-2"></i>快捷操作
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-6 mb-2">
|
|
<a href="{{ url_for('admin.upload_attendance') }}"
|
|
class="btn btn-outline-primary btn-block">
|
|
<i class="fas fa-upload me-2"></i>上传新数据
|
|
</a>
|
|
</div>
|
|
<div class="col-6 mb-2">
|
|
<a href="{{ url_for('admin.student_list') }}"
|
|
class="btn btn-outline-success btn-block">
|
|
<i class="fas fa-users me-2"></i>学生管理
|
|
</a>
|
|
</div>
|
|
<div class="col-6 mb-2">
|
|
<a href="{{ url_for('admin.statistics') }}"
|
|
class="btn btn-outline-info btn-block">
|
|
<i class="fas fa-chart-line me-2"></i>统计报表
|
|
</a>
|
|
</div>
|
|
<div class="col-6 mb-2">
|
|
<button class="btn btn-outline-secondary btn-block" onclick="exportData()">
|
|
<i class="fas fa-download me-2"></i>导出数据
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- 删除确认模态框 -->
|
|
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteModalLabel">
|
|
<i class="fas fa-exclamation-triangle text-warning me-2"></i>确认删除
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>您确定要删除 <strong id="studentName"></strong> 的这条考勤记录吗?</p>
|
|
<p class="text-danger"><small>此操作不可撤销!</small></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
<button type="button" class="btn btn-danger" id="confirmDelete">确认删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.btn-block {
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.border-end {
|
|
border-right: 1px solid #dee2e6;
|
|
}
|
|
|
|
.table th {
|
|
background-color: #f8f9fc;
|
|
border-top: none;
|
|
font-weight: 600;
|
|
font-size: 0.85rem;
|
|
color: #5a5c69;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
.badge {
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.btn-group-sm > .btn {
|
|
padding: 0.25rem 0.5rem;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
/* 排序功能样式 */
|
|
.sortable {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
position: relative;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.sortable:hover {
|
|
background-color: #e9ecef !important;
|
|
}
|
|
|
|
.sort-icon {
|
|
font-size: 0.7rem;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.sortable:hover .sort-icon {
|
|
color: #007bff !important;
|
|
}
|
|
|
|
.sortable.sort-active {
|
|
background-color: #e7f1ff !important;
|
|
}
|
|
|
|
.sortable.sort-active .sort-icon {
|
|
color: #007bff !important;
|
|
}
|
|
|
|
.sortable.sort-asc .sort-icon:before {
|
|
content: "\f0de"; /* fa-sort-up */
|
|
}
|
|
|
|
.sortable.sort-desc .sort-icon:before {
|
|
content: "\f0dd"; /* fa-sort-down */
|
|
}
|
|
|
|
/* 响应式调整 */
|
|
@media (max-width: 768px) {
|
|
.col-2 {
|
|
flex: 0 0 33.333333%;
|
|
max-width: 33.333333%;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.table-responsive {
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.badge {
|
|
font-size: 0.65rem;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
let recordToDelete = null;
|
|
|
|
function viewDetails(recordId) {
|
|
window.location.href = `/admin/attendance/${recordId}/details`;
|
|
}
|
|
|
|
function editRecord(recordId) {
|
|
window.location.href = `/admin/attendance/${recordId}/edit`;
|
|
}
|
|
|
|
function deleteRecord(recordId, studentName) {
|
|
recordToDelete = recordId;
|
|
document.getElementById('studentName').textContent = studentName;
|
|
const modal = new bootstrap.Modal(document.getElementById('deleteModal'));
|
|
modal.show();
|
|
}
|
|
|
|
document.getElementById('confirmDelete').addEventListener('click', function() {
|
|
if (recordToDelete) {
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = `/admin/attendance/${recordToDelete}/delete`;
|
|
|
|
const csrfToken = document.querySelector('meta[name="csrf-token"]');
|
|
if (csrfToken) {
|
|
const input = document.createElement('input');
|
|
input.type = 'hidden';
|
|
input.name = 'csrf_token';
|
|
input.value = csrfToken.getAttribute('content');
|
|
form.appendChild(input);
|
|
}
|
|
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
});
|
|
|
|
function exportData() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
params.set('export', 'excel');
|
|
window.location.href = '{{ url_for("admin.attendance_management") }}?' + params.toString();
|
|
}
|
|
|
|
// 自动设置结束日期为开始日期的一周后
|
|
document.getElementById('start_date').addEventListener('change', function() {
|
|
const startDate = new Date(this.value);
|
|
const endDate = new Date(startDate);
|
|
endDate.setDate(startDate.getDate() + 6);
|
|
document.getElementById('end_date').value = endDate.toISOString().split('T')[0];
|
|
});
|
|
|
|
// 排序选择器变化时自动提交表单
|
|
document.getElementById('sort_by').addEventListener('change', function() {
|
|
// 重置到第一页
|
|
const pageInput = document.querySelector('input[name="page"]');
|
|
if (pageInput) {
|
|
pageInput.value = 1;
|
|
}
|
|
document.getElementById('searchForm').submit();
|
|
});
|
|
|
|
// 获取当前URL参数的函数
|
|
function getUrlParams() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
return {
|
|
start_date: params.get('start_date') || '',
|
|
end_date: params.get('end_date') || '',
|
|
student_search: params.get('student_search') || '',
|
|
sort_by: params.get('sort_by') || 'created_at_desc'
|
|
};
|
|
}
|
|
|
|
// 构建新的排序URL
|
|
function buildSortUrl(sortField, currentParams) {
|
|
const currentSort = currentParams.sort_by;
|
|
let newSort;
|
|
|
|
if (currentSort === `${sortField}_asc`) {
|
|
newSort = `${sortField}_desc`;
|
|
} else {
|
|
newSort = `${sortField}_asc`;
|
|
}
|
|
|
|
const url = new URL(window.location.origin + window.location.pathname);
|
|
url.searchParams.set('sort_by', newSort);
|
|
if (currentParams.start_date) url.searchParams.set('start_date', currentParams.start_date);
|
|
if (currentParams.end_date) url.searchParams.set('end_date', currentParams.end_date);
|
|
if (currentParams.student_search) url.searchParams.set('student_search', currentParams.student_search);
|
|
// 重置到第一页
|
|
url.searchParams.set('page', '1');
|
|
|
|
return url.toString();
|
|
}
|
|
|
|
// 表头排序功能
|
|
function setupTableSorting() {
|
|
const sortableHeaders = document.querySelectorAll('.sortable');
|
|
const currentParams = getUrlParams();
|
|
|
|
console.log('当前URL参数:', currentParams); // 调试信息
|
|
|
|
sortableHeaders.forEach(header => {
|
|
header.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
const sortField = this.getAttribute('data-sort');
|
|
console.log('点击排序字段:', sortField); // 调试信息
|
|
|
|
const newUrl = buildSortUrl(sortField, currentParams);
|
|
console.log('新URL:', newUrl); // 调试信息
|
|
|
|
window.location.href = newUrl;
|
|
});
|
|
});
|
|
|
|
// 更新当前排序状态的显示
|
|
const currentSortBy = currentParams.sort_by;
|
|
console.log('当前排序:', currentSortBy); // 调试用
|
|
|
|
if (currentSortBy && currentSortBy.includes('_')) {
|
|
// 移除所有现有的排序状态
|
|
sortableHeaders.forEach(header => {
|
|
header.classList.remove('sort-active', 'sort-asc', 'sort-desc');
|
|
});
|
|
|
|
// 解析排序字段和方向
|
|
const lastUnderscoreIndex = currentSortBy.lastIndexOf('_');
|
|
if (lastUnderscoreIndex > 0) {
|
|
const field = currentSortBy.substring(0, lastUnderscoreIndex);
|
|
const direction = currentSortBy.substring(lastUnderscoreIndex + 1);
|
|
|
|
console.log('解析排序:', field, direction); // 调试用
|
|
|
|
const header = document.querySelector(`[data-sort="${field}"]`);
|
|
if (header) {
|
|
header.classList.add('sort-active');
|
|
if (direction === 'desc') {
|
|
header.classList.add('sort-desc');
|
|
} else {
|
|
header.classList.add('sort-asc');
|
|
}
|
|
console.log('设置排序状态成功:', header.textContent.trim()); // 调试用
|
|
} else {
|
|
console.log('未找到排序表头:', field); // 调试用
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 高级搜索切换(预留功能)
|
|
function toggleAdvancedSearch() {
|
|
alert('高级搜索功能开发中...');
|
|
}
|
|
|
|
// DOM加载完成后初始化
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('页面加载完成,初始化排序功能'); // 调试信息
|
|
setupTableSorting();
|
|
});
|
|
</script>
|
|
|
|
{% endblock %}
|