优化试卷打印页面布局和分页控制

## 主要改进

### 1. 题型标题和分值说明显示优化
- 将 Ant Design Text 组件改为原生 span 元素,确保在打印时不换行
- 将分值说明嵌套到题型标题内部,强制同行显示
- 适用于所有题型:填空题、判断题、单选题、多选题、简答题、论述题

### 2. 打印分页控制优化
- 添加 page-break-after: avoid 和 page-break-inside: avoid 到关键元素
- 试卷标题和考试说明保持在同一页
- 考试说明和填空题不分页
- 题型标题和第一道题保持在同一页
- 每道题目的所有部分(题干、选项、答题区域)保持完整,不被分页打断
- 题型之间尽量紧密排列,减少空白

### 3. 样式细节调整
- 题型标题使用 flex 布局,确保标题和说明在同一行
- 统一使用 marginLeft: 8px 作为标题和说明之间的间距
- 保持 A4 纸张 1cm 页边距设置

## 修改文件
- web/src/pages/ExamPrint.module.less - 打印样式优化
- web/src/pages/ExamPrint.tsx - 题型标题结构调整

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
燕陇琪 2025-12-01 23:04:39 +08:00
parent 62281b5047
commit 8d10ebc327
3 changed files with 31 additions and 14 deletions

View File

@ -205,7 +205,7 @@
display: none !important;
}
// A4纸张设置 - 增加边距以确保圆角不被遮挡
// A4纸张设置
@page {
size: A4;
margin: 1cm;
@ -225,6 +225,9 @@
.paperHeader {
margin-bottom: 6px;
padding-bottom: 4px;
// 防止试卷标题和考试说明分页
page-break-after: avoid;
page-break-inside: avoid;
.paperTitle {
font-size: 16pt !important;
@ -256,6 +259,9 @@
overflow: visible;
// 添加一些内边距确保圆角有空间显示
padding: 2px;
// 防止考试说明和填空题分页
page-break-after: avoid;
page-break-inside: avoid;
:global(.ant-card-body) {
padding: 6px;
@ -280,10 +286,18 @@
.questionGroup {
margin-bottom: 8px;
// 防止题型组内部分页
page-break-inside: avoid;
// 尽量让下一个题型紧接着显示
page-break-after: avoid;
.groupHeader {
display: flex;
align-items: baseline;
margin-bottom: 4px;
padding-bottom: 2px;
// 确保题型标题和第一道题在同一页
page-break-after: avoid;
.groupTitle {
font-size: 12pt;
@ -291,12 +305,15 @@
.groupScore {
font-size: 10pt;
margin-left: 8px;
}
}
}
.questionItem {
margin-bottom: 6px;
// 防止题目内部分页,保持题目完整性
page-break-inside: avoid;
.questionContent {
margin-bottom: 3px;

View File

@ -352,14 +352,14 @@ const ExamPrint: React.FC = () => {
return (
<div key={type} className={styles.questionGroup}>
<div className={styles.groupHeader}>
<Text className={styles.groupTitle}>
<span className={styles.groupTitle}>
{TYPE_NAME[type]}
</Text>
{TYPE_SCORE[type] > 0 && (
<Text type="secondary" className={styles.groupScore}>
{questions.length}{TYPE_SCORE[type]}{totalScore}
</Text>
)}
{TYPE_SCORE[type] > 0 && (
<span className={styles.groupScore} style={{ marginLeft: '8px' }}>
{questions.length}{TYPE_SCORE[type]}{totalScore}
</span>
)}
</span>
</div>
<div className={styles.questionsList}>
{questions.map((question, index) => {
@ -464,12 +464,12 @@ const ExamPrint: React.FC = () => {
{essayQuestions.length > 0 && (
<div className={styles.questionGroup}>
<div className={styles.groupHeader}>
<Text className={styles.groupTitle}>
<span className={styles.groupTitle}>
{TYPE_NAME['ordinary-essay']}
</Text>
<Text type="secondary" className={styles.groupScore}>
219
</Text>
<span className={styles.groupScore} style={{ marginLeft: '8px' }}>
219
</span>
</span>
</div>
<div className={styles.questionsList}>
{essayQuestions.map((question, index) => renderEssay(question, index))}

View File

@ -31,7 +31,7 @@ export default defineConfig({
port: 3000,
proxy: {
'/api': {
target: 'https://ankao.yuchat.top',
target: 'http://127.0.0.1:8080',
changeOrigin: true,
},
},