feat: 优化发票和证书弹窗组件,完善查看模式和文件预览功能
- 发票弹窗新增查看模式禁用状态,邮箱、文案和上传组件在查看模式下不可编辑 - 优化发票弹窗底部按钮,查看模式下仅显示"关闭"按钮 - 移除发票弹窗上传提示文案和上传区域样式冗余代码 - 证书弹窗新增图片组预览功能,支持图片文件点击放大查看 - 证书弹窗新增文件下载功能,支持所有文件类型下载 - 优化证书文
This commit is contained in:
parent
67ac563ddb
commit
5cf79a3f7e
@ -135,6 +135,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
v-model:value="formData.email"
|
v-model:value="formData.email"
|
||||||
placeholder="请输入邮箱地址"
|
placeholder="请输入邮箱地址"
|
||||||
clearable
|
clearable
|
||||||
|
:disabled="mode === 'view'"
|
||||||
/>
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
|
|
||||||
@ -145,6 +146,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
placeholder="请输入文案内容"
|
placeholder="请输入文案内容"
|
||||||
:rows="4"
|
:rows="4"
|
||||||
clearable
|
clearable
|
||||||
|
:disabled="mode === 'view'"
|
||||||
/>
|
/>
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
|
|
||||||
@ -158,6 +160,7 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@change="handleUploadChange"
|
@change="handleUploadChange"
|
||||||
@remove="handleRemove"
|
@remove="handleRemove"
|
||||||
|
:disabled="mode === 'view'"
|
||||||
>
|
>
|
||||||
<div class="upload-trigger">
|
<div class="upload-trigger">
|
||||||
<div class="upload-icon">+</div>
|
<div class="upload-icon">+</div>
|
||||||
@ -166,20 +169,17 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
</div>
|
</div>
|
||||||
</NFormItem>
|
</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>
|
</NForm>
|
||||||
|
|
||||||
<template #footer>
|
<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 @click="handleClose">取消</NButton>
|
||||||
<NButton type="primary" @click="handleConfirm">确定</NButton>
|
<NButton type="primary" @click="handleConfirm">确定</NButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else style="display: flex; justify-content: flex-end; gap: 12px">
|
||||||
|
<NButton @click="handleClose">关闭</NButton>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</NModal>
|
</NModal>
|
||||||
</template>
|
</template>
|
||||||
@ -192,8 +192,6 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
.upload-trigger {
|
.upload-trigger {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
border: 2px dashed #d9d9d9;
|
|
||||||
border-radius: 4px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -201,10 +199,6 @@ const modalTitle = props.mode === 'invoice' ? '开票' : '查看发票'
|
|||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-trigger:hover {
|
|
||||||
border-color: #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-icon {
|
.upload-icon {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
color: #d9d9d9;
|
color: #d9d9d9;
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import {
|
|||||||
NButton,
|
NButton,
|
||||||
NUpload,
|
NUpload,
|
||||||
NText,
|
NText,
|
||||||
NImage
|
NImage,
|
||||||
|
NImageGroup
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
// 临时移除图标导入以解决模块解析问题
|
// 临时移除图标导入以解决模块解析问题
|
||||||
// import { DownloadIcon } from '@vicons/tabler'
|
// import { DownloadIcon } from '@vicons/tabler'
|
||||||
@ -142,13 +143,32 @@ const handleDownloadReport = () => {
|
|||||||
|
|
||||||
// 文件预览
|
// 文件预览
|
||||||
const handlePreview = (file) => {
|
const handlePreview = (file) => {
|
||||||
// 图片和PDF可以直接预览
|
// 对于非图片文件,显示提示
|
||||||
if (file.type?.startsWith('image/') || file.type === 'application/pdf') {
|
if (!file.type?.startsWith('image/')) {
|
||||||
window.open(file.url || '', '_blank')
|
$message.info('此文件类型不支持预览,请下载查看')
|
||||||
} else {
|
return false
|
||||||
console.log('此文件类型不支持预览')
|
|
||||||
// TODO: 添加用户提示
|
|
||||||
}
|
}
|
||||||
|
// 图片文件返回 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(() => {
|
const modalTitle = computed(() => {
|
||||||
@ -187,6 +207,10 @@ const isUploadMode = computed(() => props.mode === 'upload')
|
|||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@change="handleReportUploadChange"
|
@change="handleReportUploadChange"
|
||||||
@remove="handleRemove"
|
@remove="handleRemove"
|
||||||
|
:custom-request="customRequest"
|
||||||
|
show-preview-button
|
||||||
|
show-download-button
|
||||||
|
@download="handleDownload"
|
||||||
>
|
>
|
||||||
</NUpload>
|
</NUpload>
|
||||||
</div>
|
</div>
|
||||||
@ -203,6 +227,10 @@ const isUploadMode = computed(() => props.mode === 'upload')
|
|||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@change="handleCertificateUploadChange"
|
@change="handleCertificateUploadChange"
|
||||||
@remove="handleRemove"
|
@remove="handleRemove"
|
||||||
|
:custom-request="customRequest"
|
||||||
|
show-preview-button
|
||||||
|
show-download-button
|
||||||
|
@download="handleDownload"
|
||||||
>
|
>
|
||||||
</NUpload>
|
</NUpload>
|
||||||
</div>
|
</div>
|
||||||
@ -239,24 +267,56 @@ const isUploadMode = computed(() => props.mode === 'upload')
|
|||||||
<NText depth="3">暂无证书文件</NText>
|
<NText depth="3">暂无证书文件</NText>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="certificate-display">
|
<div v-else class="certificate-display">
|
||||||
<div
|
<NImageGroup>
|
||||||
v-for="file in certificateFileList"
|
<div
|
||||||
:key="file.id"
|
v-for="file in certificateFileList"
|
||||||
class="certificate-image"
|
:key="file.id"
|
||||||
@click="handlePreview(file)"
|
class="certificate-item"
|
||||||
>
|
>
|
||||||
<NImage
|
<div class="certificate-image">
|
||||||
v-if="file.type?.startsWith('image/')"
|
<NImage
|
||||||
:src="file.url"
|
v-if="file.type?.startsWith('image/')"
|
||||||
width="120"
|
:src="file.url"
|
||||||
height="120"
|
width="120"
|
||||||
objectFit="cover"
|
height="120"
|
||||||
preview-disabled
|
object-fit="cover"
|
||||||
/>
|
:preview-src="file.url"
|
||||||
<div v-else class="file-icon">
|
/>
|
||||||
{{ file.name?.split('.').pop()?.toUpperCase() || 'FILE' }}
|
<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>
|
||||||
</div>
|
</NImageGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -411,6 +471,13 @@ const isUploadMode = computed(() => props.mode === 'upload')
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.certificate-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.certificate-image {
|
.certificate-image {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -424,6 +491,12 @@ const isUploadMode = computed(() => props.mode === 'upload')
|
|||||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user