Files
ny-exam-platform/tools/make-samples.php
T
nxxy335 d05fd4a9b5 feat(export/dashboard): 导出增强与大屏公开化
导出-每次考试/多考试对比:
- 合格次数阈值等标记项抽为常显区块,三类成绩表共用
- 附缺考名单扩展到多考试导出(取所选考试全都没交的人)
- 块表每场固定2列(成绩+合并空位),修复漏推空串导致的整行左移/串列
- 列宽按实际内容估算,合并区空位只给最小宽度
- 合格次数始终显示实际次数(含0),仅 ≥ 阈值标绿底
- 打印标题改为「成绩明细」,缺考名单分页单独成页
- 打印样式加 print-color-adjust:exact,绿底/红字可正常印出

数据大屏:
- ?class= 班级大屏免登录公开访问,接口侧放行并按班级裁剪后回传
- 单班大屏移除退出按钮,仅首页保留
- 修复红绿判定真bug:membersTable 误用 window.DASH(DASH为let声明取不到)
  改为 scoreGrade() 直接读自由变量,按后台合格率正确判红/黄/绿

测试/样例/文档同步更新,全量回归通过。
2026-09-27 22:04:17 +08:00

127 lines
5.1 KiB
PHP
Raw 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.
<?php
/**
* 生成「导出 / 打印」新版式的可打开样例:
* 1) docs/samples/export-multi-block.xlsx —— 多考试块表(两行表头 + 合格次数 + 红绿标记)
* 2) docs/samples/export-single-wide.xlsx —— 单场宽表(每人一行、第几次做列名)
* 3) docs/samples/sheet-data.json —— 供 make-samples.js 渲染预览 HTML
*
* 数据是一次性写死的示例数据(与 tests/test-multi-export.php 的截图场景同一套口径),
* 不是真实导出结果,仅用于看版式。
*
* 运行:php tools/make-samples.php
*/
declare(strict_types=1);
require __DIR__ . '/../bootstrap.php';
require __DIR__ . '/../lib/multi_export.php';
/** 构造一名学生的若干次考试记录(成绩按时间升序) */
function sample_stu(string $sid, string $name, float $best, array $scoresAsc, array $tempMarks = []): array
{
$list = [];
$t = 1000000;
foreach ($scoresAsc as $i => $sc) {
$t += 600;
$list[] = [
'idx' => $i + 1,
'submit_ts' => $t,
'score' => $sc,
'temp_save' => !empty($tempMarks[$i]),
'duration' => 120,
];
}
return [
'sid' => $sid,
'name' => $name,
'cls' => '1班',
'grp' => 'A',
'score' => end($scoresAsc),
'best_score' => $best,
'attempts' => count($scoresAsc),
'attempts_list' => $list,
];
}
/* ---- 示例数据:与需求截图同口径(合格线 110,阈值 1 次) ---- */
$exams = [
'm' => ['name' => '第一次月考·数学', 'rows' => [
sample_stu('356001', '张三', 136.0, [112.0, 100.0, 136.0, 127.0]),
sample_stu('356002', '李四', 0.0, []), // 整场未考
sample_stu('356003', '王五', 95.0, [95.0]), // 未达合格线 → 不标绿
]],
'e' => ['name' => '第一次月考·英语', 'rows' => [
sample_stu('356001', '张三', 112.0, [112.0, 99.0]),
sample_stu('356002', '李四', 133.0, [130.0, 129.0, 133.0]),
]],
];
$opts = [
'pass_line' => 110, // 本卷满分 130 × 合格率 85%
'pass_times' => 1, // 达标阈值
'mark_best' => true, // 最高分标红
'pass_row' => true, // 输出「合格次数」行
];
/* ---- 1) 多考试块表 ---- */
$block = ny_assemble_block_sheet($exams, $opts);
$blockBin = XlsxWriter::renderMulti([[
'name' => '每次考试',
'rows' => $block['rows'],
'widths' => $block['widths'] ?? [],
'merges' => $block['merges'],
'header_rows' => $block['header_rows'],
'cell_styles' => $block['cell_styles'] ?? [],
]]);
$blockPath = __DIR__ . '/../docs/samples/export-multi-block.xlsx';
file_put_contents($blockPath, $blockBin);
/* ---- 2) 单场宽表(只导出一场考试时的版式) ---- */
$wideRes = ny_assemble_attempt_wide_sheet($exams['m'], $opts);
$wideBin = XlsxWriter::renderMulti([[
'name' => '每次考试',
'rows' => $wideRes['rows'],
'widths' => $wideRes['widths'] ?? [],
'merges' => $wideRes['merges'],
'header_rows' => $wideRes['header_rows'],
'cell_styles' => $wideRes['cell_styles'] ?? [],
]]);
$widePath = __DIR__ . '/../docs/samples/export-single-wide.xlsx';
file_put_contents($widePath, $wideBin);
/* ---- 3) 交给 Node 渲染预览 HTML(用 app.js 里的 sheetToHtml,避免两份实现漂移) ---- */
$data = [
'block' => [
'title' => '多考试导出 · 每次考试(两行表头)',
'sheet' => [
'rows' => $block['rows'],
'merges' => $block['merges'],
'header_rows' => $block['header_rows'],
'cell_styles' => $block['cell_styles'] ?? [],
],
'meta' => [
'pass_line' => $opts['pass_line'],
'pass_times' => $opts['pass_times'],
],
],
'wide' => [
'title' => '单场导出 · 每次考试(每人一行的宽表)',
'sheet' => [
'rows' => $wideRes['rows'],
'merges' => $wideRes['merges'],
'header_rows' => $wideRes['header_rows'],
'cell_styles' => $wideRes['cell_styles'] ?? [],
],
'meta' => [
'pass_line' => $opts['pass_line'],
'pass_times' => $opts['pass_times'],
'exam_name' => $exams['m']['name'],
],
],
];
file_put_contents(__DIR__ . '/../docs/samples/sheet-data.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
echo '块表:' . count($block['rows']) . ' 行 / ' . count($block['merges']) . ' 处合并 / '
. count($block['cell_styles'] ?? []) . " 处标记 → " . realpath($blockPath) . PHP_EOL;
echo '宽表:' . count($wideRes['rows']) . ' 行 / ' . count($wideRes['merges']) . ' 处合并 / '
. count($wideRes['cell_styles'] ?? []) . " 处标记 → " . realpath($widePath) . PHP_EOL;
echo '预览数据:' . realpath(__DIR__ . '/../docs/samples/sheet-data.json') . PHP_EOL;