From aa6f4a032952f2387a2aa3ad24804d497c9adb28 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 18 Jun 2026 09:24:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=BE=E7=A8=8B=E5=B0=8F?= =?UTF-8?q?=E7=BB=93=E6=9F=A5=E8=AF=A2=E5=B1=95=E5=BC=80=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/app/static/admin.html | 7 +-- app/app/static/admin.js | 100 ++++++++++++++++++++++++-------------- app/app/static/styles.css | 65 +++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 41 deletions(-) diff --git a/app/app/static/admin.html b/app/app/static/admin.html index cc0f971..c560d1e 100644 --- a/app/app/static/admin.html +++ b/app/app/static/admin.html @@ -4,7 +4,7 @@ 管理后台 - +
@@ -344,9 +344,6 @@ 时间 学生 老师/科目 - 标题 - 小结正文 - 操作 @@ -453,6 +450,6 @@ - + diff --git a/app/app/static/admin.js b/app/app/static/admin.js index 94f6476..f332d74 100644 --- a/app/app/static/admin.js +++ b/app/app/static/admin.js @@ -108,6 +108,8 @@ let currentTeachers = []; let editingTeacherId = ""; let currentSummaryReviews = []; let activeSummaryReview = null; +let currentSummarySearchItems = []; +let expandedSummarySearchId = ""; let currentOperationLogs = []; let expandedOperationLogId = ""; const registerPreviewState = { @@ -728,23 +730,15 @@ function summarySearchParams() { return params; } -function renderSummarySearchBody(item) { - const fullId = `summary-full-${item.id}`; - const hasFull = String(item.body || "") !== String(item.body_preview || ""); - return `
${escapeHtml(item.body_preview || "")}
- - `; -} - function renderSummaryActions(item) { if (item.time_range) { - return `已完整`; + return `时间已完整`; } const inputId = `summary-time-${item.id}`; return `
- - + +
`; } @@ -753,30 +747,58 @@ function renderMatchedFields(item) { return fields.length ? `
命中:${fields.map(escapeHtml).join("、")}` : ""; } -async function loadSummarySearch() { - summarySearchRows.innerHTML = `正在读取`; - try { - const data = await fetchJson(`/api/admin/course-summaries?${summarySearchParams().toString()}`); - summarySearchMeta.innerHTML = [ - metric("命中小结", `${data.count} 条`), - metric("当前显示", `${data.returned} 条`), - ].join(""); - summarySearchRows.innerHTML = data.items - .map((item) => ` +function renderSummarySearchRows(items) { + return items + .map((item) => { + const expanded = String(item.id) === expandedSummarySearchId; + const mainRow = ` ${escapeHtml(item.date_iso || "未识别")} ${escapeHtml(item.time_range || "缺少时间")} ${escapeHtml(item.student || "")}
${escapeHtml(item.group || "")} ${escapeHtml(item.teacher || "待核对老师")}
${escapeHtml(item.subject || "待核对科目")} - ${escapeHtml(item.title || "")}${renderMatchedFields(item)} - ${renderSummarySearchBody(item)} - ${renderSummaryActions(item)} - `) - .join(""); - if (!data.items.length) { - summarySearchRows.innerHTML = `没有符合条件的课程小结`; - } + `; + const detailRow = expanded + ? ` + +
+
+
+
${escapeHtml(item.title || "课程小结正文")}
+ ${renderMatchedFields(item)} +
+
+
${escapeHtml(item.body || item.body_preview || "暂无正文")}
+
${renderSummaryActions(item)}
+
+ + ` + : ""; + return `${mainRow}${detailRow}`; + }) + .join(""); +} + +function renderCurrentSummarySearch() { + summarySearchRows.innerHTML = renderSummarySearchRows(currentSummarySearchItems); + if (!currentSummarySearchItems.length) { + summarySearchRows.innerHTML = `没有符合条件的课程小结`; + } +} + +async function loadSummarySearch() { + summarySearchRows.innerHTML = `正在读取`; + try { + const data = await fetchJson(`/api/admin/course-summaries?${summarySearchParams().toString()}`); + currentSummarySearchItems = data.items || []; + if (!currentSummarySearchItems.some((item) => String(item.id) === expandedSummarySearchId)) expandedSummarySearchId = ""; + summarySearchMeta.innerHTML = [ + metric("命中小结", `${data.count} 条`), + metric("当前显示", `${data.returned} 条`), + ].join(""); + renderCurrentSummarySearch(); } catch (error) { - summarySearchRows.innerHTML = `读取失败:${escapeHtml(error.message)}`; + currentSummarySearchItems = []; + summarySearchRows.innerHTML = `读取失败:${escapeHtml(error.message)}`; } } @@ -1307,7 +1329,6 @@ summarySearchForm.addEventListener("submit", (event) => { }); summarySearchMissingTime.addEventListener("change", loadSummarySearch); summarySearchRows.addEventListener("click", (event) => { - const button = event.target.closest(".summary-toggle"); const saveTime = event.target.closest(".summary-time-save"); const deleteSummary = event.target.closest(".summary-delete"); if (saveTime) { @@ -1325,11 +1346,18 @@ summarySearchRows.addEventListener("click", (event) => { deleteCourseSummary(deleteSummary.dataset.summaryId).catch((error) => alert(error.message)); return; } - if (!button) return; - const target = document.getElementById(button.dataset.target); - if (!target) return; - target.hidden = !target.hidden; - button.textContent = target.hidden ? "展开" : "收起"; + const row = event.target.closest(".summary-search-result-row"); + if (!row) return; + expandedSummarySearchId = expandedSummarySearchId === row.dataset.summaryId ? "" : row.dataset.summaryId; + renderCurrentSummarySearch(); +}); +summarySearchRows.addEventListener("keydown", (event) => { + if (event.key !== "Enter" && event.key !== " ") return; + const row = event.target.closest(".summary-search-result-row"); + if (!row) return; + event.preventDefault(); + expandedSummarySearchId = expandedSummarySearchId === row.dataset.summaryId ? "" : row.dataset.summaryId; + renderCurrentSummarySearch(); }); logOperation.addEventListener("change", loadOperationLogs); logStatus.addEventListener("change", loadOperationLogs); diff --git a/app/app/static/styles.css b/app/app/static/styles.css index 2379ed5..7930ac0 100644 --- a/app/app/static/styles.css +++ b/app/app/static/styles.css @@ -658,6 +658,57 @@ textarea:focus { margin-top: 8px; } +.summary-search-result-row { + cursor: pointer; +} + +.summary-search-result-row:hover td { + background: #f8fafc; +} + +.summary-search-detail-row td { + padding: 0; + background: #fbfcfd; +} + +.summary-search-detail-panel { + padding: 14px 16px 16px; + border-top: 1px solid var(--line); +} + +.summary-search-detail-head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + margin-bottom: 8px; +} + +.summary-search-full { + max-width: none; +} + +.summary-search-actions { + display: flex; + align-items: center; + justify-content: flex-end; + flex-wrap: wrap; + gap: 10px; + margin-top: 14px; + padding-top: 12px; + border-top: 1px solid var(--line); +} + +.summary-search-actions .summary-time-actions { + justify-content: flex-end; +} + +.summary-action-note { + color: var(--muted); + font-size: 13px; + font-weight: 700; +} + .muted { color: var(--muted); } @@ -1581,6 +1632,20 @@ td { padding: 12px 14px 14px; } + .summary-search-detail-panel { + padding: 12px 14px 14px; + } + + .summary-search-actions, + .summary-search-actions .summary-time-actions { + justify-content: stretch; + } + + .summary-search-actions .secondary-button, + .summary-search-actions .summary-time-input { + width: 100%; + } + .log-detail-grid { grid-template-columns: 1fr; gap: 10px;