weizong song 3 months ago
parent 7b34f3f962
commit 06a3c4ad5a

@ -7,14 +7,18 @@
<!-- 已选择会议纪要 -->
<div v-if="selectedMeetingMinute" class="selected-item selected-oa">
<el-icon class="item-icon"><Document /></el-icon>
<!-- 如果有附件URL链接到附件否则显示普通文本 -->
<el-link
v-if="selectedMeetingMinute.file_url"
type="primary"
:underline="false"
class="item-title item-title--link"
@click.prevent="handleViewSelectedDetail"
:href="selectedMeetingMinute.file_url"
target="_blank"
>
{{ selectedMeetingMinute.title }}
</el-link>
<span v-else class="item-title">{{ selectedMeetingMinute.title }}</span>
<el-button
type="primary"
link
@ -600,7 +604,8 @@ watch(() => props.modelValue, (newVal) => {
inputMode.value = 'oa_meeting_minutes'
selectedMeetingMinute.value = {
id: newVal.meeting_minute_id,
title: newVal.title || '会议纪要'
title: newVal.title || '会议纪要',
file_url: newVal.file_url || null
}
// meeting_minute_id
if (newVal.meeting_minute_id && props.readonly) {
@ -721,7 +726,11 @@ const confirmSelect = () => {
return
}
selectedMeetingMinute.value = selectedRow.value
// selectedMeetingMinute file_url
selectedMeetingMinute.value = {
...selectedRow.value,
file_url: null // null
}
const value = {
mode: 'oa_meeting_minutes',
meeting_minute_id: selectedRow.value.id,
@ -736,6 +745,8 @@ const confirmSelect = () => {
const file = detail.files_details[0]
value.file_url = file.url
value.file_name = file.original_name
// selectedMeetingMinute便
selectedMeetingMinute.value.file_url = file.url
}
emit('update:modelValue', value)
})

@ -13,27 +13,25 @@
<!-- 普通字段区域 -->
<template v-if="section.fields && Array.isArray(section.fields)">
<table class="info-table">
<tr
v-for="field in getVisibleFields(section)"
:key="field.key || field.element_id"
>
<td class="label">{{ field.label || field.name || '-' }}</td>
<td class="value">
<template v-if="getFieldValue(field)">
<!-- 文本类型 -->
<span v-if="field.element_type === 'text' || field.element_type === 'textarea'">
{{ getFieldValue(field) }}
</span>
<!-- 数字类型 -->
<span v-else-if="field.element_type === 'number'">
{{ formatNumber(getFieldValue(field)) }}
</span>
<!-- 日期类型 -->
<span v-else-if="field.element_type === 'date'">
{{ formatDate(getFieldValue(field)) }}
</span>
<!-- 勾选清单类型 -->
<div v-else-if="field.element_type === 'checklist'" class="readonly-checklist">
<template v-for="field in getVisibleFields(section)" :key="field.key || field.element_id">
<tr>
<td class="label">{{ field.label || field.name || '-' }}</td>
<td class="value">
<template v-if="getFieldValue(field)">
<!-- 文本类型 -->
<span v-if="field.element_type === 'text' || field.element_type === 'textarea'">
{{ getFieldValue(field) }}
</span>
<!-- 数字类型 -->
<span v-else-if="field.element_type === 'number'">
{{ formatNumber(getFieldValue(field)) }}
</span>
<!-- 日期类型 -->
<span v-else-if="field.element_type === 'date'">
{{ formatDate(getFieldValue(field)) }}
</span>
<!-- 勾选清单类型 -->
<div v-else-if="field.element_type === 'checklist'" class="readonly-checklist">
<!-- 有配置 options"勾选/备注"过滤展示 -->
<template v-if="Array.isArray(getChecklistOptions(field)) && getChecklistOptions(field).length">
<div
@ -198,8 +196,27 @@
</span>
</template>
<span v-else class="empty-value">-</span>
</td>
</tr>
</td>
</tr>
<!-- 会议纪要若唯一附件为 PDF则在本行后追加一个通栏行展示 PDF尽量拉宽 -->
<tr
v-if="field.element_type === 'meeting_minutes' && getMeetingMinutesPdfUrl(field)"
class="meeting-minutes-pdf-row"
>
<td class="value meeting-minutes-pdf-td" colspan="2">
<div
class="print-file-item print-pdf meeting-minutes-pdf"
:data-pdf-id="`planned_meeting_minutes_${field.element_id || field.key}`"
:data-pdf-url="getMeetingMinutesPdfUrl(field)"
>
<div class="pdf-pages-container">
<div class="pdf-loading">PDF 加载中...</div>
</div>
</div>
</td>
</tr>
</template>
</table>
</template>
@ -389,6 +406,35 @@ const getFieldValue = (field) => {
return null
}
// PDF URL JSON
const getMeetingMinutesPdfUrl = (field) => {
if (!field || field.element_type !== 'meeting_minutes') return null
const rawVal = getFieldValue(field)
if (rawVal === null || rawVal === undefined || rawVal === '') return null
let v = rawVal
if (typeof v === 'string') {
try {
const parsed = JSON.parse(v)
if (parsed && typeof parsed === 'object') v = parsed
} catch {
// ignore
}
}
if (!v || typeof v !== 'object') return null
const url = (v.file_url || v.url || '').toString().trim()
if (!url) return null
const name = (v.file_name || v.name || '').toString().trim()
const extFromName = name.includes('.') ? name.split('.').pop() : ''
const extFromUrl = url.split('?')[0].split('#')[0].split('.').pop()
const ext = String(extFromName || extFromUrl || '').toLowerCase()
return ext === 'pdf' ? url : null
}
//
const isChecklistChecked = (value, optionValue) => {
if (!value) return false

@ -107,7 +107,6 @@
<el-table-column prop="apply_date" label="申请日期" width="120" />
<el-table-column prop="perform_period" label="合同履行期" width="150" show-overflow-tooltip />
<el-table-column prop="pay_method" label="付款方式" width="120" show-overflow-tooltip />
<el-table-column prop="fund_source" label="资金来源" width="150" show-overflow-tooltip />
<el-table-column prop="tender_agent" label="招标代理" width="150" show-overflow-tooltip />
<el-table-column prop="purchase_method_id" label="采购方式" width="120" show-overflow-tooltip>
<template #default="{ row }">
@ -134,11 +133,19 @@
<el-tag v-else type="info" size="small"></el-tag>
</template>
</el-table-column>
<el-table-column prop="fund_source" label="项目经费来源" width="200" show-overflow-tooltip>
<el-table-column prop="fund_source" label="计划资金来源" width="200" show-overflow-tooltip>
<template #default="{ row }">
{{ row.fund_source_budget_data?.name || row.fund_source || '-' }}
</template>
</el-table-column>
<el-table-column prop="actual_fund_sources" label="实际资金来源" width="300" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row.actual_fund_sources && row.actual_fund_sources.length > 0">
{{ row.actual_fund_sources.join(' | ') }}
</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="owner_department_id" label="科室" width="150" show-overflow-tooltip>
<template #default="{ row }">
{{ getDepartmentName(row.owner_department_id) }}
@ -176,8 +183,9 @@
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="操作" width="180" fixed="right">
<el-table-column label="操作" width="240" fixed="right">
<template #default="{ row }">
<el-button type="info" link @click="openViewDialog(row)"></el-button>
<el-button type="primary" link @click="openForm(row)"></el-button>
<el-button type="danger" link @click="handleDelete(row)"></el-button>
</template>
@ -482,6 +490,112 @@
</el-form>
</el-drawer>
<!-- 查看对话框 -->
<el-dialog v-model="viewDialogVisible" title="合同详情" width="80%" :close-on-click-modal="false">
<div v-if="viewData" class="contract-view-content">
<el-descriptions :column="2" border>
<el-descriptions-item label="合同编号">{{ viewData.contract_no || '-' }}</el-descriptions-item>
<el-descriptions-item label="合同名称">{{ viewData.title || '-' }}</el-descriptions-item>
<el-descriptions-item label="合同主要内容" :span="2">{{ viewData.main_content || '-' }}</el-descriptions-item>
<el-descriptions-item label="甲方">{{ viewData.party_a || '-' }}</el-descriptions-item>
<el-descriptions-item label="乙方">{{ viewData.party_b || '-' }}</el-descriptions-item>
<el-descriptions-item label="合同金额(元)">{{ formatAmount(viewData.amount_total) }}</el-descriptions-item>
<el-descriptions-item label="项目预算金额(元)">{{ formatAmount(viewData.budget_amount) }}</el-descriptions-item>
<el-descriptions-item label="金额类型">
<el-tag v-if="viewData.amount_type === 'fixed'" type="success" size="small"></el-tag>
<el-tag v-else-if="viewData.amount_type === 'open'" type="warning" size="small">开口合同</el-tag>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="金额说明" v-if="viewData.amount_type === 'open'">{{ viewData.amount_description || '-' }}</el-descriptions-item>
<el-descriptions-item label="签订日期">{{ viewData.sign_date || '-' }}</el-descriptions-item>
<el-descriptions-item label="申请日期">{{ viewData.apply_date || '-' }}</el-descriptions-item>
<el-descriptions-item label="合同履行期">{{ viewData.perform_period || '-' }}</el-descriptions-item>
<el-descriptions-item label="付款方式">{{ viewData.pay_method || '-' }}</el-descriptions-item>
<el-descriptions-item label="预算年度">
{{ viewData.fund_source_year?.year ? viewData.fund_source_year.year + '年' : (viewData.fund_source_budget_data?.budget_year?.year ? viewData.fund_source_budget_data.budget_year.year + '年' : '-') }}
</el-descriptions-item>
<el-descriptions-item label="计划资金来源" :span="2">
{{ viewData.fund_source_budget_data?.name || viewData.fund_source || '-' }}
</el-descriptions-item>
<el-descriptions-item label="实际资金来源" :span="2">
<span v-if="viewData.actual_fund_sources && viewData.actual_fund_sources.length > 0">
{{ viewData.actual_fund_sources.join(' | ') }}
</span>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="合同类型">
<span v-if="viewData.contractType">{{ viewData.contractType.name }}</span>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="采购类别">
<span v-if="viewData.purchaseCategory">{{ viewData.purchaseCategory.name }}</span>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="采购方式">
<span v-if="viewData.purchaseMethod">{{ viewData.purchaseMethod.name }}</span>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="是否政府采购">
<el-tag v-if="viewData.is_government_purchase" type="success" size="small"></el-tag>
<el-tag v-else type="info" size="small"></el-tag>
</el-descriptions-item>
<el-descriptions-item label="招标代理">{{ viewData.tender_agent || '-' }}</el-descriptions-item>
<el-descriptions-item label="合同履行情况">{{ viewData.perform_status || '-' }}</el-descriptions-item>
<el-descriptions-item label="是否验收">
<el-tag v-if="viewData.is_accepted" type="success" size="small"></el-tag>
<el-tag v-else type="info" size="small"></el-tag>
</el-descriptions-item>
<el-descriptions-item label="科室">
{{ getDepartmentName(viewData.owner_department_id) }}
</el-descriptions-item>
<el-descriptions-item label="合同签订/变更经办人">
{{ formatUserNames(viewData.handler_admin_ids) }}
</el-descriptions-item>
<el-descriptions-item label="申请科室经办人">
{{ formatUserNames(viewData.apply_handler_id) }}
</el-descriptions-item>
<el-descriptions-item label="采购科室经办人">
{{ getUserName(viewData.purchase_handler_id) }}
</el-descriptions-item>
<el-descriptions-item label="已发起付款" :span="2">
<span style="font-weight: 600;">
<span style="color: #409eff;">{{ viewData.payment_stats?.payment_count || 0 }} </span>
<span style="color: #67c23a; margin-left: 8px;">{{ formatAmount(viewData.payment_stats?.paid_amount || 0) }}</span>
</span>
</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ viewData.remark || '-' }}</el-descriptions-item>
<el-descriptions-item label="附件" :span="2">
<template v-if="viewData.attachment_id">
<el-link
v-if="getViewAttachmentUrl(viewData)"
:href="getViewAttachmentUrl(viewData)"
target="_blank"
type="primary"
>
{{ viewData.attachment?.original_name || viewData.attachment?.name || '查看' }}
</el-link>
<span v-else style="color: #909399;">附件加载中...</span>
</template>
<span v-else>-</span>
</el-descriptions-item>
</el-descriptions>
<el-divider content-position="left">付款计划</el-divider>
<el-table :data="viewData.pay_plans || []" border size="small" style="width: 100%">
<el-table-column prop="phase_no" label="期次" width="100" />
<el-table-column prop="due_date" label="计划付款日" width="150" />
<el-table-column prop="amount_plan" label="计划金额" width="140">
<template #default="{ row }">
{{ formatAmount(row.amount_plan) }}
</template>
</el-table-column>
</el-table>
</div>
<template #footer>
<el-button @click="viewDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<!-- 导入对话框 -->
<el-dialog v-model="importDialogVisible" title="历史合同导入" width="75%" :close-on-click-modal="false">
<el-steps :active="importStep" finish-status="success" style="margin-bottom: 30px;">
@ -1065,6 +1179,8 @@ const fundSourceOptions = ref([]) // 项目经费来源选项列表
const purchaseCategoryOptions = ref([]) //
const drawerVisible = ref(false)
const viewDialogVisible = ref(false)
const viewData = ref(null)
const formRef = ref(null)
const form = reactive(getEmptyForm())
const payPlanDeleteIds = ref([])
@ -1991,6 +2107,47 @@ function handlePageChange(val) {
fetchList()
}
function openViewDialog(row) {
if (!row || !row.id) {
ElMessage.warning('请选择要查看的合同')
return
}
viewData.value = null
viewDialogVisible.value = true
loadViewDetail(row.id)
}
async function loadViewDetail(id) {
try {
const response = await request.get(`/budget/contracts/${id}`)
if (response && response.code === 0) {
viewData.value = response.data || response
} else {
ElMessage.error(response?.msg || '获取详情失败')
viewDialogVisible.value = false
}
} catch (e) {
console.error(e)
ElMessage.error('获取详情失败:' + (e.message || '未知错误'))
viewDialogVisible.value = false
}
}
function getViewAttachmentUrl(row) {
if (!row || !row.attachment_id) return null
if (row.attachment && row.attachment.url) {
return row.attachment.url
}
if (row.attachment && row.attachment.folder && row.attachment.name) {
const baseUrl = config.baseURL || ''
return `${baseUrl}/${row.attachment.folder}/${row.attachment.name}`
}
return null
}
function openForm(row) {
if (!row || !row.id) {
ElMessage.warning('请选择要编辑的合同')

@ -69,123 +69,140 @@
</tr>
<!-- 支付模板字段fields_data / element_values 双写 -->
<tr
v-for="el in visiblePaymentTemplateElements"
:key="`pay_el_${el.id}`"
>
<td class="label">{{ el.name }}</td>
<td class="value" colspan="3">
<!-- 勾选清单 -->
<div v-if="el.type === 'checklist'" class="readonly-checklist">
<div
v-for="(opt, idx) in (el.options || [])"
:key="opt.value || idx"
v-show="isChecklistChecked(payment?.fields?.[el.id], opt.value) || getChecklistRemark(el, opt.value)"
class="checklist-option-item"
>
<div class="checklist-option-wrapper">
<el-checkbox
:model-value="isChecklistChecked(payment?.fields?.[el.id], opt.value)"
disabled
class="checklist-checkbox"
>
{{ `${idx + 1}${opt.label}` }}
</el-checkbox>
<span
v-if="getChecklistRemark(el, opt.value)"
class="checklist-remark-text"
>
{{ getChecklistRemark(el, opt.value) }}
</span>
</div>
</div>
</div>
<!-- 会议纪要 -->
<div v-else-if="el.type === 'meeting_minutes'">
<MeetingMinutesField
:model-value="payment?.fields?.[el.id]"
readonly
/>
</div>
<!-- 明细表格 -->
<div v-else-if="el.type === 'detail_table'" class="readonly-detail-table">
<el-table
:data="getDetailTableData(el.id)"
border
style="width: 100%"
size="small"
>
<el-table-column type="index" label="#" width="60" align="center" />
<el-table-column
v-for="field in getDetailTableFields(el.id)"
:key="field.field_key"
:prop="field.field_key"
:label="field.field_name"
:min-width="field.field_type === 'textarea' ? 200 : 150"
<template v-for="el in visiblePaymentTemplateElements" :key="`pay_el_${el.id}`">
<tr>
<td class="label">{{ el.name }}</td>
<td class="value" colspan="3">
<!-- 勾选清单 -->
<div v-if="el.type === 'checklist'" class="readonly-checklist">
<div
v-for="(opt, idx) in (el.options || [])"
:key="opt.value || idx"
v-show="isChecklistChecked(payment?.fields?.[el.id], opt.value) || getChecklistRemark(el, opt.value)"
class="checklist-option-item"
>
<template #default="{ row }">
<span v-if="field.field_type === 'department'">
{{ getDepartmentName(row[field.field_key]) }}
</span>
<span v-else-if="field.field_type === 'user'">
{{ getUserName(row[field.field_key]) }}
</span>
<span v-else>
{{ row[field.field_key] || '-' }}
<div class="checklist-option-wrapper">
<el-checkbox
:model-value="isChecklistChecked(payment?.fields?.[el.id], opt.value)"
disabled
class="checklist-checkbox"
>
{{ `${idx + 1}${opt.label}` }}
</el-checkbox>
<span
v-if="getChecklistRemark(el, opt.value)"
class="checklist-remark-text"
>
{{ getChecklistRemark(el, opt.value) }}
</span>
</template>
</el-table-column>
</el-table>
</div>
<!-- 审批流程 -->
<div v-else-if="el.type === 'approval_flow'" class="approval-flow-display">
<div v-if="getFlowDisplayInfo(el.id)" class="flow-info">
<el-tag type="primary" size="small">
{{ getFlowDisplayInfo(el.id) }}
</el-tag>
</div>
</div>
</div>
<span v-else class="muted">-</span>
</div>
<!-- 附件类型 -->
<div v-else-if="el.type === 'form_element' && el.field_type === 'attachment'" class="attachment-display">
<div v-if="getAttachmentItems(el.id).length" class="file-list">
<span v-for="(file, idx) in getAttachmentItems(el.id)" :key="`${file.url || file.name}_${idx}`" class="file-item">
<el-link
v-if="file.url"
:href="file.url"
target="_blank"
type="primary"
:underline="false"
class="file-link"
@click="handleAttachmentClick(file)"
>
{{ file.name || `附件${idx + 1}` }}
</el-link>
<el-link
v-else
type="primary"
:underline="false"
class="file-link file-link--no-url"
@click="handleAttachmentClick(file)"
<!-- 会议纪要 -->
<div v-else-if="el.type === 'meeting_minutes'">
<MeetingMinutesField
:model-value="payment?.fields?.[el.id]"
readonly
/>
</div>
<!-- 明细表格 -->
<div v-else-if="el.type === 'detail_table'" class="readonly-detail-table">
<el-table
:data="getDetailTableData(el.id)"
border
style="width: 100%"
size="small"
>
<el-table-column type="index" label="#" width="60" align="center" />
<el-table-column
v-for="field in getDetailTableFields(el.id)"
:key="field.field_key"
:prop="field.field_key"
:label="field.field_name"
:min-width="field.field_type === 'textarea' ? 200 : 150"
>
{{ file.name || `附件${idx + 1}` }}
</el-link>
<span v-if="idx < getAttachmentItems(el.id).length - 1" class="file-separator"></span>
</span>
<template #default="{ row }">
<span v-if="field.field_type === 'department'">
{{ getDepartmentName(row[field.field_key]) }}
</span>
<span v-else-if="field.field_type === 'user'">
{{ getUserName(row[field.field_key]) }}
</span>
<span v-else>
{{ row[field.field_key] || '-' }}
</span>
</template>
</el-table-column>
</el-table>
</div>
<span v-else class="muted">-</span>
</div>
<!-- 默认展示 -->
<span v-else>
{{ formatTemplateFieldValue(el, payment?.fields?.[el.id]) }}
</span>
</td>
</tr>
<!-- 审批流程 -->
<div v-else-if="el.type === 'approval_flow'" class="approval-flow-display">
<div v-if="getFlowDisplayInfo(el.id)" class="flow-info">
<el-tag type="primary" size="small">
{{ getFlowDisplayInfo(el.id) }}
</el-tag>
</div>
<span v-else class="muted">-</span>
</div>
<!-- 附件类型 -->
<div v-else-if="el.type === 'form_element' && el.field_type === 'attachment'" class="attachment-display">
<div v-if="getAttachmentItems(el.id).length" class="file-list">
<span v-for="(file, idx) in getAttachmentItems(el.id)" :key="`${file.url || file.name}_${idx}`" class="file-item">
<el-link
v-if="file.url"
:href="file.url"
target="_blank"
type="primary"
:underline="false"
class="file-link"
@click="handleAttachmentClick(file)"
>
{{ file.name || `附件${idx + 1}` }}
</el-link>
<el-link
v-else
type="primary"
:underline="false"
class="file-link file-link--no-url"
@click="handleAttachmentClick(file)"
>
{{ file.name || `附件${idx + 1}` }}
</el-link>
<span v-if="idx < getAttachmentItems(el.id).length - 1" class="file-separator"></span>
</span>
</div>
<span v-else class="muted">-</span>
</div>
<!-- 默认展示 -->
<span v-else>
{{ formatTemplateFieldValue(el, payment?.fields?.[el.id]) }}
</span>
</td>
</tr>
<!-- 会议纪要若唯一附件为 PDF则在本行后追加一个通栏行展示 PDF尽量拉宽 -->
<tr
v-if="el.type === 'meeting_minutes' && getMeetingMinutesPdfUrl(payment?.fields?.[el.id])"
class="meeting-minutes-pdf-row"
>
<td class="value meeting-minutes-pdf-td" colspan="4">
<div
class="print-file-item print-pdf meeting-minutes-pdf"
:data-pdf-id="`meeting_minutes_${el.id}`"
:data-pdf-url="getMeetingMinutesPdfUrl(payment?.fields?.[el.id])"
>
<div class="pdf-pages-container">
<div class="pdf-loading">PDF 加载中...</div>
</div>
</div>
</td>
</tr>
</template>
</table>
</div>
@ -782,10 +799,37 @@ const handlePrint = async (e) => {
} catch (error) {
console.error('[打印] 处理失败:', error)
// 使
window.print()
window.print()
}
}
// PDF JSON
const getMeetingMinutesPdfUrl = (rawVal) => {
if (rawVal === null || rawVal === undefined || rawVal === '') return null
let v = rawVal
if (typeof v === 'string') {
try {
const parsed = JSON.parse(v)
if (parsed && typeof parsed === 'object') v = parsed
} catch {
// ignore
}
}
if (!v || typeof v !== 'object') return null
const url = (v.file_url || v.url || '').toString().trim()
if (!url) return null
const name = (v.file_name || v.name || '').toString().trim()
const extFromName = name.includes('.') ? name.split('.').pop() : ''
const extFromUrl = url.split('?')[0].split('#')[0].split('.').pop()
const ext = String(extFromName || extFromUrl || '').toLowerCase()
return ext === 'pdf' ? url : null
}
//
const handleClose = () => {
// 访退
@ -968,7 +1012,7 @@ const renderPdfAsImages = async () => {
await nextTick()
// PDF
const pdfContainers = document.querySelectorAll('.flow-template-content .print-pdf[data-pdf-url]')
const pdfContainers = document.querySelectorAll('.a4-page .print-pdf[data-pdf-url]')
for (const container of pdfContainers) {
const pdfUrl = container.getAttribute('data-pdf-url')
@ -1003,7 +1047,19 @@ const renderPdfAsImages = async () => {
}
const arrayBuffer = await response.arrayBuffer()
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise
// PDF.js
// PDF
// PDF
const pdf = await pdfjsLib.getDocument({
data: arrayBuffer,
// 退使
standardFontDataUrl: undefined, // 使
verbosity: 0, //
// PDF使CIDCMap
// cmapscMapUrlcMapPacked
// cMapUrl: '/pdfjs/cmaps/',
// cMapPacked: true
}).promise
//
pagesContainer.innerHTML = ''
@ -1019,10 +1075,18 @@ const renderPdfAsImages = async () => {
canvas.height = viewport.height
const context = canvas.getContext('2d')
await page.render({
canvasContext: context,
viewport
}).promise
//
const renderContext = {
canvasContext: context,
viewport: viewport,
//
enableWebGL: false,
//
transform: null,
background: null
}
await page.render(renderContext).promise
//
const img = document.createElement('img')
@ -1324,10 +1388,18 @@ onMounted(async () => {
.flow-template-content :deep(.print-file-name) {
font-size: 13px;
font-weight: 500;
color: #374151;
color: #409eff;
margin-bottom: 8px;
padding-bottom: 4px;
border-bottom: 1px solid #e5e7eb;
text-decoration: none;
cursor: pointer;
transition: color 0.2s;
}
.flow-template-content :deep(.print-file-name:hover) {
color: #66b1ff;
text-decoration: underline;
}
.flow-template-content :deep(.print-image img) {
@ -1363,6 +1435,36 @@ onMounted(async () => {
border: 1px dashed #ddd;
}
/* 会议纪要等非 flow-template-content 场景也需要 PDF 预览样式(统一挂在 a4-page 下) */
.a4-page :deep(.print-pdf) {
width: 100%;
margin: 0;
padding: 0;
}
.a4-page :deep(.pdf-pages-container) {
width: 100%;
}
.a4-page :deep(.pdf-page-image) {
width: 100%;
display: block;
page-break-inside: avoid;
}
.a4-page :deep(.pdf-loading),
.a4-page :deep(.pdf-error) {
padding: 20px;
text-align: center;
color: #666;
background: #f5f5f5;
border: 1px dashed #ddd;
}
.meeting-minutes-pdf-row .meeting-minutes-pdf-td {
padding-top: 8px;
}
/* 流程打印模版样式(屏幕) */
.flow-template-content :deep(table) {
width: 100%;
@ -1512,12 +1614,25 @@ onMounted(async () => {
.flow-template-content :deep(.pdf-error) {
display: none !important; /* 打印时隐藏加载提示 */
}
.a4-page :deep(.pdf-page-image) {
width: 100% !important;
max-width: 100% !important;
page-break-inside: avoid;
}
.a4-page :deep(.pdf-loading),
.a4-page :deep(.pdf-error) {
display: none !important; /* 打印时隐藏加载提示 */
}
/* 确保文件名在打印时也显示 */
.flow-template-content :deep(.print-file-name) {
font-size: 12px;
margin-bottom: 6px;
padding-bottom: 3px;
color: #409eff;
text-decoration: none;
}
}

Loading…
Cancel
Save