| {% extends "admin_layout.html" %} |
| {% block admin_title %}用户管理{% endblock %} |
| {% block admin_page_content %} |
| <section class="content-grid admin-grid reveal-up delay-2"> |
| <article class="card"> |
| <div class="card-head"> |
| <span class="kicker">新增用户</span> |
| <h2>手动录入用户信息</h2> |
| <p>管理员可以直接录入学生账号,课程和定时任务则在对应页面分别管理。</p> |
| </div> |
| <form method="post" action="{{ url_for('create_user') }}" class="form-grid form-grid-compact"> |
| <label class="field"> |
| <span>学号</span> |
| <input type="text" name="student_id" inputmode="numeric" placeholder="13 位学号" required> |
| </label> |
| <label class="field"> |
| <span>显示名称</span> |
| <input type="text" name="display_name" placeholder="可选备注"> |
| </label> |
| <label class="field"> |
| <span>刷新间隔</span> |
| <input type="number" name="refresh_interval_seconds" min="{{ refresh_interval_min }}" max="{{ refresh_interval_max }}" value="{{ default_refresh_interval_seconds }}" required> |
| </label> |
| <label class="field span-2"> |
| <span>密码</span> |
| <input type="password" name="password" placeholder="教务处密码" required> |
| </label> |
| <button type="submit" class="btn btn-secondary">创建用户</button> |
| </form> |
| </article> |
|
|
| <article class="card"> |
| <div class="card-head"> |
| <span class="kicker">跳转提示</span> |
| <h2>功能已拆分</h2> |
| <p>这里负责用户资料、课程和任务操作。定时任务请进入“定时任务”页面,注册码请进入“注册码”页面。</p> |
| </div> |
| <div class="button-row wrap-row"> |
| <a href="{{ url_for('admin_schedules') }}" class="btn btn-secondary">去定时任务页</a> |
| <a href="{{ url_for('admin_registration_codes') }}" class="btn btn-ghost">去注册码页</a> |
| </div> |
| </article> |
| </section> |
|
|
| <section class="card reveal-up delay-3 span-2"> |
| <div class="card-head"> |
| <span class="kicker">用户管理</span> |
| <h2>所有用户与课程详情</h2> |
| <p>可以直接修改用户信息、增减课程,或代替用户启动和停止任务。</p> |
| </div> |
| <div class="user-card-grid"> |
| {% for user in users %} |
| <section class="user-card" id="user-{{ user.id }}"> |
| <div class="user-card-head"> |
| <div> |
| <h3>{{ user.display_name or user.student_id }}</h3> |
| <p>{{ user.student_id }}</p> |
| </div> |
| <span class="status-pill status-{{ user.latest_task.status if user.latest_task else 'idle' }}"> |
| {{ task_labels.get(user.latest_task.status, '未启动') if user.latest_task else '未启动' }} |
| </span> |
| </div> |
|
|
| <div class="chip-row tight"> |
| <span class="chip {% if user.is_active %}highlight{% endif %}">{{ '启用中' if user.is_active else '已禁用' }}</span> |
| <span class="chip">课程 {{ user.course_count }}</span> |
| <span class="chip">最近任务 {{ user.latest_task.id if user.latest_task else '--' }}</span> |
| <span class="chip">刷新 {{ user.refresh_interval_seconds or default_refresh_interval_seconds }} 秒</span> |
| <span class="chip">尝试 {{ user.latest_task.total_attempts if user.latest_task else 0 }}</span> |
| <span class="chip">错误 {{ user.latest_task.total_errors if user.latest_task else 0 }}</span> |
| <span class="chip">定时 {{ '开启' if user.schedule and user.schedule.is_enabled else '关闭' }}</span> |
| </div> |
|
|
| <form method="post" action="{{ url_for('update_user', user_id=user.id) }}" class="form-grid form-grid-compact slim-form"> |
| <label class="field span-2"> |
| <span>显示名称</span> |
| <input type="text" name="display_name" value="{{ user.display_name }}" placeholder="备注名称"> |
| </label> |
| <label class="field"> |
| <span>刷新间隔</span> |
| <input type="number" name="refresh_interval_seconds" min="{{ refresh_interval_min }}" max="{{ refresh_interval_max }}" value="{{ user.refresh_interval_seconds or default_refresh_interval_seconds }}" required> |
| </label> |
| <label class="field span-2"> |
| <span>重置密码</span> |
| <input type="password" name="password" placeholder="留空表示不修改"> |
| </label> |
| <button type="submit" class="btn btn-ghost">保存用户</button> |
| </form> |
|
|
| <div class="button-row wrap-row compact-row"> |
| <a href="{{ url_for('admin_schedules') }}#user-{{ user.id }}" class="btn btn-secondary">去设定时任务</a> |
| <form method="post" action="{{ url_for('toggle_user', user_id=user.id) }}"> |
| <button type="submit" class="btn btn-ghost {% if not user.is_active %}danger{% endif %}">{{ '禁用' if user.is_active else '启用' }}</button> |
| </form> |
| <form method="post" action="{{ url_for('admin_start_user_task', user_id=user.id) }}"> |
| <button type="submit" class="btn btn-primary">代启动任务</button> |
| </form> |
| <form method="post" action="{{ url_for('admin_stop_user_task', user_id=user.id) }}"> |
| <button type="submit" class="btn btn-ghost danger">代停止任务</button> |
| </form> |
| <form method="post" action="{{ url_for('delete_user_by_admin', user_id=user.id) }}"> |
| <button type="submit" class="btn btn-ghost danger">删除用户</button> |
| </form> |
| </div> |
|
|
| <form method="post" action="{{ url_for('admin_add_course', user_id=user.id) }}" class="form-grid form-grid-compact slim-form"> |
| <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> |
|
|
| <div class="course-list"> |
| {% if user.courses %} |
| {% for course in user.courses %} |
| <div class="course-chip-row"> |
| <span>{{ category_labels.get(course.category, course.category) }} · {{ course.course_id }}_{{ course.course_index }}</span> |
| <form method="post" action="{{ url_for('admin_delete_course', course_target_id=course.id) }}"> |
| <button type="submit" class="inline-action">删除</button> |
| </form> |
| </div> |
| {% endfor %} |
| {% else %} |
| <div class="empty-mini">当前没有课程目标。</div> |
| {% endif %} |
| </div> |
| </section> |
| {% else %} |
| <div class="empty-state-card"> |
| 还没有录入任何用户,请先通过上方表单创建用户。 |
| </div> |
| {% endfor %} |
| </div> |
| </section> |
| {% endblock %}
|
|
|