Merge branch 'lm/fix/stlye'

This commit is contained in:
tangweijie 2026-02-04 18:56:03 +08:00
commit e8aefff16b
2 changed files with 269 additions and 138 deletions

View File

@ -1,20 +1,41 @@
<template> <template>
<Dialog style="display: none;" :title="'评估报告'" v-model="dialogVisible" width="900px"> <Dialog style="display: none" :title="'评估报告'" v-model="dialogVisible" width="900px">
<div v-loading="loading" class="report-edit-container" ref="previewRef"> <div v-loading="loading" class="report-edit-container" ref="previewRef">
<template v-if="selectedReport"> <template v-if="selectedReport">
<div class="basic-info-title">{{ selectedReport.templateName }}</div> <div class="basic-info-title">{{ selectedReport.templateName }}</div>
<!-- 基本信息区 --> <!-- 基本信息区 -->
<div class="basic-info-section"> <div class="basic-info-section">
<div class="basic-info-item">服刑人员{{ selectedReport.prisonerName }} ({{ selectedReport.prisonerNo }})</div> <div class="basic-info-item"
>服刑人员{{ selectedReport.prisonerName }} ({{ selectedReport.prisonerNo }})</div
>
<div class="basic-info-item">监区{{ selectedReport.areaName || '-' }}</div> <div class="basic-info-item">监区{{ selectedReport.areaName || '-' }}</div>
<div class="basic-info-item">评估日期{{ formatDateTime(selectedReport.evaluationDate, 'YYYY-MM-DD') }}</div> <div class="basic-info-item"
<div class="basic-info-item">风险等级{{ getDictLabel(DICT_TYPE.PRISON_RISK_LEVEL, selectedReport.riskLevel) }}</div> >评估日期{{ formatDateTime(selectedReport.evaluationDate, 'YYYY-MM-DD') }}</div
<div class="basic-info-item">状态{{ getDictLabel(DICT_TYPE.PRISON_REPORT_STATUS, selectedReport.status) }}</div> >
<div class="basic-info-item"
>风险等级{{
getDictLabel(DICT_TYPE.PRISON_RISK_LEVEL, selectedReport.riskLevel)
}}</div
>
<div class="basic-info-item"
>状态{{ getDictLabel(DICT_TYPE.PRISON_REPORT_STATUS, selectedReport.status) }}</div
>
</div> </div>
<div v-for="item in dimensionAnalysisPanelRef" :key="item.id" class="dimension-item"> <div
<div class="dimension-item-title">{{ item.name }}</div> v-for="(item, index) in dimensionAnalysisPanelRef"
<div style="white-space: pre-line; line-height: 1.5;">{{ item.aiAnalysis?.replace(/## 综合分析建议\n\n/g, '') }}</div> :key="item.id"
class="dimension-item"
>
<div class="dimension-item-title"
>{{ ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'][index] }}{{
item.name
}}</div
>
<div style="white-space: pre-line; line-height: 1.5">{{
// '##' CRLF/LF
item.aiAnalysis?.replace(/(^|\r?\n)##.*?\r?\n\r?\n/gm, '$1')
}}</div>
</div> </div>
</template> </template>
@ -32,7 +53,14 @@
import { DICT_TYPE, getDictLabel } from '@/utils/dict' import { DICT_TYPE, getDictLabel } from '@/utils/dict'
import { formatDateTime } from '@/utils/formatTime' import { formatDateTime } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { ReportApi, ReportVO, DimensionDataApi, DimensionDataVO, DimensionApi, DimensionVO } from '@/api/prison/evaluation-report' import {
ReportApi,
ReportVO,
DimensionDataApi,
DimensionDataVO,
DimensionApi,
DimensionVO
} from '@/api/prison/evaluation-report'
import { PrisonerApi } from '@/api/prison/prisoner' import { PrisonerApi } from '@/api/prison/prisoner'
import { asBlob } from 'html-docx-js-typescript' import { asBlob } from 'html-docx-js-typescript'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
@ -78,7 +106,8 @@ const loadReportDetail = async (id: number) => {
try { try {
selectedReport.value = await ReportApi.getReport(id) selectedReport.value = await ReportApi.getReport(id)
dimensionDataList.value = await DimensionDataApi.getDimensionDataListByReportId(id) dimensionDataList.value = await DimensionDataApi.getDimensionDataListByReportId(id)
drawerTitle.value = selectedReport.value?.title || `${selectedReport.value?.prisonerName} - 评估报告` drawerTitle.value =
selectedReport.value?.title || `${selectedReport.value?.prisonerName} - 评估报告`
// //
if (selectedReport.value?.prisonerId && !selectedReport.value.areaName) { if (selectedReport.value?.prisonerId && !selectedReport.value.areaName) {
@ -92,15 +121,16 @@ const loadReportDetail = async (id: number) => {
// //
if (selectedReport.value?.templateId) { if (selectedReport.value?.templateId) {
try { try {
const dimensionList = await DimensionApi.getDimensionsByTemplateId(selectedReport.value.templateId) const dimensionList = await DimensionApi.getDimensionsByTemplateId(
selectedReport.value.templateId
)
if (dimensionList && dimensionList.length > 0) { if (dimensionList && dimensionList.length > 0) {
console.log(dimensionList); console.log(dimensionList)
dimensions.value = dimensionList dimensions.value = dimensionList
} else { } else {
// 使 // 使
dimensions.value = getDefaultDimensions(selectedReport.value.templateId) dimensions.value = getDefaultDimensions(selectedReport.value.templateId)
} }
} catch { } catch {
dimensions.value = getDefaultDimensions(selectedReport.value.templateId) dimensions.value = getDefaultDimensions(selectedReport.value.templateId)
} }
@ -108,11 +138,11 @@ const loadReportDetail = async (id: number) => {
if (selectedReport.value?.id && dimensions.value.length > 0) { if (selectedReport.value?.id && dimensions.value.length > 0) {
const list = await DimensionDataApi.getDimensionDataListByReportId(selectedReport.value.id) const list = await DimensionDataApi.getDimensionDataListByReportId(selectedReport.value.id)
console.log(list, dimensions.value); console.log(list, dimensions.value)
dimensionAnalysisPanelRef.value = dimensions.value.map(item => { dimensionAnalysisPanelRef.value = dimensions.value.map((item) => {
return { return {
...item, ...item,
aiAnalysis: list.find(analys => analys.dimensionId === item.id)?.aiAnalysis aiAnalysis: list.find((analys) => analys.dimensionId === item.id)?.aiAnalysis
} }
}) })
} }
@ -127,11 +157,51 @@ const loadReportDetail = async (id: number) => {
/** 获取默认维度配置 */ /** 获取默认维度配置 */
const getDefaultDimensions = (templateId: number): DimensionVO[] => { const getDefaultDimensions = (templateId: number): DimensionVO[] => {
return [ return [
{ id: 1, templateId, name: '基本信息', dimensionType: 1, aiEnabled: 0, status: 0, dataSources: ['prisoner'] }, {
{ id: 2, templateId, name: '犯罪情况分析', dimensionType: 1, aiEnabled: 1, status: 0, dataSources: ['prisoner', 'risk'] }, id: 1,
{ id: 3, templateId, name: '服刑表现评估', dimensionType: 1, aiEnabled: 1, status: 0, dataSources: ['score', 'violation', 'reward'] }, templateId,
{ id: 4, templateId, name: '消费行为分析', dimensionType: 1, aiEnabled: 1, status: 0, dataSources: ['consumption'] }, name: '基本信息',
{ id: 5, templateId, name: '综合评估结论', dimensionType: 1, aiEnabled: 1, status: 0, dataSources: ['prisoner', 'psychology'] } dimensionType: 1,
aiEnabled: 0,
status: 0,
dataSources: ['prisoner']
},
{
id: 2,
templateId,
name: '犯罪情况分析',
dimensionType: 1,
aiEnabled: 1,
status: 0,
dataSources: ['prisoner', 'risk']
},
{
id: 3,
templateId,
name: '服刑表现评估',
dimensionType: 1,
aiEnabled: 1,
status: 0,
dataSources: ['score', 'violation', 'reward']
},
{
id: 4,
templateId,
name: '消费行为分析',
dimensionType: 1,
aiEnabled: 1,
status: 0,
dataSources: ['consumption']
},
{
id: 5,
templateId,
name: '综合评估结论',
dimensionType: 1,
aiEnabled: 1,
status: 0,
dataSources: ['prisoner', 'psychology']
}
] ]
} }
@ -189,40 +259,36 @@ const exportToWord = async () => {
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<style> <style>
/* 使用 pt 单位以避免 Word/WPS 在 px->pt 换算时产生差异 */
body { body {
font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif; font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 14px; font-size: 11pt;
line-height: 1.6; line-height: 1.5;
margin: 20px;
padding: 20px;
} }
.basic-info-title{ .basic-info-title{
font-family: '黑体', 'Microsoft YaHei', SimSun, Arial, sans-serif; font-size: 18pt;
font-size: 21px;
font-weight: 700; font-weight: 700;
color: black; color: black;
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 15pt;
} }
.basic-info-section { .basic-info-section {
padding: 15px 20px;
color: black; color: black;
font-size: 12px; font-size: 11pt;
} }
.basic-info-item{ .basic-info-item{
margin-right: 30px; margin-right: 25pt;
} }
.dimension-item { .dimension-item {
padding: 0 40px; font-size: 11pt;
font-size: 12px;
color: black; color: black;
} }
.dimension-item-title { .dimension-item-title {
font-size: 21px; font-size: 15pt;
padding: 15px 0;
font-weight: 500; font-weight: 500;
color: black; color: black;
margin-top: 15pt;
} }
</style> </style>
</head> </head>
@ -269,7 +335,7 @@ defineExpose({ open })
color: black; color: black;
font-size: 14px; font-size: 14px;
} }
.basic-info-item{ .basic-info-item {
margin-right: 30px; margin-right: 30px;
} }

View File

@ -1,5 +1,11 @@
<template> <template>
<Dialog style="display: none;" title="问卷预览" v-model="dialogVisible" width="900px" :fullscreen="false"> <Dialog
style="display: none"
title="问卷预览"
v-model="dialogVisible"
width="900px"
:fullscreen="false"
>
<div ref="previewRef" class="questionnaire-preview" v-loading="loading"> <div ref="previewRef" class="questionnaire-preview" v-loading="loading">
<!-- 问卷头部信息 --> <!-- 问卷头部信息 -->
<h1 class="preview-header">{{ recordInfo?.questionnaireName }}</h1> <h1 class="preview-header">{{ recordInfo?.questionnaireName }}</h1>
@ -18,22 +24,23 @@
<!-- 问题列表按分区显示 --> <!-- 问题列表按分区显示 -->
<div class="preview-questions"> <div class="preview-questions">
<template v-for="partition in partitions" :key="partition.name || 'default'"> <template v-for="(partition, index) in partitions" :key="partition.name || 'default'">
<!-- 分区标题 --> <!-- 分区标题 -->
<div v-if="partition.name" class="partition-title"> <div v-if="partition.name" class="partition-title">
{{ ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'][index] }}
{{ partition.name }} {{ partition.name }}
<span class="question-count">({{ partition.questions.length }} 道题)</span> <span class="question-count">({{ partition.questions.length }} 道题)</span>
</div> </div>
<!-- 问题列表 --> <!-- 问题列表 -->
<div class="question-items"> <div class="question-items">
<div <div
v-for="(questionWithAnswer, index) in partition.questions" v-for="(questionWithAnswer, index) in partition.questions"
:key="questionWithAnswer.question.id" :key="questionWithAnswer.question.id"
class="question-item" class="question-item"
> >
<span class="question-index">{{ index + 1 }}.</span> <span class="question-index">{{ index + 1 }}.</span>
<span class="question-title">{{ questionWithAnswer.question.title }}</span> <span class="question-title">{{ questionWithAnswer.question.title }}</span>
<!-- 帮助说明 --> <!-- 帮助说明 -->
<span v-if="questionWithAnswer.question.helpText" class="question-help-inline"> <span v-if="questionWithAnswer.question.helpText" class="question-help-inline">
@ -41,25 +48,50 @@
</span> </span>
<!-- 单选/多选题 --> <!-- 单选/多选题 -->
<span v-if="questionWithAnswer.question.type === 1 || questionWithAnswer.question.type === 2" class="question-options-inline"> <span
v-if="
questionWithAnswer.question.type === 1 || questionWithAnswer.question.type === 2
"
class="question-options-inline"
>
<span <span
v-for="option in getQuestionOptions(questionWithAnswer.question)" v-for="option in getQuestionOptions(questionWithAnswer.question)"
:key="option.label" :key="option.label"
class="option-item" class="option-item"
> >
<span v-if="questionWithAnswer.question.type === 1 && questionWithAnswer.answer?.answerText?.trim() === option.label"> <span
v-if="
questionWithAnswer.question.type === 1 &&
questionWithAnswer.answer?.answerText?.trim() === option.label
"
>
{{ option.label }} {{ option.label }}
</span> </span>
<span v-if="questionWithAnswer.question.type === 1 && questionWithAnswer.answer?.answerText?.trim() !== option.label"> <span
v-if="
questionWithAnswer.question.type === 1 &&
questionWithAnswer.answer?.answerText?.trim() !== option.label
"
>
{{ option.label }} {{ option.label }}
</span> </span>
<span v-if="questionWithAnswer.question.type === 2 && getSelectedLabels(questionWithAnswer.answer).includes(option.label)"> <span
v-if="
questionWithAnswer.question.type === 2 &&
getSelectedLabels(questionWithAnswer.answer).includes(option.label)
"
>
{{ option.label }} {{ option.label }}
</span> </span>
<span v-if="questionWithAnswer.question.type === 2 && !getSelectedLabels(questionWithAnswer.answer).includes(option.label)"> <span
v-if="
questionWithAnswer.question.type === 2 &&
!getSelectedLabels(questionWithAnswer.answer).includes(option.label)
"
>
{{ option.label }} {{ option.label }}
</span> </span>
@ -67,26 +99,48 @@
</span> </span>
<!-- 填空题 --> <!-- 填空题 -->
<span v-else-if="questionWithAnswer.question.type === 3" class="question-input-inline"> <span
v-else-if="questionWithAnswer.question.type === 3"
class="question-input-inline"
>
{{ getAnswerDisplayValue(questionWithAnswer.answer) }} {{ getAnswerDisplayValue(questionWithAnswer.answer) }}
</span> </span>
<!-- 评分题 --> <!-- 评分题 -->
<span v-else-if="questionWithAnswer.question.type === 4" class="question-rating-inline"> <span
<span class="question-input-inline">{{ getAnswerDisplayValue(questionWithAnswer.answer) }}</span> v-else-if="questionWithAnswer.question.type === 4"
class="question-rating-inline"
>
<span class="question-input-inline">{{
getAnswerDisplayValue(questionWithAnswer.answer)
}}</span>
</span> </span>
<!-- 日期题 --> <!-- 日期题 -->
<span v-else-if="questionWithAnswer.question.type === 5" class="question-date-inline"> <span v-else-if="questionWithAnswer.question.type === 5" class="question-date-inline">
<span class="date-info" v-if="getRangeValue(questionWithAnswer.question, 'min') || getRangeValue(questionWithAnswer.question, 'max')"> <span
日期范围{{ getRangeValue(questionWithAnswer.question, 'min') || '无限制' }} ~ {{ getRangeValue(questionWithAnswer.question, 'max') || '无限制' }} class="date-info"
v-if="
getRangeValue(questionWithAnswer.question, 'min') ||
getRangeValue(questionWithAnswer.question, 'max')
"
>
日期范围{{ getRangeValue(questionWithAnswer.question, 'min') || '无限制' }} ~
{{ getRangeValue(questionWithAnswer.question, 'max') || '无限制' }}
</span> </span>
<span class="question-input-inline">{{ getAnswerDisplayValue(questionWithAnswer.answer) }}</span> <span class="question-input-inline">{{
getAnswerDisplayValue(questionWithAnswer.answer)
}}</span>
</span> </span>
<!-- 数字题 --> <!-- 数字题 -->
<span v-else-if="questionWithAnswer.question.type === 6" class="question-number-inline"> <span
<span class="question-input-inline">{{ getAnswerDisplayValue(questionWithAnswer.answer) }}</span> v-else-if="questionWithAnswer.question.type === 6"
class="question-number-inline"
>
<span class="question-input-inline">{{
getAnswerDisplayValue(questionWithAnswer.answer)
}}</span>
</span> </span>
</div> </div>
</div> </div>
@ -137,7 +191,7 @@ const partitions = computed(() => {
questions.value.forEach((q, index) => { questions.value.forEach((q, index) => {
const partName = q.partName || '' const partName = q.partName || ''
const answer = answers.value.find(a => a.questionId === q.id) const answer = answers.value.find((a) => a.questionId === q.id)
if (!partMap.has(partName)) { if (!partMap.has(partName)) {
partMap.set(partName, []) partMap.set(partName, [])
@ -150,12 +204,11 @@ const partitions = computed(() => {
}) })
// //
const sortedParts = Array.from(partMap.entries()) const sortedParts = Array.from(partMap.entries()).sort((a, b) => {
.sort((a, b) => { const sortA = a[1][0]?.question.partSort ?? 0
const sortA = a[1][0]?.question.partSort ?? 0 const sortB = b[1][0]?.question.partSort ?? 0
const sortB = b[1][0]?.question.partSort ?? 0 return sortA - sortB
return sortA - sortB })
})
// //
const result: Array<{ name: string; questions: QuestionWithAnswer[] }> = [] const result: Array<{ name: string; questions: QuestionWithAnswer[] }> = []
@ -184,20 +237,21 @@ const partitions = computed(() => {
/** 根据问题ID获取答案 */ /** 根据问题ID获取答案 */
const getAnswerByQuestionId = (questionId: number): Answer | undefined => { const getAnswerByQuestionId = (questionId: number): Answer | undefined => {
return answers.value.find(a => a.questionId === questionId) return answers.value.find((a) => a.questionId === questionId)
} }
/** 获取答案显示值(兼容不同字段名) */ /** 获取答案显示值(兼容不同字段名) */
const getAnswerDisplayValue = (answer?: Answer): string => { const getAnswerDisplayValue = (answer?: Answer): string => {
if (!answer) return '' if (!answer) return ''
// 使 answerText使 optionIds // 使 answerText使 optionIds
return answer.answerText || answer.optionIds || '-' const value = answer.answerText || answer.optionIds || ''
return String(value).trim().replace(/^["']|["']$/g, '')
} }
/** 问卷类型标签 */ /** 问卷类型标签 */
const getTypeLabel = (type: number) => { const getTypeLabel = (type: number) => {
const options = getIntDictOptions(DICT_TYPE.PRISON_QUESTIONNAIRE_TYPE) const options = getIntDictOptions(DICT_TYPE.PRISON_QUESTIONNAIRE_TYPE)
return options.find(o => o.value === type)?.label || '未知' return options.find((o) => o.value === type)?.label || '未知'
} }
/** 获取问题选项 */ /** 获取问题选项 */
@ -233,11 +287,16 @@ const getRangeValue = (question: Question, key: 'min' | 'max') => {
/** 安全获取多选答案的标签数组 */ /** 安全获取多选答案的标签数组 */
const getSelectedLabels = (answer?: Answer): string[] => { const getSelectedLabels = (answer?: Answer): string[] => {
if (!answer?.answerText) return [] if (!answer?.answerText) return []
return answer.answerText.split(',').map(s => s.trim()) return answer.answerText.split(',').map((s) => s.trim())
} }
/** 判断选项是否被选中(支持单选和多选)- 已废弃,改用模板直接绑定 */ /** 判断选项是否被选中(支持单选和多选)- 已废弃,改用模板直接绑定 */
const isOptionSelected = (answer?: Answer, optionValue?: string, optionLabel?: string, questionType?: number): boolean => { const isOptionSelected = (
answer?: Answer,
optionValue?: string,
optionLabel?: string,
questionType?: number
): boolean => {
if (!answer || !optionValue || !optionLabel) { if (!answer || !optionValue || !optionLabel) {
return false return false
} }
@ -245,7 +304,7 @@ const isOptionSelected = (answer?: Answer, optionValue?: string, optionLabel?: s
// type === 2answerText // type === 2answerText
if (questionType === 2 && answer.answerText && answer.answerText.includes(',')) { if (questionType === 2 && answer.answerText && answer.answerText.includes(',')) {
const answerText = answer.answerText const answerText = answer.answerText
const selectedLabels = answerText.split(',').map(s => s.trim()) const selectedLabels = answerText.split(',').map((s) => s.trim())
return selectedLabels.includes(optionLabel) return selectedLabels.includes(optionLabel)
} }
@ -257,7 +316,7 @@ const isOptionSelected = (answer?: Answer, optionValue?: string, optionLabel?: s
// questionType // questionType
if (answer.answerText && answer.answerText.includes(',')) { if (answer.answerText && answer.answerText.includes(',')) {
const answerText = answer.answerText const answerText = answer.answerText
const selectedLabels = answerText.split(',').map(s => s.trim()) const selectedLabels = answerText.split(',').map((s) => s.trim())
return selectedLabels.includes(optionLabel) return selectedLabels.includes(optionLabel)
} }
@ -266,7 +325,6 @@ const isOptionSelected = (answer?: Answer, optionValue?: string, optionLabel?: s
return false return false
} }
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (recordId: number) => { const open = async (recordId: number) => {
dialogVisible.value = true dialogVisible.value = true
@ -296,7 +354,9 @@ const open = async (recordId: number) => {
if (recordData.questionnaireId) { if (recordData.questionnaireId) {
try { try {
const { QuestionnaireApi } = await import('@/api/prison/questionnaire') const { QuestionnaireApi } = await import('@/api/prison/questionnaire')
questionnaireInfo.value = await QuestionnaireApi.getQuestionnaire(recordData.questionnaireId) questionnaireInfo.value = await QuestionnaireApi.getQuestionnaire(
recordData.questionnaireId
)
} catch (error) { } catch (error) {
console.warn('加载问卷详细信息失败:', error) console.warn('加载问卷详细信息失败:', error)
} }
@ -327,7 +387,11 @@ const exportToWord = async () => {
} }
// HTML // HTML
const previewHTML = previewRef.value.innerHTML let previewHTML = previewRef.value.innerHTML
// WPS
previewHTML = previewHTML.replace(/[\u201C\u201D\u2018\u2019]/g, '') //
previewHTML = previewHTML.replace(/^["']|["']$/gm, '') //
// HTML使 // HTML使
const fullHTML = ` const fullHTML = `
@ -336,108 +400,110 @@ const exportToWord = async () => {
<meta charset="utf-8"> <meta charset="utf-8">
<title>${recordInfo.value?.questionnaireName || '问卷'}</title> <title>${recordInfo.value?.questionnaireName || '问卷'}</title>
<style> <style>
/* 使用 pt 单位以避免 Word/WPS 在 px->pt 换算时产生差异 */
body { body {
font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif; font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 16px; font-size: 11pt;
line-height: 1.6; margin: 15pt;
margin: 20px; padding: 15pt;
padding: 20px;
} }
h1 { h1 {
font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 18pt;
font-weight: 500; font-weight: 500;
color: #000; color: #000;
text-align: center; text-align: center;
} }
.section-title { .section-title {
margin: 15px 0; font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 18px; margin-bottom: 15pt;
font-weight: 500; font-size: 18pt;
font-weight: 700;
color: #000; color: #000;
} }
.description-content { .description-content {
color: #000; color: #000;
line-height: 1.8; font-size: 11pt;
font-size: 16px; margin-bottom: 6pt;
line-height: 1.5;
} }
.instruction-content { .instruction-content {
color: #000; color: #000;
font-size: 18px; font-size: 11pt;
font-weight: 500; font-weight: 500;
line-height: 1.8; margin-bottom: 6pt;
line-height: 1.5;
} }
.partition-title { .partition-title {
margin-bottom: 16px; margin-top: 15pt;
margin-top: 24px;
color: #000; color: #000;
font-size: 17px; font-size: 15pt;
font-weight: 500; font-weight: 500;
} }
.partition-title:first-child { .partition-title:first-child {
margin-top: 0; margin-top: 0;
} }
.question-count { .question-count {
font-size: 14px; font-size: 11pt;
color: #909399; color: #909399;
font-weight: normal; font-weight: normal;
margin-left: 4px; margin-left: 2pt;
} }
.question-item { .question-item {
font-size: 16px; font-size: 11pt;
color: #000; color: #000;
line-height: 1.6; margin-bottom: 8pt;
margin-bottom: 16px; line-height: 1.5;
page-break-inside: avoid; page-break-inside: avoid;
} }
.question-index { .question-index {
margin-right: 4px; margin-right: 2pt;
font-weight: bold;
} }
.question-title { .question-title {
margin-right: 8px; margin-right: 4pt;
} }
.question-help-inline { .question-help-inline {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 3pt;
color: #909399; color: #909399;
font-size: 15px; font-size: 11pt;
padding: 4px 8px;
background: #f4f4f5; background: #f4f4f5;
border-radius: 4px; border-radius: 2pt;
margin-right: 8px; margin-right: 6pt;
} }
.question-options-inline { .question-options-inline {
display: inline-flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 12px; gap: 8pt;
align-items: center; align-items: center;
} }
.option-item { .option-item {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 3pt;
} }
.question-rating-inline, .question-rating-inline,
.question-date-inline, .question-date-inline,
.question-number-inline { .question-number-inline {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 12px; gap: 8pt;
flex-wrap: wrap; flex-wrap: wrap;
margin-left: 8px; margin-left: 3pt;
} }
.rating-info, .rating-info,
.date-info, .date-info,
.number-info { .number-info {
display: inline-flex; display: inline-flex;
gap: 16px; gap: 11pt;
color: #909399; color: #909399;
font-size: 13px; font-size: 11pt;
} }
.question-input-inline { .question-input-inline {
color: #000; color: #000;
font-size: 16px; font-size: 11pt;
line-height: 2.2; line-height: 1.5;
text-decoration: underline; text-decoration: underline;
} }
</style> </style>
@ -475,100 +541,99 @@ defineExpose({ open, exportToWord })
} }
h1 { h1 {
font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 18pt;
font-weight: 500; font-weight: 500;
color: #000; color: #000;
text-align: center; text-align: center;
} }
.section-title { .section-title {
margin: 15px 0; font-family: 'Microsoft YaHei', '微软雅黑', SimSun, Arial, sans-serif;
font-size: 16px; margin-bottom: 15pt;
font-weight: 500; font-size: 18pt;
font-weight: 700;
color: #000; color: #000;
} }
.description-content { .description-content {
color: #000; color: #000;
line-height: 1.8; line-height: 3;
font-size: 14px; font-size: 11pt;
} }
.instruction-content { .instruction-content {
color: #000; color: #000;
font-size: 16px; font-size: 11pt;
font-weight: 500; font-weight: 500;
line-height: 1.8; line-height: 3;
} }
.partition-title { .partition-title {
margin-bottom: 16px; margin-top: 15pt;
margin-top: 24px;
color: #000; color: #000;
font-size: 15px; font-size: 15pt;
font-weight: 500; font-weight: 500;
} }
.partition-title:first-child { .partition-title:first-child {
margin-top: 0; margin-top: 0;
} }
.question-count { .question-count {
font-size: 12px; font-size: 11pt;
color: #909399; color: #909399;
font-weight: normal; font-weight: normal;
margin-left: 4px; margin-left: 2pt;
} }
.question-item { .question-item {
font-size: 14px; font-size: 11pt;
color: #000; color: #000;
line-height: 1.6; line-height: 3;
margin-bottom: 16px;
page-break-inside: avoid; page-break-inside: avoid;
} }
.question-index { .question-index {
margin-right: 4px; margin-right: 2pt;
font-weight: bold;
} }
.question-title { .question-title {
margin-right: 8px; margin-right: 4pt;
} }
.question-help-inline { .question-help-inline {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 6px; gap: 3pt;
color: #909399; color: #909399;
font-size: 13px; font-size: 11pt;
padding: 4px 8px;
background: #f4f4f5; background: #f4f4f5;
border-radius: 4px; border-radius: 2pt;
margin-right: 8px; margin-right: 6pt;
} }
.question-options-inline { .question-options-inline {
display: inline-flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 12px; gap: 8pt;
align-items: center; align-items: center;
} }
.option-item { .option-item {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 8px; gap: 3pt;
} }
.question-rating-inline, .question-rating-inline,
.question-date-inline, .question-date-inline,
.question-number-inline { .question-number-inline {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 12px; gap: 8pt;
flex-wrap: wrap; flex-wrap: wrap;
margin-left: 8px; margin-left: 3pt;
} }
.rating-info, .rating-info,
.date-info, .date-info,
.number-info { .number-info {
display: inline-flex; display: inline-flex;
gap: 16px; gap: 11pt;
color: #909399; color: #909399;
font-size: 13px; font-size: 11pt;
} }
.question-input-inline { .question-input-inline {
color: #000; color: #000;
font-size: 14px; font-size: 11pt;
line-height: 2.2; line-height: 3;
text-decoration: underline; text-decoration: underline;
} }
</style> </style>