SACC / templates /dashboard.html
cacode's picture
Deploy runtime refresh interval, counters, and curriculum callback check
774585c verified
{% extends "base.html" %}
{% block title %}用户控制台 | SCU 选课控制台{% endblock %}
{% block content %}
<section class="dashboard-shell" data-log-stream-url="{{ url_for('stream_user_logs', last_id=recent_logs[-1].id if recent_logs else 0) }}" data-status-url="{{ url_for('user_status') }}">
<header class="topbar reveal-up">
<div>
<span class="eyebrow">User Console</span>
<h1>{{ current_user.display_name or current_user.student_id }} 的选课面板</h1>
<p>登录账号:{{ current_user.student_id }},你的课程目标与运行日志会实时同步到这里。</p>
</div>
<form method="post" action="{{ url_for('logout') }}">
<button type="submit" class="btn btn-ghost">退出登录</button>
</form>
</header>
<section class="metric-grid reveal-up delay-1">
<article class="metric-card">
<span>当前任务</span>
<strong id="task-status-text">{{ task_labels.get(task.status, '未启动') if task else '未启动' }}</strong>
<small id="task-updated-at">最近更新时间:{{ task.updated_at if task else '暂无' }}</small>
</article>
<article class="metric-card">
<span>待选课程</span>
<strong id="course-count">{{ courses|length }}</strong>
<small>管理员可看到全部课程内容</small>
</article>
<article class="metric-card">
<span>累计尝试次数</span>
<strong id="task-attempts">{{ task.total_attempts if task else 0 }}</strong>
<small>每次课程尝试都会累计到这里</small>
</article>
<article class="metric-card">
<span>累计错误次数</span>
<strong id="task-errors">{{ task.total_errors if task else 0 }}</strong>
<small id="task-last-error">{{ task.last_error if task and task.last_error else '当前没有错误提示' }}</small>
</article>
<article class="metric-card">
<span>刷新间隔</span>
<strong id="refresh-interval">{{ current_user.refresh_interval_seconds or default_refresh_interval_seconds }} 秒</strong>
<small>未抢到课时,等待下一轮刷新的时间</small>
</article>
</section>
<section class="content-grid dashboard-grid">
<article class="card reveal-up delay-2">
<div class="card-head">
<span class="kicker">个人信息</span>
<h2>更新登录信息</h2>
<p>密码会用于后台登录教务系统,请保持为最新有效密码。</p>
</div>
<form method="post" action="{{ url_for('update_profile') }}" class="form-grid">
<label class="field">
<span>显示名称</span>
<input type="text" name="display_name" value="{{ current_user.display_name }}" placeholder="可选昵称">
</label>
<label class="field">
<span>教务密码</span>
<input type="password" name="password" value="" placeholder="重新输入当前有效密码" required>
</label>
<button type="submit" class="btn btn-primary">保存账号信息</button>
</form>
</article>
<article class="card reveal-up delay-2">
<div class="card-head">
<span class="kicker">运行参数</span>
<h2>调整刷新间隔</h2>
<p>当本轮没有抢到目标课程时,任务会按这里的秒数等待下一轮刷新。</p>
</div>
<form method="post" action="{{ url_for('update_runtime_settings') }}" class="form-grid form-grid-compact">
<label class="field">
<span>未命中后刷新间隔</span>
<input type="number" name="refresh_interval_seconds" min="{{ refresh_interval_min }}" max="{{ refresh_interval_max }}" value="{{ current_user.refresh_interval_seconds or default_refresh_interval_seconds }}" required>
</label>
<button type="submit" class="btn btn-secondary">更新刷新间隔</button>
</form>
</article>
<article class="card reveal-up delay-2">
<div class="card-head">
<span class="kicker">课程目标</span>
<h2>添加课程号与课序号</h2>
<p>支持方案选课与自由选课,管理员会看到你录入的全部内容。</p>
</div>
<form method="post" action="{{ url_for('add_course') }}" class="form-grid form-grid-compact">
<label class="field">
<span>选课类型</span>
<select name="category">
<option value="free">自由选课</option>
<option value="plan">方案选课</option>
</select>
</label>
<label class="field">
<span>课程号</span>
<input type="text" name="course_id" placeholder="例如 888005010A59" autocapitalize="characters" required>
</label>
<label class="field">
<span>课序号</span>
<input type="text" name="course_index" placeholder="例如 01 或 666" autocapitalize="characters" required>
</label>
<button type="submit" class="btn btn-secondary">加入抢课队列</button>
</form>
</article>
<article class="card reveal-up delay-3 span-2">
<div class="card-head split">
<div>
<span class="kicker">执行控制</span>
<h2>启动与停止任务</h2>
<p>后台会按照管理员设置的并行数进行排队和执行。</p>
</div>
<div class="button-row">
<form method="post" action="{{ url_for('start_task') }}">
<button type="submit" class="btn btn-primary">启动任务</button>
</form>
<form method="post" action="{{ url_for('stop_task') }}">
<button type="submit" class="btn btn-ghost danger">停止任务</button>
</form>
</div>
</div>
<div class="status-strip">
<span class="status-pill status-{{ task.status if task else 'idle' }}" id="task-status-pill">{{ task_labels.get(task.status, '未启动') if task else '未启动' }}</span>
<span>创建时间:{{ task.created_at if task else '暂无任务' }}</span>
<span>触发者:{{ task.requested_by if task else '暂无' }}</span>
<span>尝试次数:<strong id="task-attempts-inline">{{ task.total_attempts if task else 0 }}</strong></span>
<span>错误次数:<strong id="task-errors-inline">{{ task.total_errors if task else 0 }}</strong></span>
</div>
<div class="course-table-wrap">
<table class="data-table">
<thead>
<tr>
<th>类型</th>
<th>课程号</th>
<th>课序号</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% if courses %}
{% for course in courses %}
<tr>
<td>{{ category_labels.get(course.category, course.category) }}</td>
<td>{{ course.course_id }}</td>
<td>{{ course.course_index }}</td>
<td>
<form method="post" action="{{ url_for('delete_course', course_target_id=course.id) }}">
<button type="submit" class="inline-action">移除</button>
</form>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4" class="empty-cell">还没有课程目标,先添加课程号和课序号吧。</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</article>
<article class="card reveal-up delay-3 span-2">
<div class="card-head split">
<div>
<span class="kicker">实时日志</span>
<h2>后台运行日志</h2>
<p>这里会持续显示程序执行时的关键步骤、错误与结果。</p>
</div>
<span class="live-dot">LIVE</span>
</div>
<div class="log-console" id="log-console">
{% if recent_logs %}
{% for log in recent_logs %}
<div class="log-line level-{{ log.level|lower }}">
<span class="log-meta">{{ log.created_at }} | {{ log.scope }} | {{ log.level }}</span>
<span>{{ log.message }}</span>
</div>
{% endfor %}
{% else %}
<div class="log-line level-info muted">暂无日志,启动任务后这里会自动刷新。</div>
{% endif %}
</div>
</article>
</section>
</section>
{% endblock %}