Commit 8367be89 by yuzhenWang

Merge branch 'wyz' into 'test'

Wyz

See merge request !143
parents b32db88e c5b88c5f
......@@ -37,6 +37,7 @@
"lodash": "^4.18.1",
"nprogress": "0.2.0",
"p-limit": "^7.3.0",
"pdfjs-dist": "^5.7.284",
"pinia": "3.0.2",
"spark-md5": "^3.0.2",
"splitpanes": "^4.0.4",
......
......@@ -101,6 +101,7 @@
:headers="headers"
multiple
:limit="limit"
:accept="acceptUploadType"
:show-file-list="false"
:on-exceed="handleExceed"
:on-success="uploadSuccess"
......@@ -148,7 +149,7 @@
</CommonDialog>
<!-- 文件预览弹窗(页面内查看,不打开新窗口) -->
<el-dialog
<!-- <el-dialog
v-model="previewDialogVisible"
:title="previewFileName"
width="70%"
......@@ -157,18 +158,65 @@
@close="previewUrl = ''"
>
<div class="preview-container">
<!-- 图片预览 -->
<div v-if="previewFileType === 'image'" class="preview-image-wrapper">
<img :src="previewUrl" class="preview-image" alt="预览图片" />
</div>
<!-- PDF 预览(使用 iframe 内嵌) -->
<iframe
v-else-if="previewFileType === 'pdf'"
:src="previewUrl"
class="preview-pdf"
frameborder="0"
></iframe>
<div v-else-if="previewFileType === 'unsupported'" class="preview-unsupported">
<el-icon :size="48" color="#909399"><Document /></el-icon>
<p>暂不支持预览此类型文件</p>
<el-button type="primary" @click="previewDialogVisible = false"> 关闭 </el-button>
</div>
</div>
</el-dialog> -->
<!-- 文件预览弹窗 -->
<el-dialog
v-model="previewDialogVisible"
:title="previewFileName"
width="80%"
:close-on-click-modal="false"
destroy-on-close
@close="closePreview"
>
<div class="preview-container">
<!-- 图片预览 -->
<div v-if="previewFileType === 'image'" class="preview-image-wrapper">
<img :src="previewUrl" class="preview-image" alt="预览图片" />
</div>
<!-- PDF 预览(pdf.js 插件) -->
<div v-else-if="previewFileType === 'pdf'" class="pdf-viewer">
<div class="pdf-toolbar">
<el-button-group>
<el-button size="small" :disabled="pdfCurrentPage <= 1" @click="prevPage">
<el-icon><ArrowLeft /></el-icon> 上一页
</el-button>
<el-button size="small" :disabled="pdfCurrentPage >= pdfTotalPages" @click="nextPage">
下一页 <el-icon><ArrowRight /></el-icon>
</el-button>
</el-button-group>
<span class="page-info"> 第 {{ pdfCurrentPage }} / {{ pdfTotalPages }} 页 </span>
<el-button-group>
<el-button size="small" @click="zoomOut">
<el-icon><ZoomOut /></el-icon> 缩小
</el-button>
<el-button size="small" @click="zoomIn">
<el-icon><ZoomIn /></el-icon> 放大
</el-button>
</el-button-group>
</div>
<div class="pdf-canvas-wrapper">
<canvas ref="pdfCanvasRef" class="pdf-canvas"></canvas>
</div>
</div>
<!-- 不支持预览的文件类型 -->
<div v-else-if="previewFileType === 'unsupported'" class="preview-unsupported">
......@@ -187,7 +235,7 @@
</template>
<script setup name="FileUpload">
import { ref } from 'vue'
import { ref, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { downloadFilesAsZip } from '@/utils/zipDownload' // 引入刚才封装的工具
import CommonDialog from '@/components/commonDialog'
......@@ -196,6 +244,7 @@ import { getToken } from '@/utils/auth'
import { addFile, getAppointmentFile, delFile, editAppointmentFile } from '@/api/sign/appointment'
import useDictStore from '@/store/modules/dict'
import useUserStore from '@/store/modules/user'
import { ArrowLeft, ArrowRight, ZoomIn, ZoomOut, Document } from '@element-plus/icons-vue'
const userStore = useUserStore()
import {
uploadMaterialList,
......@@ -206,11 +255,19 @@ import {
downloadCompressedFile,
delMaterial
} from '@/api/common'
import * as PDFJS from 'pdfjs-dist'
// 设置 worker 路径(重要!)
PDFJS.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url
).toString()
const props = defineProps({
activeName: { type: String, default: '' }, //tab名称
idsObj: { type: Object, default: () => ({}) }, //父组件传递过来的id对象
pageSource: { type: String, default: '' } //页面来源
})
const acceptUploadType = ref('.pdf,.jpg,.jpeg,.png,.bmp,.gif,.svg')
const uploadRef = ref(null)
const dictStore = useDictStore() //获取字典数据
const { proxy } = getCurrentInstance()
......@@ -222,6 +279,85 @@ const limit = ref(10)
const fileSize = ref(10)
const headers = ref({ Authorization: 'Bearer ' + getToken() })
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + '/oss/api/oss/upload') // 上传的服务器地址
// PDF 预览相关
const pdfCanvasRef = ref(null) // canvas 元素引用
const pdfDoc = ref(null) // pdf 文档实例
const pdfCurrentPage = ref(1) // 当前页
const pdfTotalPages = ref(0) // 总页数
const pdfScale = ref(1.2) // 缩放比例
// 渲染指定页
const renderPdfPage = async pageNum => {
if (!pdfDoc.value) return
const page = await pdfDoc.value.getPage(pageNum)
const viewport = page.getViewport({ scale: pdfScale.value })
const canvas = pdfCanvasRef.value
const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
const renderContext = {
canvasContext: context,
viewport: viewport
}
await page.render(renderContext).promise
}
// 加载并渲染 PDF
const loadPdf = async url => {
try {
// 重置状态
pdfDoc.value = null
pdfCurrentPage.value = 1
pdfTotalPages.value = 0
const loadingTask = PDFJS.getDocument(url)
pdfDoc.value = await loadingTask.promise
pdfTotalPages.value = pdfDoc.value.numPages
await renderPdfPage(pdfCurrentPage.value)
} catch (err) {
console.error('PDF 加载失败', err)
ElMessage.error('PDF 文件加载失败,请检查文件链接')
previewDialogVisible.value = false
}
}
// 上一页
const prevPage = () => {
if (pdfCurrentPage.value > 1) {
pdfCurrentPage.value--
renderPdfPage(pdfCurrentPage.value)
}
}
// 下一页
const nextPage = () => {
if (pdfCurrentPage.value < pdfTotalPages.value) {
pdfCurrentPage.value++
renderPdfPage(pdfCurrentPage.value)
}
}
// 放大/缩小
const zoomIn = () => {
pdfScale.value = Math.min(pdfScale.value + 0.2, 3.0)
renderPdfPage(pdfCurrentPage.value)
}
const zoomOut = () => {
pdfScale.value = Math.max(pdfScale.value - 0.2, 0.5)
renderPdfPage(pdfCurrentPage.value)
}
const closePreview = () => {
// 清理 PDF 资源
if (pdfDoc.value) {
pdfDoc.value.destroy()
pdfDoc.value = null
}
pdfTotalPages.value = 0
pdfCurrentPage.value = 1
pdfScale.value = 1.0
previewUrl.value = ''
}
// ==================== 文件预览弹窗 ====================
const previewDialogVisible = ref(false)
const previewUrl = ref('')
......@@ -229,6 +365,43 @@ const previewFileName = ref('')
const previewFileType = ref('') // 'image', 'pdf', 'unsupported'
// 预览文件(页面内弹窗,不打开新窗口)
// function previewFile(file) {
// console.log('====================================')
// console.log('file', file)
// console.log('====================================')
// // const url = file.url || file.fileUrl
// let url = ''
// if (file.fileKey) {
// // url = `https://files.csf.hk/${file.fileKey}`
// url = `https://csf-hk.oss-cn-hongkong.aliyuncs.com/PC/test/pdf/2026/05/13/a482331b118142d782ac6ba7697eae15.pdf`
// } else {
// url = file.url
// }
// if (!url) {
// ElMessage.warning('文件地址不存在')
// return
// }
// const ext = (file.originalName || '').split('.').pop().toLowerCase()
// previewUrl.value = url
// previewFileName.value = file.originalName || '文件'
// if (['jpg', 'jpeg', 'png', 'webp', 'gif', 'bmp', 'svg'].includes(ext)) {
// previewFileType.value = 'image'
// previewDialogVisible.value = true
// } else if (ext === 'pdf') {
// previewFileType.value = 'pdf'
// previewDialogVisible.value = true
// } else {
// // 不支持预览的文件类型,弹窗显示提示
// previewFileType.value = 'unsupported'
// previewDialogVisible.value = true
// }
// console.log('====================================')
// console.log('previewUrl.value', previewUrl.value)
// console.log('previewFileName.value', previewFileName.value)
// console.log('previewFileType.value', previewFileType.value)
// console.log('====================================')
// }
function previewFile(file) {
const url = file.url || file.fileUrl
if (!url) {
......@@ -245,16 +418,14 @@ function previewFile(file) {
} else if (ext === 'pdf') {
previewFileType.value = 'pdf'
previewDialogVisible.value = true
// 确保 DOM 更新后再加载 PDF
nextTick(() => {
loadPdf(previewUrl.value)
})
} else {
// 不支持预览的文件类型,弹窗显示提示
previewFileType.value = 'unsupported'
previewDialogVisible.value = true
}
console.log('====================================')
console.log('previewUrl.value', previewUrl.value)
console.log('previewFileName.value', previewFileName.value)
console.log('previewFileType.value', previewFileType.value)
console.log('====================================')
}
// 图片查看相关状态
const imageViewerVisible = ref(false)
......@@ -575,6 +746,7 @@ function handleBeforeUpload(file) {
// proxy.$modal.msgError('文件名不正确,不能包含英文逗号!')
// return false
// }
const isLt = file.size / 1024 / 1024 < fileSize.value
if (!isLt) {
proxy.$modal.msgError(`上传文件大小不能超过 ${fileSize.value} MB!`)
......@@ -681,6 +853,38 @@ defineExpose({
})
</script>
<style lang="scss" scoped>
.pdf-viewer {
display: flex;
flex-direction: column;
height: 70vh;
}
.pdf-toolbar {
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
padding: 8px 0;
border-bottom: 1px solid #e4e7ed;
margin-bottom: 12px;
.page-info {
font-size: 14px;
color: #606266;
}
}
.pdf-canvas-wrapper {
flex: 1;
overflow: auto;
text-align: center;
}
.pdf-canvas {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
margin: 0 auto;
}
.preview-container {
display: flex;
justify-content: center;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment