Files
drl_2/xuexiao/templates/keshibiao_index.html
user9994793890 ee860ce0ae Initial commit
2026-05-29 10:28:07 +08:00

135 lines
7.4 KiB
HTML
Raw Permalink 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.

{% extends "base.html" %}
{% from 'macros/sortable.html' import sort_th %}
{% block title %}课时核对表 - 学生课程管理系统{% endblock %}
{% block content %}
<div class="page-toolbar">
<div>
<h4 class="page-title"><i class="bi bi-table"></i> 课时核对表</h4>
<p class="page-sub text-muted">Excel 导入 · 查看每位学员剩余课时、余额、单价</p>
</div>
<a href="{{ url_for('keshibiao_balances') }}" class="btn btn-neo-primary">
<i class="bi bi-people"></i> 学员课时余额一览
</a>
</div>
<div class="stat-grid mb-4">
<div class="neo-surface neo-stat">
<div class="stat-icon purple"><i class="bi bi-calendar3"></i></div>
<div><p class="stat-value">{{ period_stats|length }}</p><p class="stat-label">已导入月份</p></div>
</div>
<div class="neo-surface neo-stat">
<div class="stat-icon green"><i class="bi bi-journal-text"></i></div>
<div><p class="stat-value">{{ total_snapshots }}</p><p class="stat-label">快照记录</p></div>
</div>
<div class="neo-surface neo-stat">
<div class="stat-icon blue"><i class="bi bi-clock-history"></i></div>
<div><p class="stat-value">{{ total_class_records }}</p><p class="stat-label">上课记录</p></div>
</div>
<div class="neo-surface neo-stat">
<div class="stat-icon yellow"><i class="bi bi-wallet2"></i></div>
<div><p class="stat-value">{{ total_accounts }}</p><p class="stat-label">课时账户</p></div>
</div>
</div>
{% if latest_year and preview_rows %}
<div class="neo-surface p-4 mb-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="fw-bold mb-0"><i class="bi bi-eye"></i> 最新月份预览({{ latest_year }}-{{ '%02d'|format(latest_month) }})</h6>
<a href="{{ url_for('keshibiao_balances', year=latest_year, month=latest_month) }}" class="btn btn-sm btn-outline-primary">查看全部 →</a>
</div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0">
<thead class="table-light">
<tr>
<th>{{ sort_th('keshibiao_index', 'student', '学员', preview_sort, preview_order, preview_params, '') }}</th>
<th>{{ sort_th('keshibiao_index', 'course', '课程', preview_sort, preview_order, preview_params, '') }}</th>
<th class="text-end">{{ sort_th('keshibiao_index', 'end_lessons', '正课剩余', preview_sort, preview_order, preview_params) }}</th>
<th class="text-end">{{ sort_th('keshibiao_index', 'end_gift', '赠课', preview_sort, preview_order, preview_params) }}</th>
<th class="text-end">{{ sort_th('keshibiao_index', 'end_total', '总课时', preview_sort, preview_order, preview_params) }}</th>
<th class="text-end">{{ sort_th('keshibiao_index', 'end_balance', '余额', preview_sort, preview_order, preview_params) }}</th>
<th class="text-end">{{ sort_th('keshibiao_index', 'unit_price', '单价/节', preview_sort, preview_order, preview_params) }}</th>
</tr>
</thead>
<tbody>
{% for r in preview_rows %}
<tr>
<td>{{ r.student_name }}</td>
<td><span class="badge bg-secondary">{{ r.course }}</span></td>
<td class="text-end">{{ r.end_lessons if r.end_lessons is not none else '-' }}</td>
<td class="text-end">{{ r.end_gift_lessons if r.end_gift_lessons is not none else '-' }}</td>
<td class="text-end fw-semibold text-primary">{{ r.end_total_lessons if r.end_total_lessons is not none else '-' }}</td>
<td class="text-end text-success">{% if r.end_balance is not none %}¥{{ '%.2f'|format(r.end_balance) }}{% else %}-{% endif %}</td>
<td class="text-end">{% if r.unit_price is not none %}{{ '%.2f'|format(r.unit_price) }}{% else %}-{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="row g-4">
<div class="col-lg-5">
<div class="neo-surface p-4">
<h6 class="fw-bold mb-3"><i class="bi bi-cloud-upload"></i> 导入 Excel</h6>
<p class="text-muted small mb-3">目录:<code>{{ keshi_dir }}</code></p>
{% if current_user.has_permission('keshibiao_import') %}
<form method="POST" action="{{ url_for('keshibiao_import') }}">
<div class="mb-3">
<label class="form-label">选择文件(留空=导入目录下全部正式表)</label>
<select class="form-select" name="filename">
<option value="">— 全部正式 xlsx —</option>
{% for f in xlsx_files %}
<option value="{{ f }}">{{ f }}</option>
{% endfor %}
</select>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="update" value="1" id="updateMode" checked>
<label class="form-check-label" for="updateMode">已存在月份则更新(覆盖快照与当月上课记录)</label>
</div>
<button type="submit" class="btn btn-neo-primary w-100" {% if not xlsx_files %}disabled{% endif %}>
<i class="bi bi-play-fill"></i> 开始导入
</button>
</form>
<form method="POST" action="{{ url_for('keshibiao_repair_chains') }}" class="mt-2">
<button type="submit" class="btn btn-outline-secondary w-100">
<i class="bi bi-link-45deg"></i> 修复月初月末衔接链
</button>
</form>
{% if not xlsx_files %}
<p class="text-warning small mt-2 mb-0">目录暂无正式月度表,请放入「课时核对表(2026.x月份).xlsx」。</p>
{% endif %}
{% else %}
<p class="text-muted">无导入权限</p>
{% endif %}
</div>
</div>
<div class="col-lg-7">
<div class="neo-surface p-4">
<h6 class="fw-bold mb-3"><i class="bi bi-calendar-range"></i> 已导入月份</h6>
{% if period_stats %}
<div class="table-responsive">
<table class="table table-sm align-middle mb-0">
<thead><tr><th>年月</th><th>学员课程条数</th><th></th></tr></thead>
<tbody>
{% for y, m, cnt in period_stats %}
<tr>
<td>{{ y }}-{{ '%02d'|format(m) }}</td>
<td>{{ cnt }}</td>
<td>
<a href="{{ url_for('keshibiao_balances', year=y, month=m) }}" class="btn btn-sm btn-outline-primary">查看余额</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="text-muted text-center py-4 mb-0">尚未导入任何月份数据</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}