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

## 主要改进

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

View File

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

View File

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