+ {group.kinds.length > 1 && }
+
+ {active === 'terms' &&
+ {active === 'terms' && <> ({ value: row.id, label: row.name }))} onChange={setSelectedTerms} />
>}
+ {rows.isError ? : rowKey="id" loading={rows.isLoading} dataSource={pagedRows} columns={columns} pagination={false} scroll={{ x: 900 }} locale={{ emptyText: }} />}
+ {total > pageSize && { setPage(next); setPageSize(size) }} />}
+
+ setEditing(undefined)} onOk={() => form.submit()} width={620}>}{(active === 'colleges' || active === 'buildings') && ({ value: item.id, label: item.name }))} />}{active === 'colleges' && }{active === 'majors' && <> ({ value: item.id, label: item.name }))} />>}{active === 'classes' && <> ({ value: item.id, label: item.name }))} /> ({ value: item.id, label: `${item.displayName}${item.staffNumber ? ` · ${item.staffNumber}` : ''}` }))} />>}{active === 'terms' && <>设为当前学期>}{active === 'classrooms' && <> ({ value: item.id, label: `${item.campusName} · ${item.name}` }))} />>}
+ void applyArchive()} onCancel={() => setArchive((state) => ({ ...state, open: false }))}>符合条件 {eligible.length} / {archive.previews.length} 条。提交时会再次检查,受阻记录不执行。
{archive.busy && !archive.previews.length ? : archive.previews.map((item) => {item.name || '不可操作记录'}{item.error && {item.error}
}{!item.error && <>{item.isArchived ? '已归档' : '未归档'}{item.archiveReason ? ` · 原因:${item.archiveReason}` : ''}
{item.isArchived === archive.target && 已处于目标状态,无需重复操作。
}{item.blockers?.map((blocker, index) => {blocker.message}
)}{item.notices?.map((notice, index) => {notice.message}
)}>})}{!archive.results.length ? : archive.results.map((result) => )}
+ setHistory((state) => ({ ...state, open: false }))}>{history.busy ? : history.entries.length ? history.entries.map((entry) => {entry.isArchived ? '归档' : '恢复'} · {entry.actorName || entry.actorUserId}{new Date(entry.createdAt).toLocaleString('zh-CN', { hour12: false })}
{entry.reason}
) : }第 {history.page} 页
+
+}
diff --git a/web-react/src/pages/base-data.css b/web-react/src/pages/base-data.css
new file mode 100644
index 0000000..2752d87
--- /dev/null
+++ b/web-react/src/pages/base-data.css
@@ -0,0 +1 @@
+.base-data-page{gap:16px}.base-data-card{min-width:0;padding:16px;border:1px solid var(--line);background:#fff}.base-tabs{display:grid;grid-template-columns:repeat(4,1fr);margin:-16px -16px 16px;border-bottom:1px solid var(--line)}.base-tabs button{padding:13px 16px;text-align:left;border:0;border-right:1px solid var(--line);background:#f7f9fb;cursor:pointer}.base-tabs button:last-child{border-right:0}.base-tabs button.active{box-shadow:inset 0 -3px var(--teal);background:var(--teal-soft)}.base-tabs strong,.base-tabs span{display:block}.base-tabs strong{color:var(--brand-deep);font-size:10px}.base-tabs span{margin-top:3px;color:var(--ink-muted);font-size:8px}.base-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:7px;margin-bottom:14px}.base-toolbar>.ant-input-affix-wrapper{width:245px}.base-toolbar>.ant-select{min-width:145px}.base-toolbar>.ant-input-number{width:125px}.base-toolbar>span:last-child{color:var(--ink-muted);font-size:9px}.base-data-card>.ant-alert{margin-bottom:12px}.base-data-card>.ant-pagination{display:flex;justify-content:flex-end;margin-top:15px}.archive-batch{display:flex;gap:8px;margin-bottom:12px}.archive-batch>.ant-select{width:280px}.row-actions{display:flex;flex-wrap:wrap;gap:5px}.base-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.base-form-grid.three{grid-template-columns:repeat(3,1fr)}.base-form-grid .ant-input-number{width:100%}.archive-preview{padding:11px 0;border-bottom:1px solid var(--line)}.archive-preview p{margin:5px 0;color:var(--ink-muted);line-height:1.55}.archive-preview .archive-error{color:#b42318}.archive-reason{display:grid;gap:7px;margin-top:14px;font-weight:600}.history-pagination{display:flex;align-items:center;justify-content:center;gap:12px;margin-top:16px}@media(max-width:800px){.base-tabs{grid-template-columns:repeat(2,1fr)}.base-toolbar{align-items:stretch;flex-direction:column}.base-toolbar>*{width:100%!important}.archive-batch{flex-direction:column}.archive-batch>.ant-select{width:100%}.base-form-grid,.base-form-grid.three{grid-template-columns:1fr}}@media(max-width:520px){.base-tabs{grid-template-columns:1fr}.base-tabs button{border-right:0;border-bottom:1px solid var(--line)}}