内容页边距:宽度优先给内容,顶栏与内容列同一条基线

高分辨屏上内容列被写死的 1360px 夹在中间,两侧大片空白,
顶栏控件还留在窗口边缘,和内容列差出一百多像素。

* 新增布局变量 --layout-header-h / --content-pad / --content-pad-end /
  --content-max,边距一处可调:14px 起,≥900 20px、≥1600 24px、≥2200 28px
* 内容列上限 1360 → 1680,宽度优先给内容;顶栏 padding-inline 跟着
  内容列内收(max(pad, (100% - 上限)/2)),1920/2560 下右缘零偏差
* 底部留白单独成变量,阅读器高度按 100vh - 顶栏 - 上下留白计算,
  移动端 768 的写死高度一并变量化,去掉多余的几像素竖直滚动
* 试卷排版收紧行距与段距;同时带上上一轮未提交的试卷/分屏样式
main
mula.liu 2026-09-18 14:56:36 +08:00
parent 5f72149ceb
commit c06ca75c89
1 changed files with 785 additions and 5 deletions

View File

@ -22,6 +22,13 @@
--danger-soft: #fef2f2; --danger-soft: #fef2f2;
--danger-soft-border: #fecaca; --danger-soft-border: #fecaca;
--warning-soft: #fffbeb; --warning-soft: #fffbeb;
/* 内容页布局尺度:顶栏高度、内容列左右留白、内容列最大宽度 */
--layout-header-h: 56px;
--content-pad: 14px;
/* 底部留白单独一个变量:.app-content 的下边距比四周略大一点,
阅读器高度等「满屏高度」计算时统一引用它,避免出现几像素的竖直滚动条。 */
--content-pad-end: calc(var(--content-pad) + 4px);
--content-max: 1680px;
} }
/* 深色模式:只换中性色,品牌色与语义色保持不变 */ /* 深色模式:只换中性色,品牌色与语义色保持不变 */
@ -269,6 +276,13 @@ body {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 20; z-index: 20;
/* 与 .app-content-inner 同一条基线:内容列被 max-width 收窄时,
顶栏控件同步内收(推导:内容列左偏移 = pad + (100% - 2*pad - 上限)/2
= (100% - 上限)/2,未被夹住时就是 pad,故取两者较大值)。 */
padding-inline: max(
var(--content-pad),
calc((100% - var(--content-max)) / 2)
) !important;
background: var(--header-bg); background: var(--header-bg);
border-bottom: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft);
backdrop-filter: saturate(180%) blur(8px); backdrop-filter: saturate(180%) blur(8px);
@ -467,12 +481,33 @@ body {
color: var(--text-strong); color: var(--text-strong);
} }
/* 内容页边距:留白随视口变宽略微加大,但宽度优先给内容,
避免高分辨屏上「中间一条窄柱、两侧大片空白」。 */
@media (min-width: 900px) {
:root {
--content-pad: 20px;
}
}
@media (min-width: 1600px) {
:root {
--content-pad: 24px;
}
}
@media (min-width: 2200px) {
:root {
--content-pad: 28px;
}
}
.app-content { .app-content {
padding: 20px; padding: var(--content-pad);
padding-block-end: var(--content-pad-end);
} }
.app-content-inner { .app-content-inner {
max-width: 1360px; max-width: min(100%, var(--content-max));
margin: 0 auto; margin: 0 auto;
} }
@ -986,7 +1021,10 @@ body {
.ebook-reader { .ebook-reader {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: calc(100vh - 96px); /* 顶栏 + 内容区上下留白之外的全部空间,保证页面本身不产生竖直滚动 */
height: calc(
100vh - var(--layout-header-h) - var(--content-pad) - var(--content-pad-end)
);
min-height: 480px; min-height: 480px;
overflow: hidden; overflow: hidden;
background: var(--surface); background: var(--surface);
@ -1138,12 +1176,16 @@ body {
} }
@media (max-width: 768px) { @media (max-width: 768px) {
:root {
--content-pad-end: calc(var(--content-pad) + 2px);
}
.app-content { .app-content {
padding: 14px; padding: var(--content-pad);
padding-block-end: var(--content-pad-end);
} }
.ebook-reader { .ebook-reader {
height: calc(100vh - 92px);
min-height: 420px; min-height: 420px;
} }
@ -1288,3 +1330,741 @@ body {
.daily-submit.ant-btn:disabled { .daily-submit.ant-btn:disabled {
box-shadow: none; box-shadow: none;
} }
/* ---------------- 分屏工作台(题库 / 记录 / 错题 / 答题) ---------------- */
.split-view {
display: flex;
align-items: stretch;
overflow: hidden;
background: var(--surface);
border: 1px solid var(--border-soft);
border-radius: 14px;
box-shadow: 0 1px 2px rgba(31, 32, 51, 0.04);
}
.split-aside {
flex: 0 0 auto;
min-width: 0;
display: flex;
flex-direction: column;
overflow: hidden;
background: var(--surface-2);
}
.split-view--left .split-aside {
border-inline-end: 1px solid var(--border-soft);
}
.split-view--right .split-aside {
border-inline-start: 1px solid var(--border-soft);
}
.split-main {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* 窄屏:左右分屏退回上下堆叠,清单只占一小段高度 */
.split-view--stack {
flex-direction: column;
height: auto !important;
}
.split-view--stack .split-aside {
border-inline-end: 0;
border-inline-start: 0;
border-bottom: 1px solid var(--border-soft);
width: 100% !important;
max-height: 40vh;
}
.split-view--stack .split-main {
min-height: 60vh;
}
.split-resizer {
flex: 0 0 7px;
cursor: col-resize;
position: relative;
background: transparent;
touch-action: none;
}
.split-resizer::after {
content: "";
position: absolute;
inset: 0 3px;
border-radius: 3px;
background: var(--border-soft);
transition: background 0.16s ease;
}
.split-resizer:hover::after,
.split-resizer--active::after {
background: var(--brand);
}
body.split-dragging {
cursor: col-resize;
user-select: none;
}
/* 分屏里的一栏 */
.pane {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.pane-head {
flex: 0 0 auto;
padding: 12px 14px;
border-bottom: 1px solid var(--border-soft);
background: var(--surface);
}
.split-aside > .pane > .pane-head {
background: var(--surface-2);
}
.pane-head-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.pane-title {
font-size: 14px;
font-weight: 600;
color: var(--text-strong);
min-width: 0;
}
.pane-extra {
flex-shrink: 0;
}
.pane-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
margin-top: 10px;
}
.pane-toolbar:empty {
display: none;
}
/* 题库侧栏的三个筛选下拉尽量等分一行;栏太窄时整体换行,
而不是把「难度不限」压成「难度…」;
菜单宽度靠 popupMatchSelectWidth={false} 单独放开,长选项不会被裁。 */
.bank-filter-select {
flex: 1 1 92px;
min-width: 92px;
}
.pane-body {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
padding: 10px 12px 18px;
}
.pane--flat .pane-body {
padding: 0;
overflow: hidden;
display: flex;
}
.pane-foot {
flex: 0 0 auto;
padding: 10px 14px;
border-top: 1px solid var(--border-soft);
background: var(--surface);
}
/* 清单条目 */
.master-item {
display: block;
width: 100%;
text-align: start;
padding: 10px 12px;
margin-bottom: 6px;
border: 1px solid transparent;
border-radius: 10px;
background: transparent;
color: inherit;
cursor: pointer;
transition: background 0.16s ease, border-color 0.16s ease;
}
.master-item:hover {
background: var(--surface-hover);
}
.master-item--active {
background: var(--brand-soft);
border-color: rgba(91, 92, 226, 0.35);
}
.master-item-title {
display: flex;
align-items: center;
gap: 6px;
font-weight: 600;
color: var(--text-strong);
line-height: 1.5;
}
.master-item-sub {
margin-top: 3px;
font-size: 12px;
color: var(--text-secondary);
line-height: 1.6;
}
.master-group {
margin: 6px 0 4px;
padding: 0 4px;
font-size: 12px;
font-weight: 600;
color: var(--text-muted);
}
/* 得分环 / 计数的数字都用等宽数字,纵向对比才整齐 */
.tabular {
font-variant-numeric: tabular-nums;
}
/* ---------------- 试卷排版 ---------------- */
.paper {
display: flex;
flex-direction: column;
flex: 1 1 auto;
min-height: 0;
min-width: 0;
}
.paper-head {
flex: 0 0 auto;
padding: 14px 20px 10px;
border-bottom: 1px solid var(--border-soft);
background: var(--surface);
}
.paper-head-main {
min-width: 0;
}
.paper-title {
font-size: 16px;
font-weight: 650;
color: var(--text-strong);
line-height: 1.5;
}
.paper-meta {
margin-top: 2px;
font-size: 12.5px;
color: var(--text-secondary);
line-height: 1.7;
}
.paper-head-side {
flex-shrink: 0;
}
.paper-score {
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 0 12px;
border-inline-start: 1px solid var(--border-soft);
}
.paper-score-value {
font-size: 22px;
font-weight: 700;
line-height: 1.1;
color: var(--brand);
font-variant-numeric: tabular-nums;
}
.paper-score-total {
font-size: 13px;
font-weight: 500;
color: var(--text-secondary);
}
.paper-score-label {
font-size: 11.5px;
color: var(--text-secondary);
}
.paper-head-tools {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-top: 12px;
}
.paper-body {
flex: 1 1 auto;
min-height: 0;
overflow: auto;
padding: 14px 18px 24px;
}
/* 一道题 */
.paper-question {
display: flex;
gap: 12px;
padding: 14px 10px 16px;
border-radius: 12px;
transition: background 0.16s ease, box-shadow 0.16s ease;
}
.paper-question + .paper-question {
border-top: 1px dashed var(--border-soft);
border-radius: 12px 12px 0 0;
}
.paper-question--active {
background: var(--surface-2);
box-shadow: inset 3px 0 0 var(--brand);
}
.paper-question-rail {
flex: 0 0 auto;
padding-top: 1px;
}
.paper-question-no {
display: inline-grid;
place-items: center;
min-width: 28px;
height: 28px;
padding: 0 6px;
border-radius: 50%;
background: var(--track);
color: var(--text-strong);
font-size: 13px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.paper-question--correct .paper-question-no {
background: var(--success-soft);
color: var(--success-soft-border);
color: #16a34a;
}
.paper-question--wrong .paper-question-no {
background: var(--danger-soft);
color: #dc2626;
}
.paper-question-main {
flex: 1 1 auto;
min-width: 0;
}
.paper-question-head {
min-height: 24px;
margin-bottom: 2px;
}
.paper-question-actions {
margin-inline-start: auto;
}
.paper-stem {
font-size: 15.5px;
font-weight: 600;
line-height: 1.85;
color: var(--text-strong);
margin: 6px 0 12px;
}
.paper-options {
max-width: 760px;
}
.paper-answer {
margin-top: 12px;
padding: 10px 12px;
border-radius: 10px;
background: var(--surface-2);
border: 1px solid var(--border-soft);
max-width: 760px;
}
.paper-explain-body {
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed var(--border-soft);
line-height: 1.85;
color: var(--text-strong);
}
.paper-explain-toggle {
border: 0;
background: transparent;
padding: 0;
cursor: pointer;
color: var(--brand);
font-size: 13px;
}
/* 答题卡 */
.answer-sheet {
display: flex;
align-items: center;
gap: 14px;
flex-wrap: wrap;
}
.answer-sheet-chips {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
.answer-chip {
position: relative;
display: inline-flex;
align-items: center;
gap: 3px;
min-width: 32px;
height: 30px;
padding: 0 8px;
border: 1px solid var(--border-soft);
border-radius: 9px;
background: var(--surface);
color: var(--text-strong);
font-size: 13px;
font-variant-numeric: tabular-nums;
cursor: pointer;
transition: border-color 0.16s ease, background 0.16s ease, transform 0.16s ease;
}
.answer-chip:hover {
transform: translateY(-1px);
border-color: var(--brand);
}
.answer-chip--active {
border-color: var(--brand);
box-shadow: 0 0 0 2px var(--brand-soft);
}
.answer-chip-icon {
font-size: 11px;
}
.answer-chip--correct {
background: var(--success-soft);
border-color: var(--success-soft-border);
color: #16a34a;
}
.answer-chip--wrong {
background: var(--danger-soft);
border-color: var(--danger-soft-border);
color: #dc2626;
}
.answer-chip--done {
border-color: rgba(91, 92, 226, 0.45);
color: var(--brand);
}
.answer-chip--pending {
border-style: dashed;
color: var(--text-muted);
}
.answer-sheet-legend {
display: flex;
align-items: center;
gap: 10px;
font-size: 12px;
color: var(--text-secondary);
}
.answer-sheet-legend-toggle {
border: 0;
background: transparent;
padding: 0;
cursor: pointer;
color: var(--text-secondary);
font-size: 12px;
text-decoration: underline dotted;
}
.answer-sheet-legend-items {
display: flex;
}
.answer-sheet-legend-items span {
display: inline-flex;
align-items: center;
gap: 4px;
}
.answer-dot {
width: 9px;
height: 9px;
border-radius: 3px;
display: inline-block;
}
.answer-dot--correct {
background: var(--success-soft);
border: 1px solid #16a34a;
}
.answer-dot--wrong {
background: var(--danger-soft);
border: 1px solid #dc2626;
}
.answer-dot--done {
background: var(--brand-soft);
border: 1px solid var(--brand);
}
.answer-dot--pending {
background: transparent;
border: 1px dashed var(--text-muted);
}
.answer-sheet-summary {
margin-inline-start: auto;
display: flex;
align-items: center;
gap: 10px;
font-size: 12.5px;
color: var(--text-secondary);
}
/* 答题中的提交条 */
.paper-submit {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
/* 题库卡片里的章节导航 */
.chapter-nav-count {
font-variant-numeric: tabular-nums;
color: var(--text-secondary);
font-size: 12px;
}
/* 试卷头部:标题与视图切换并排 */
.paper-head-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
/* 题干下方的主体(选项 / 作答控件) */
.paper-body-slot {
min-width: 0;
}
/* 可折叠解析 */
.paper-explain {
margin-top: 12px;
max-width: 760px;
}
.paper-explain-caret {
margin-inline-start: 6px;
font-size: 10px;
color: var(--text-muted);
}
/* 我的作答 / 正确答案 对照 */
.answer-compare {
align-items: center;
row-gap: 4px;
}
.answer-chip-no {
font-variant-numeric: tabular-nums;
}
/* 清单里的可点分组(教材名)与更紧凑的子项(章节) */
.master-group-button {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
padding: 5px 8px;
border: 0;
border-radius: 8px;
background: transparent;
color: var(--text-strong);
font: inherit;
text-align: start;
cursor: pointer;
transition: background 0.16s ease, color 0.16s ease;
}
.master-group-button:hover {
background: var(--surface-hover);
}
.master-group-button--active {
color: var(--brand);
}
.master-item--tight {
padding: 7px 10px;
margin-bottom: 2px;
border-radius: 8px;
}
.master-item--tight .master-item-title {
font-weight: 500;
font-size: 13px;
}
/* 侧栏底部的小字提示 */
.aside-hint {
margin-top: 14px;
padding: 10px 4px 0;
border-top: 1px dashed var(--border-soft);
line-height: 1.7;
}
/* 生成任务进度条(挂在分屏上方,高度变化由 ResizeObserver 收敛) */
.bank-task {
margin-bottom: 12px;
padding: 12px 16px 4px;
background: var(--surface);
border: 1px solid var(--border-soft);
border-radius: 12px;
}
/* 成绩单摘要 */
.result-score {
display: flex;
align-items: baseline;
gap: 8px;
margin-bottom: 8px;
}
.result-score-value {
font-size: 30px;
font-weight: 700;
line-height: 1.1;
color: var(--brand);
font-variant-numeric: tabular-nums;
}
.result-score-total {
font-size: 15px;
font-weight: 500;
color: var(--text-secondary);
}
.result-score-label {
font-size: 12px;
color: var(--text-secondary);
}
.result-knowledge {
margin-top: 14px;
padding-top: 4px;
border-top: 1px dashed var(--border-soft);
}
.result-knowledge-row {
gap: 8px;
padding: 4px 0;
font-size: 13px;
}
.result-knowledge-name {
flex: 1 1 auto;
min-width: 0;
color: var(--text-strong);
}
/* 章节测试:组卷条件收成上方一条窄栏,高度留给答题工作台 */
.test-launcher {
padding: 12px 14px;
background: var(--surface);
border: 1px solid var(--border-soft);
border-radius: 14px;
box-shadow: 0 1px 2px rgba(31, 32, 51, 0.04);
}
.test-launcher-row {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.test-launcher-select {
width: 260px;
max-width: 100%;
}
.test-launcher-meta {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed var(--border-soft);
}
.test-launcher-tags {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
}
.test-launcher-note {
flex: 1 1 240px;
min-width: 0;
font-size: 12.5px;
}
@media (max-width: 1200px) {
.paper-head {
padding: 12px 14px 8px;
}
.paper-body {
padding: 14px 12px 26px;
}
.paper-question {
padding: 16px 6px 18px;
}
}