fix: show full student summaries
This commit is contained in:
@@ -12,7 +12,7 @@ from ..api_utils import (
|
||||
payload_to_teacher,
|
||||
read_register_payload,
|
||||
)
|
||||
from ..auth import verify_admin_auth, verify_student_profiles_auth
|
||||
from ..auth import verify_admin_auth, verify_any_auth, verify_student_profiles_auth
|
||||
from ..config import (
|
||||
ACCOUNTS_PATH,
|
||||
ADMIN_TASKS_PATH,
|
||||
@@ -176,7 +176,7 @@ def students(
|
||||
|
||||
|
||||
@router.get("/api/students/{student}")
|
||||
def student_detail(student: str, _user: str = Depends(verify_student_profiles_auth)):
|
||||
def student_detail(student: str, _user: str = Depends(verify_any_auth)):
|
||||
for student_profile in load_student_profiles():
|
||||
if student_profile.student == student or student_profile.student_id == student:
|
||||
return student_profile_to_dict(student_profile)
|
||||
|
||||
+3
-33
@@ -50,7 +50,6 @@ let currentRecordOrder = [];
|
||||
let correctedRecords = new Map();
|
||||
let correctedRecordOrder = [];
|
||||
let expandedSummaryRecords = new Set();
|
||||
let expandedSummaryBodies = new Set();
|
||||
let collapsedTeacherGroups = new Set();
|
||||
let currentRecordPage = { query: "", offset: 0, limit: 0, total: 0, shown: 0, hasMore: false };
|
||||
let activeCorrectionKey = "";
|
||||
@@ -244,16 +243,7 @@ function renderRecordRow(row, rowNumber) {
|
||||
</tr>`;
|
||||
}
|
||||
|
||||
function summaryBodyKey(recordKey, index) {
|
||||
return `${recordKey}:${index}`;
|
||||
}
|
||||
|
||||
function summaryPreviewText(value) {
|
||||
const text = String(value || "暂无正文");
|
||||
return text.length > 120 ? `${text.slice(0, 120)}...` : text;
|
||||
}
|
||||
|
||||
function renderSummaryEntry(summary, recordKey, index) {
|
||||
function renderSummaryEntry(summary) {
|
||||
const title = summary.title || "课程小结";
|
||||
const time = summary.time_range ? ` · ${summary.time_range}` : "";
|
||||
const meta = [
|
||||
@@ -261,15 +251,11 @@ function renderSummaryEntry(summary, recordKey, index) {
|
||||
summary.teacher || "",
|
||||
summary.subject || "",
|
||||
].filter(Boolean).join(" · ");
|
||||
const bodyKey = summaryBodyKey(recordKey, index);
|
||||
const body = summary.body || "暂无正文";
|
||||
const expanded = expandedSummaryBodies.has(bodyKey);
|
||||
const canToggle = body.length > 120;
|
||||
return `<div class="record-summary-item">
|
||||
<div class="record-summary-title">${escapeHtml(title)}${escapeHtml(time)}</div>
|
||||
${meta ? `<div class="record-summary-meta">${escapeHtml(meta)}</div>` : ""}
|
||||
<div class="summary-body${expanded ? " summary-full" : " summary-preview"}">${escapeHtml(expanded ? body : summaryPreviewText(body))}</div>
|
||||
${canToggle ? `<button class="summary-toggle" type="button" data-summary-body-key="${escapeHtml(bodyKey)}">${expanded ? "收起全文" : "展开全文"}</button>` : ""}
|
||||
<div class="summary-body summary-full">${escapeHtml(body)}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -300,7 +286,7 @@ function renderGroupedRecords(records) {
|
||||
const summaryCount = Number(row.summary_count || 0);
|
||||
const summaryRow = summaryCount
|
||||
? `<tr class="summary-collapse-row" data-summary-row="${escapeHtml(row._recordKey)}" ${expandedSummaryRecords.has(row._recordKey) ? "" : "hidden"}>
|
||||
<td colspan="${RECORD_TABLE_COLUMN_COUNT}">${(row.summaries || []).map((summary, index) => renderSummaryEntry(summary, row._recordKey, index)).join("")}</td>
|
||||
<td colspan="${RECORD_TABLE_COLUMN_COUNT}">${(row.summaries || []).map((summary) => renderSummaryEntry(summary)).join("")}</td>
|
||||
</tr>`
|
||||
: renderSummaryMissingRow(row._recordKey, expandedSummaryRecords.has(row._recordKey));
|
||||
return `${renderRecordRow(row, displayIndex)}${summaryRow}`;
|
||||
@@ -341,15 +327,6 @@ function toggleTeacherGroup(teacher) {
|
||||
renderCurrentRecords();
|
||||
}
|
||||
|
||||
function toggleSummaryBody(key) {
|
||||
if (expandedSummaryBodies.has(key)) {
|
||||
expandedSummaryBodies.delete(key);
|
||||
} else {
|
||||
expandedSummaryBodies.add(key);
|
||||
}
|
||||
renderCurrentRecords();
|
||||
}
|
||||
|
||||
function statusClass(status) {
|
||||
if (status === "欠费") return "debt";
|
||||
if (status === "预警") return "warning";
|
||||
@@ -414,7 +391,6 @@ function resetCorrections() {
|
||||
correctedRecordOrder = [];
|
||||
currentRecordOrder = [];
|
||||
expandedSummaryRecords = new Set();
|
||||
expandedSummaryBodies = new Set();
|
||||
collapsedTeacherGroups = new Set();
|
||||
activeCorrectionKey = "";
|
||||
updateCorrectionToolbar();
|
||||
@@ -782,7 +758,6 @@ async function queryRecords(query, options = {}) {
|
||||
} else {
|
||||
currentRecordOrder = [];
|
||||
expandedSummaryRecords = new Set();
|
||||
expandedSummaryBodies = new Set();
|
||||
collapsedTeacherGroups = new Set();
|
||||
}
|
||||
try {
|
||||
@@ -853,7 +828,6 @@ recordRows.addEventListener("click", (event) => {
|
||||
const editButton = event.target.closest(".correction-edit");
|
||||
const deleteButton = event.target.closest(".record-delete");
|
||||
const teacherToggle = event.target.closest(".teacher-group-toggle");
|
||||
const summaryToggle = event.target.closest(".summary-toggle");
|
||||
if (summarySupplementButton) {
|
||||
openSummarySupplementDialog(summarySupplementButton.dataset.recordKey);
|
||||
return;
|
||||
@@ -870,10 +844,6 @@ recordRows.addEventListener("click", (event) => {
|
||||
toggleTeacherGroup(teacherToggle.dataset.teacher);
|
||||
return;
|
||||
}
|
||||
if (summaryToggle) {
|
||||
toggleSummaryBody(summaryToggle.dataset.summaryBodyKey);
|
||||
return;
|
||||
}
|
||||
const row = event.target.closest(".record-row");
|
||||
if (row && !event.target.closest(".record-action-cell")) toggleRecordSummary(row.dataset.recordKey);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>新时空教务管理系统</title>
|
||||
<link rel="stylesheet" href="/static/styles.css?v=20260626-record-index" />
|
||||
<link rel="stylesheet" href="/static/styles.css?v=20260704-summary-full" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="topbar">
|
||||
@@ -167,6 +167,6 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="/static/app.js?v=20260626-record-index"></script>
|
||||
<script src="/static/app.js?v=20260704-summary-full"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -933,27 +933,6 @@ textarea:focus {
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.summary-body + .summary-toggle,
|
||||
.summary-full + .summary-toggle {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.summary-toggle {
|
||||
min-height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
color: var(--accent-strong);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.summary-toggle:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.summary-conflict-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
|
||||
@@ -119,6 +119,38 @@ assertEqual("纠错后排序仍使用显示记录", value("currentRecordOrder.jo
|
||||
vm.runInContext("updateCorrectionToolbar('测试提交按钮')", context);
|
||||
assertEqual("提交审核按钮文案", value("submitCorrectionsBtn.textContent"), "提交审核 1 条");
|
||||
|
||||
vm.runInContext(
|
||||
`
|
||||
const longSummaryBody = "完整课程小结内容".repeat(20);
|
||||
currentRecords = [
|
||||
{
|
||||
date: "2026.06.14",
|
||||
weekday: "星期日",
|
||||
time: "10:00-11:00",
|
||||
student: "甲",
|
||||
duration: "1小时0分",
|
||||
duration_hours: 1,
|
||||
teacher: "王老师",
|
||||
subject: "英语",
|
||||
_recordIndex: 0,
|
||||
_recordKey: "summary-test",
|
||||
summary_count: 1,
|
||||
summaries: [{ title: "课程小结", body: longSummaryBody, teacher: "王老师", subject: "英语" }],
|
||||
},
|
||||
];
|
||||
expandedSummaryRecords = new Set(["summary-test"]);
|
||||
collapsedTeacherGroups = new Set();
|
||||
const summaryHtml = renderGroupedRecords(currentRecords);
|
||||
if (!summaryHtml.includes(longSummaryBody)) {
|
||||
throw new Error("课程小结展开后应直接显示完整正文");
|
||||
}
|
||||
if (summaryHtml.includes("展开全文") || summaryHtml.includes("summary-toggle") || summaryHtml.includes("summary-preview")) {
|
||||
throw new Error("课程小结展开后不应再渲染展开全文按钮或预览裁切");
|
||||
}
|
||||
`,
|
||||
context,
|
||||
);
|
||||
|
||||
const adminElements = new Map();
|
||||
function adminElement(id) {
|
||||
if (!adminElements.has(id)) {
|
||||
|
||||
Reference in New Issue
Block a user