feat(export/dashboard): 导出增强与大屏公开化
导出-每次考试/多考试对比: - 合格次数阈值等标记项抽为常显区块,三类成绩表共用 - 附缺考名单扩展到多考试导出(取所选考试全都没交的人) - 块表每场固定2列(成绩+合并空位),修复漏推空串导致的整行左移/串列 - 列宽按实际内容估算,合并区空位只给最小宽度 - 合格次数始终显示实际次数(含0),仅 ≥ 阈值标绿底 - 打印标题改为「成绩明细」,缺考名单分页单独成页 - 打印样式加 print-color-adjust:exact,绿底/红字可正常印出 数据大屏: - ?class= 班级大屏免登录公开访问,接口侧放行并按班级裁剪后回传 - 单班大屏移除退出按钮,仅首页保留 - 修复红绿判定真bug:membersTable 误用 window.DASH(DASH为let声明取不到) 改为 scoreGrade() 直接读自由变量,按后台合格率正确判红/黄/绿 测试/样例/文档同步更新,全量回归通过。
This commit is contained in:
@@ -80,24 +80,9 @@ $rosterCount = Roster::count();
|
||||
|
||||
<section class="subbar">
|
||||
<span class="subbar-label">导出</span>
|
||||
<label class="subbar-item">排序
|
||||
<select id="exportSortSel">
|
||||
<option value="time">按提交时间</option>
|
||||
<option value="sid">按学号</option>
|
||||
<option value="score_desc">按成绩降序</option>
|
||||
<option value="score_asc">按成绩升序</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="subbar-item" title="每人只导一行:最近一次成绩 + 最高分 + 考试次数">
|
||||
<input type="checkbox" id="exportLatest">按最新成绩
|
||||
</label>
|
||||
<label class="subbar-item" title="按班级拆分多个工作表(xlsx 多表)">
|
||||
<input type="checkbox" id="exportSplit">按班级分表
|
||||
</label>
|
||||
<span class="hint" id="exportBarHint">成绩明细 / 每次考试 / 缺考名单 / 多考试对比,都在「导出」里配置</span>
|
||||
<span class="spacer"></span>
|
||||
<button class="btn" id="btnExport">导出成绩</button>
|
||||
<button class="btn" id="btnExportAbsent">导出缺考</button>
|
||||
<button class="btn" id="btnExportMulti" title="勾选多场考试,横向对比同一批学生的成绩">多考试对比导出</button>
|
||||
<button class="btn btn-primary" id="btnExportOpen" title="导出与打印:选好导出内容、范围与标记方式,再导出 Excel 或直接打印">导出</button>
|
||||
</section>
|
||||
|
||||
<section class="cards" id="statCards">
|
||||
@@ -425,10 +410,18 @@ $rosterCount = Roster::count();
|
||||
<div class="fi">
|
||||
<label>打印范围</label>
|
||||
<select id="ptScope">
|
||||
<option value="latest" selected>按最新成绩打印(每人一行)</option>
|
||||
<option value="all">打印全部记录(含每位学生历史提交)</option>
|
||||
<option value="latest" selected>每人一行(汇总)</option>
|
||||
<option value="all">每次考试一行(含历史提交)</option>
|
||||
</select>
|
||||
<p class="hint">全部记录会把每位学生的每次提交各打一行,完整留存历史;按最新成绩则每人仅显示当前代表成绩。</p>
|
||||
<p class="hint">「每次考试一行」会把每位学生的每次提交各打一行,完整留存历史。</p>
|
||||
</div>
|
||||
<div class="fi">
|
||||
<label>每人成绩口径</label>
|
||||
<select id="ptRowScore" title="每人一行时的代表成绩;选「每次考试一行」时本项不生效">
|
||||
<option value="latest" selected>最新成绩(最近一次提交)</option>
|
||||
<option value="best">最高成绩(该生最高分)</option>
|
||||
</select>
|
||||
<p class="hint">与「导出 → 成绩明细」的「每人成绩」一致,默认最新成绩。</p>
|
||||
</div>
|
||||
<div class="fi checks">
|
||||
<label><input type="checkbox" id="ptRank" checked> 显示名次(全表连续编号)</label>
|
||||
@@ -437,6 +430,7 @@ $rosterCount = Roster::count();
|
||||
<label><input type="checkbox" id="ptAbsent" title="成绩表后另起一页附缺考名单,含备注列供手写"> 附缺考名单(另起一页)</label>
|
||||
</div>
|
||||
<p class="hint">打印内容<b>不受页面当前筛选外的影响</b>,始终按当前班级/组别筛选结果输出;表头会在每页自动重复,末尾附签字栏。</p>
|
||||
<p class="hint">要打印<b>多场考试对比</b>或<b>「每次考试」表</b>(最高分标红、合格次数达标绿底)?用工具栏的 <b>导出</b> 弹窗,选「多考试对比」或「每次考试」后点「打印」。</p>
|
||||
<p class="hint" id="ptHint"></p>
|
||||
</div>
|
||||
<div class="modal-foot">
|
||||
@@ -478,35 +472,186 @@ $rosterCount = Roster::count();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 多考试对比导出 -->
|
||||
<div class="modal" id="multiExportModal">
|
||||
<!-- ================= 统一导出 / 打印 =================
|
||||
所有导出(成绩明细 / 每次考试 / 缺考名单 / 多考试对比)与打印都在这一个弹窗里配置:
|
||||
先选「导出什么」,再按需展开「范围」「列与标记」「打印」三个区块。 -->
|
||||
<div class="modal" id="exportModal">
|
||||
<div class="modal-box wide">
|
||||
<div class="modal-head"><h3>多考试成绩对比导出</h3><button class="x" data-close>×</button></div>
|
||||
<div class="modal-head"><h3>导出 / 打印</h3><button class="x" data-close>×</button></div>
|
||||
<div class="modal-body">
|
||||
<p class="hint" style="margin:0 0 12px">勾选多场考试后导出一张横向对比表:第一行是考试名称,前两列是学号 / 姓名,默认按学号排序;每场考试的成绩可按「最新」或「最高」显示。</p>
|
||||
<div class="me-bar">
|
||||
<label class="chk"><input type="radio" name="meScoreMode" value="latest" checked> 最新成绩</label>
|
||||
<label class="chk"><input type="radio" name="meScoreMode" value="highest"> 最高成绩</label>
|
||||
<span class="spacer"></span>
|
||||
<button class="btn sm" id="btnMeSelAll">全选</button>
|
||||
<button class="btn sm" id="btnMeClear">清空</button>
|
||||
|
||||
<!-- 1. 导出内容 -->
|
||||
<div class="ex-sec">
|
||||
<div class="ex-sec-title">导出内容</div>
|
||||
<div class="ex-types">
|
||||
<label class="ex-type" data-for="detail">
|
||||
<input type="radio" name="exType" value="detail" checked>
|
||||
<span class="ex-type-t">
|
||||
<b>成绩明细</b>
|
||||
<small>每人一行:学号 / 姓名 / 班级 / 组别 / 成绩 / 次数 / 时间 / 时长</small>
|
||||
</span>
|
||||
</label>
|
||||
<label class="ex-type" data-for="attempts">
|
||||
<input type="radio" name="exType" value="attempts">
|
||||
<span class="ex-type-t">
|
||||
<b>每次考试</b>
|
||||
<small>按截图版式:一行一次考试,最高分标红、合格次数标绿</small>
|
||||
</span>
|
||||
</label>
|
||||
<label class="ex-type" data-for="absent">
|
||||
<input type="radio" name="exType" value="absent">
|
||||
<span class="ex-type-t">
|
||||
<b>缺考名单</b>
|
||||
<small>学号 / 姓名 / 班级 / 组别(跟随下方筛选范围)</small>
|
||||
</span>
|
||||
</label>
|
||||
<label class="ex-type" data-for="multi">
|
||||
<input type="radio" name="exType" value="multi">
|
||||
<span class="ex-type-t">
|
||||
<b>多考试对比</b>
|
||||
<small>勾选多场考试,横向对比:每场一列,最高分标红、合格次数标绿</small>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-scroll mid">
|
||||
<table class="grid compact" id="meTable">
|
||||
<thead><tr><th style="width:6%"><input type="checkbox" id="meCheckAll" title="全选"></th><th style="width:8%">顺序</th><th>考试名称</th></tr></thead>
|
||||
<tbody id="meBody"><tr><td colspan="3" class="empty">(暂无可导出的考试,请先在右上角刷新问卷列表)</td></tr></tbody>
|
||||
</table>
|
||||
|
||||
<!-- 2. 统计范围(班级 / 组别) -->
|
||||
<div class="ex-sec" id="exScopeSec">
|
||||
<div class="ex-sec-title">统计范围 <small id="exScopeSum"></small></div>
|
||||
<div class="ex-row">
|
||||
<label class="ex-field">班级
|
||||
<select id="exClsSel" multiple size="4" title="按住 Ctrl / ⌘ 可多选;不选 = 全部班级"></select>
|
||||
</label>
|
||||
<label class="ex-field">组别
|
||||
<select id="exGrpSel" multiple size="4" title="按住 Ctrl / ⌘ 可多选;不选 = 全部组别"></select>
|
||||
</label>
|
||||
<div class="ex-field ex-field-tip">
|
||||
<span class="hint" id="exScopeHint">不选 = 全部(Ctrl / ⌘ 多选)</span>
|
||||
<span class="hint">选多个班级 / 组别时,导出会自动补出对应列并按相同值合并单元格。</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="hint" id="meMeta">已选 0 场</p>
|
||||
|
||||
<!-- 3. 明细列与标记(成绩明细 / 每次考试 用) -->
|
||||
<div class="ex-sec" id="exDetailSec">
|
||||
<div class="ex-sec-title">成绩口径与列</div>
|
||||
<div class="ex-row">
|
||||
<label class="ex-field">每人成绩
|
||||
<select id="exRowScore" title="每人一行时的代表成绩:最新 = 最近一次真实提交;最高 = 该生最高分">
|
||||
<option value="latest" selected>最新成绩</option>
|
||||
<option value="best">最高成绩</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="ex-field">排序
|
||||
<select id="exSort">
|
||||
<option value="time">按提交时间</option>
|
||||
<option value="sid">按学号</option>
|
||||
<option value="score_desc">按成绩降序</option>
|
||||
<option value="score_asc">按成绩升序</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="ex-field">出表方式
|
||||
<select id="exDetailMode">
|
||||
<option value="latest" selected>每人一行(汇总)</option>
|
||||
<option value="all">每次考试一行(明细)</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="ex-checks" id="exDetailChecks">
|
||||
<label><input type="checkbox" id="exSplit"> 按班级分工作表</label>
|
||||
</div>
|
||||
<p class="hint" id="exDetailHint">每人一行时可用「每人成绩」切换最新 / 最高;「每次考试一行」会保留每位学生的历史提交。</p>
|
||||
</div>
|
||||
|
||||
<!-- 3.5 附加工作表(成绩明细 / 每次考试 / 多考试对比 共用) -->
|
||||
<div class="ex-sec" id="exExtraSec">
|
||||
<div class="ex-sec-title">附加内容</div>
|
||||
<div class="ex-checks">
|
||||
<label><input type="checkbox" id="exWithAbsent" checked> 附缺考名单(名单里有、所选考试全都没交的人)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. 标记与合格次数(成绩明细 / 每次考试 / 多考试对比 共用) -->
|
||||
<div class="ex-sec" id="exMarkSec">
|
||||
<div class="ex-sec-title">标记与合格次数</div>
|
||||
<div class="ex-row">
|
||||
<label class="ex-field">合格次数阈值
|
||||
<input type="number" id="exPassTimes" min="1" max="20" step="1" value="1"
|
||||
title="同一场考试里「达到合格线」的次数 ≥ 此值才标绿(默认 1 次)">
|
||||
</label>
|
||||
<div class="ex-field ex-field-tip">
|
||||
<span class="hint">合格线 = 该场考试满分 × 合格率(在「试卷设置」里按卷配置,缺省用全局)</span>
|
||||
<span class="hint">例:阈值填 2,则该场考到合格线 ≥ 2 次才把「合格次数」标绿。</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ex-checks">
|
||||
<label><input type="checkbox" id="exMarkBest" checked> 最高分标红</label>
|
||||
<label><input type="checkbox" id="exPassRow" checked> 输出「合格次数」行(达标绿底)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. 多考试内容 -->
|
||||
<div class="ex-sec" id="exMultiSec" hidden>
|
||||
<div class="ex-sec-title">多考试对比</div>
|
||||
<div class="ex-row">
|
||||
<label class="ex-field">表格形态
|
||||
<select id="exMultiMode">
|
||||
<option value="block" selected>两行表头(每次考试 + 合格次数)</option>
|
||||
<option value="summary">成绩对比(每人一行)</option>
|
||||
<option value="both">两者都出</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="ex-field">对比成绩
|
||||
<select id="exMultiScore">
|
||||
<option value="latest" selected>最新成绩</option>
|
||||
<option value="highest">最高成绩</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="ex-pick">
|
||||
<div class="ex-pick-head">
|
||||
<span>勾选要对比的考试 <small id="exPickCount"></small></span>
|
||||
<span class="spacer"></span>
|
||||
<button class="btn sm" id="btnExPickAll" type="button">全选</button>
|
||||
<button class="btn sm" id="btnExPickNone" type="button">清空</button>
|
||||
</div>
|
||||
<div class="table-scroll mid">
|
||||
<table class="grid compact" id="exExamTable">
|
||||
<thead><tr><th style="width:8%"><input type="checkbox" id="exCheckAll" title="全选"></th><th style="width:8%">顺序</th><th>考试名称</th></tr></thead>
|
||||
<tbody id="exExamBody"><tr><td colspan="3" class="empty">(暂无可导出的考试,请先在右上角刷新问卷列表)</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. 打印设置 -->
|
||||
<div class="ex-sec" id="exPrintSec" hidden>
|
||||
<div class="ex-sec-title">打印设置</div>
|
||||
<div class="ex-row">
|
||||
<label class="ex-field">纸张方向
|
||||
<select id="exOrient" title="多考试打印默认横向(列多,横向不易折行)">
|
||||
<option value="landscape" selected>横向(A4)</option>
|
||||
<option value="portrait">纵向(A4)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="ex-field ex-field-grow">打印标题
|
||||
<input type="text" id="exPrintTitle" placeholder="留空 = 用考试名自动生成">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="hint" id="exSummaryLine" style="margin-top:4px"></p>
|
||||
</div>
|
||||
<div class="modal-foot">
|
||||
<span class="spacer"></span>
|
||||
<button class="btn" data-close>取消</button>
|
||||
<button class="btn btn-primary" id="btnMeExport">导出对比表</button>
|
||||
<button class="btn" id="btnExPrint">打印</button>
|
||||
<button class="btn btn-primary" id="btnExExport">导出 Excel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
window.NY = {
|
||||
appName: <?= json_encode(NY_APP_NAME, JSON_UNESCAPED_UNICODE) ?>,
|
||||
|
||||
Reference in New Issue
Block a user