feat: 优化发票和证书弹窗组件,完善查看模式和文件预览功能

- 发票弹窗新增查看模式禁用状态,邮箱、文案和上传组件在查看模式下不可编辑
- 优化发票弹窗底部按钮,查看模式下仅显示"关闭"按钮
- 移除发票弹窗上传提示文案和上传区域样式冗余代码
- 证书弹窗新增图片组预览功能,支持图片文件点击放大查看
- 证书弹窗新增文件下载功能,支持所有文件类型下载
- 优化证书文
This commit is contained in:
Wei_佳 2025-11-17 14:48:34 +08:00
parent 67ac563ddb
commit 5cf79a3f7e
2 changed files with 105 additions and 38 deletions

View File

@ -135,6 +135,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
v-model:value="formData.email"
placeholder="请输入邮箱地址"
clearable
:disabled="mode === 'view'"
/>
</NFormItem>
@ -145,6 +146,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
placeholder="请输入文案内容"
:rows="4"
clearable
:disabled="mode === 'view'"
/>
</NFormItem>
@ -158,6 +160,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
:before-upload="beforeUpload"
@change="handleUploadChange"
@remove="handleRemove"
:disabled="mode === 'view'"
>
<div class="upload-trigger">
<div class="upload-icon">+</div>
@ -166,20 +169,17 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
</div>
</NFormItem>
<NFormItem>
<div style="width: 100%; text-align: left; padding-left: 100px">
<NText depth="3" style="font-size: 12px; color: #ff9800">
ps最多上传两张
</NText>
</div>
</NFormItem>
</NForm>
<template #footer>
<div style="display: flex; justify-content: flex-end; gap: 12px">
<div v-if="mode !== 'view'" style="display: flex; justify-content: flex-end; gap: 12px">
<NButton @click="handleClose">取消</NButton>
<NButton type="primary" @click="handleConfirm">确定</NButton>
</div>
<div v-else style="display: flex; justify-content: flex-end; gap: 12px">
<NButton @click="handleClose">关闭</NButton>
</div>
</template>
</NModal>
</template>
@ -192,8 +192,6 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
.upload-trigger {
width: 100px;
height: 100px;
border: 2px dashed #d9d9d9;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
@ -201,10 +199,6 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
transition: all 0.3s;
}
.upload-trigger:hover {
border-color: #40a9ff;
}
.upload-icon {
font-size: 32px;
color: #d9d9d9;

View File

@ -6,7 +6,8 @@ import {
NButton,
NUpload,
NText,
NImage
NImage,
NImageGroup
} from 'naive-ui'
//
// import { DownloadIcon } from '@vicons/tabler'
@ -142,13 +143,32 @@ const handleDownloadReport = () => {
//
const handlePreview = (file) => {
// PDF
if (file.type?.startsWith('image/') || file.type === 'application/pdf') {
window.open(file.url || '', '_blank')
} else {
console.log('此文件类型不支持预览')
// TODO:
//
if (!file.type?.startsWith('image/')) {
$message.info('此文件类型不支持预览,请下载查看')
return false
}
// true NUpload 使
return true
}
//
const handleDownload = (file) => {
const link = document.createElement('a')
link.href = file.url || ''
link.download = file.name || 'download'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
//
const customRequest = ({ file, onFinish, onError }) => {
//
//
setTimeout(() => {
onFinish()
}, 1000)
}
const modalTitle = computed(() => {
@ -187,6 +207,10 @@ const isUploadMode = computed(() => props.mode === 'upload')
:before-upload="beforeUpload"
@change="handleReportUploadChange"
@remove="handleRemove"
:custom-request="customRequest"
show-preview-button
show-download-button
@download="handleDownload"
>
</NUpload>
</div>
@ -203,6 +227,10 @@ const isUploadMode = computed(() => props.mode === 'upload')
:before-upload="beforeUpload"
@change="handleCertificateUploadChange"
@remove="handleRemove"
:custom-request="customRequest"
show-preview-button
show-download-button
@download="handleDownload"
>
</NUpload>
</div>
@ -239,24 +267,56 @@ const isUploadMode = computed(() => props.mode === 'upload')
<NText depth="3">暂无证书文件</NText>
</div>
<div v-else class="certificate-display">
<div
v-for="file in certificateFileList"
:key="file.id"
class="certificate-image"
@click="handlePreview(file)"
>
<NImage
v-if="file.type?.startsWith('image/')"
:src="file.url"
width="120"
height="120"
objectFit="cover"
preview-disabled
/>
<div v-else class="file-icon">
{{ file.name?.split('.').pop()?.toUpperCase() || 'FILE' }}
<NImageGroup>
<div
v-for="file in certificateFileList"
:key="file.id"
class="certificate-item"
>
<div class="certificate-image">
<NImage
v-if="file.type?.startsWith('image/')"
:src="file.url"
width="120"
height="120"
object-fit="cover"
:preview-src="file.url"
/>
<div v-else class="file-icon" @click="handlePreview(file)">
{{ file.name?.split('.').pop()?.toUpperCase() || 'FILE' }}
</div>
</div>
<div class="file-actions">
<NButton
v-if="file.type?.startsWith('image/')"
size="small"
type="primary"
text
@click="() => {}"
style="visibility: hidden;"
>
预览
</NButton>
<NButton
v-else
size="small"
type="primary"
text
disabled
>
不支持预览
</NButton>
<NButton
size="small"
type="primary"
text
@click="handleDownload(file)"
>
下载
</NButton>
</div>
</div>
</div>
</NImageGroup>
</div>
</div>
</div>
@ -411,6 +471,13 @@ const isUploadMode = computed(() => props.mode === 'upload')
gap: 16px;
}
.certificate-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.certificate-image {
cursor: pointer;
border-radius: 8px;
@ -424,6 +491,12 @@ const isUploadMode = computed(() => props.mode === 'upload')
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
}
.file-actions {
display: flex;
gap: 8px;
align-items: center;
}
.empty-state {
padding: 40px 20px;
text-align: center;