Private
Public Access
1
0

新增:图片文件预览功能

This commit is contained in:
2026-01-26 02:35:21 +08:00
parent 9d35ba20ca
commit 4a9b25a505

View File

@@ -108,7 +108,30 @@
<a-col :span="12">
<a-card title="📝 文件内容">
<a-space direction="vertical" :size="8" style="width: 100%">
<div
<!-- 图片预览 -->
<div v-if="isImageFile" class="image-preview-container">
<div class="image-preview-wrapper">
<img
:src="imagePreviewUrl"
class="preview-image"
@load="onImageLoad"
@error="onImageError"
alt="图片预览"
/>
<div v-if="imageLoading" class="image-loading">
<a-spin />
<span>加载中...</span>
</div>
</div>
<div class="image-info">
<a-tag>{{ getImageType() }}</a-tag>
<span v-if="imageSize">{{ formatBytes(imageSize) }}</span>
</div>
</div>
<!-- 文本编辑器 -->
<div v-else
class="file-content-wrapper"
:style="{ height: fileContentHeight + 'px' }"
>
@@ -118,7 +141,9 @@
placeholder="文件内容将显示在这里,点击文件列表中的文件即可查看"
/>
</div>
<div
v-if="!isImageFile"
class="resize-handle"
@mousedown="startResize"
title="拖拽调整高度"
@@ -130,9 +155,9 @@
<template #icon>
<icon-file />
</template>
读取
{{ isImageFile ? '预览' : '读取' }}
</a-button>
<a-button @click="writeFile" :loading="fileLoading">
<a-button @click="writeFile" :loading="fileLoading" v-if="!isImageFile">
<template #icon>
<icon-save />
</template>
@@ -260,6 +285,12 @@ const pathHistory = ref([])
const fileContentHeight = ref(250)
const favoriteFiles = ref([])
// 图片预览相关
const isImageFile = ref(false)
const imagePreviewUrl = ref('')
const imageLoading = ref(false)
const imageSize = ref(0)
// 格式化文件大小
const formatBytes = (bytes) => {
if (!bytes) return '0 B'
@@ -382,13 +413,10 @@ const readFile = async () => {
// 检查文件类型
const ext = filePath.value.split('.').pop()?.toLowerCase() || ''
// 图片文件 - 提示无法预览
const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico', 'heic', 'heif']
// 图片文件 - 显示预览
const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico']
if (imageExts.includes(ext)) {
Message.warning({
content: '图片文件暂不支持预览,请使用图片查看器打开',
duration: 3000
})
await previewImage()
return
}
@@ -438,8 +466,71 @@ const readFile = async () => {
await performFileRead()
}
// 预览图片
const previewImage = async () => {
if (!filePath.value) {
Message.error('请输入文件路径')
return
}
isImageFile.value = true
imageLoading.value = true
imagePreviewUrl.value = ''
imageSize.value = 0
try {
// 使用文件协议直接显示图片
// 转换 Windows 路径格式
let imagePath = filePath.value.replace(/\\/g, '/')
imagePreviewUrl.value = `file:///${imagePath}`
// 获取文件大小
const file = fileList.value.find(f => f.path === filePath.value)
if (file && file.size) {
imageSize.value = file.size
}
Message.success('图片加载成功')
} catch (error) {
console.error('图片预览失败:', error)
Message.error('图片预览失败: ' + (error.message || error))
isImageFile.value = false
} finally {
imageLoading.value = false
}
}
// 图片加载完成
const onImageLoad = () => {
imageLoading.value = false
}
// 图片加载失败
const onImageError = () => {
imageLoading.value = false
Message.error('图片加载失败,可能是格式不支持或文件损坏')
}
// 获取图片类型标签
const getImageType = () => {
if (!filePath.value) return ''
const ext = filePath.value.split('.').pop()?.toLowerCase() || ''
const typeMap = {
'jpg': 'JPEG',
'jpeg': 'JPEG',
'png': 'PNG',
'gif': 'GIF',
'bmp': 'BMP',
'svg': 'SVG',
'webp': 'WebP',
'ico': 'ICO'
}
return typeMap[ext] || ext.toUpperCase()
}
// 执行文件读取
const performFileRead = async () => {
isImageFile.value = false
fileLoading.value = true
try {
const content = await readFileApi(filePath.value)
@@ -526,6 +617,8 @@ const deleteFile = async () => {
// 清空内容
const clearContent = () => {
fileContent.value = ''
isImageFile.value = false
imagePreviewUrl.value = ''
Message.info('内容已清空')
}
@@ -750,6 +843,54 @@ onMounted(() => {
border: none;
}
/* 图片预览容器 */
.image-preview-container {
width: 100%;
}
.image-preview-wrapper {
position: relative;
width: 100%;
min-height: 300px;
max-height: 600px;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-fill-1);
border: 1px solid var(--color-border-2);
border-radius: 8px;
overflow: hidden;
}
.preview-image {
max-width: 100%;
max-height: 600px;
object-fit: contain;
display: block;
margin: 0 auto;
}
.image-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
color: var(--color-text-3);
}
.image-info {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 0;
font-size: 13px;
color: var(--color-text-3);
}
.file-content-wrapper {
position: relative;
overflow: hidden;