Files
file-tool-wails/frontend/src/composables/useImageTool.js
2026-06-17 08:05:20 +08:00

266 lines
6.9 KiB
JavaScript

import { ref, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
export function useImageTool() {
const filePath = ref('')
const filePreview = ref('')
const imageInfo = ref(null)
const processing = ref(false)
const resultInfo = ref(null)
const outputPath = ref('')
const compareImages = ref({ original: '', processed: '' })
const config = ref({ defaultOutputDir: '' })
const showPreview = ref(false)
const previewSrc = ref('')
const previewIndex = ref(0)
const previewScale = ref(1)
const previewX = ref(0)
const previewY = ref(0)
const isDragging = ref(false)
const dragStart = ref({ x: 0, y: 0 })
onMounted(async () => {
try {
config.value = await window.go.main.FileHandler.GetConfig()
} catch (e) {}
})
function formatSize(bytes) {
if (!bytes) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
function getFileName() {
if (!filePath.value) return '未选择文件'
return filePath.value.split(/[/\\]/).pop()
}
async function selectFile(fileFilters) {
try {
const path = await window.go.main.FileHandler.OpenFileDialog('选择文件', fileFilters)
if (path) {
filePath.value = path
resetState()
outputPath.value = ''
await loadFilePreview()
}
} catch (e) {
ElMessage.error('选择文件失败: ' + e.message)
}
}
async function loadFilePreview() {
if (!filePath.value) return
try {
const b64 = await window.go.main.FileHandler.GetImageBase64(filePath.value)
if (b64) {
filePreview.value = b64
const info = await window.go.main.FileHandler.GetFileInfo(filePath.value)
imageInfo.value = info
}
} catch (e) {
console.error('加载预览失败:', e)
}
}
function resetState() {
resultInfo.value = null
compareImages.value = { original: '', processed: '' }
previewScale.value = 1
previewX.value = 0
previewY.value = 0
filePreview.value = ''
imageInfo.value = null
}
function clearImageFile() {
filePath.value = ''
filePreview.value = ''
imageInfo.value = null
resultInfo.value = null
compareImages.value = { original: '', processed: '' }
outputPath.value = ''
}
async function processFile(req) {
if (!filePath.value) {
ElMessage.warning('请先选择文件')
return
}
processing.value = true
resultInfo.value = null
compareImages.value = { original: '', processed: '' }
try {
const result = await window.go.main.FileHandler.ProcessFile(req)
if (result.success) {
resultInfo.value = {
path: result.path,
size: formatSize(result.size),
sizeBytes: result.size,
originalSize: result.originalSize ? formatSize(result.originalSize) : '',
originalSizeBytes: result.originalSize || 0,
tempPath: result.path,
isImageOp: true,
}
try {
const b64 = await window.go.main.FileHandler.GetImageBase64(filePath.value)
compareImages.value.original = b64
compareImages.value.processed = await window.go.main.FileHandler.GetImageBase64(result.path)
if (!compareImages.value.processed) {
compareImages.value.processed = b64
}
} catch (e) {}
await window.go.main.FileHandler.AddRecentUse({
id: req.format,
name: '',
category: 'image',
usedAt: Date.now(),
})
ElMessage.success('处理完成')
} else {
ElMessage.error(result.message)
}
} catch (e) {
ElMessage.error('处理失败: ' + e.message)
} finally {
processing.value = false
}
}
async function selectOutputPath(outputFilters, defaultName) {
try {
const path = await window.go.main.FileHandler.OpenSaveDialog('保存文件', defaultName, outputFilters)
if (path) {
outputPath.value = path
}
} catch (e) {}
}
async function downloadResult(outputFilters, getOutputExtFn, getOutputDefaultNameFn) {
if (!resultInfo.value?.tempPath) return
try {
const ext = getOutputExtFn ? getOutputExtFn() : '.png'
const defaultName = getOutputDefaultNameFn ? getOutputDefaultNameFn() : ('output' + ext)
const savePath = await window.go.main.FileHandler.OpenSaveDialog('保存文件', defaultName, outputFilters)
if (savePath) {
const result = await window.go.main.FileHandler.SaveResult(resultInfo.value.tempPath, savePath)
if (result.success) {
ElMessage.success('文件已保存到: ' + savePath)
resultInfo.value.path = savePath
} else {
ElMessage.error(result.message)
}
}
} catch (e) {
ElMessage.error('保存失败: ' + e.message)
}
}
function openPreview(src, index) {
previewSrc.value = src
previewIndex.value = index
previewScale.value = 1
previewX.value = 0
previewY.value = 0
showPreview.value = true
}
function closePreview() {
showPreview.value = false
}
function onWheel(e) {
e.preventDefault()
const delta = e.deltaY > 0 ? -0.1 : 0.1
previewScale.value = Math.max(0.1, Math.min(5, previewScale.value + delta))
}
function onMouseDown(e) {
if (e.button !== 0) return
isDragging.value = true
dragStart.value = { x: e.clientX - previewX.value, y: e.clientY - previewY.value }
}
function onMouseMove(e) {
if (!isDragging.value) return
previewX.value = e.clientX - dragStart.value.x
previewY.value = e.clientY - dragStart.value.y
}
function onMouseUp() {
isDragging.value = false
}
function resetPreview() {
previewScale.value = 1
previewX.value = 0
previewY.value = 0
}
function switchPreview(dir) {
previewIndex.value = dir
previewSrc.value = dir === 0 ? compareImages.value.original : compareImages.value.processed
resetPreview()
}
async function openOutputFolder() {
if (resultInfo.value?.path) {
const dir = resultInfo.value.path.replace(/[/\\][^/\\]+$/, '')
try {
await window.go.main.FileHandler.OpenFolder(dir)
} catch (e) {
ElMessage.error('打开文件夹失败')
}
}
}
return {
filePath,
filePreview,
imageInfo,
processing,
resultInfo,
outputPath,
compareImages,
config,
showPreview,
previewSrc,
previewIndex,
previewScale,
previewX,
previewY,
isDragging,
dragStart,
formatSize,
getFileName,
selectFile,
loadFilePreview,
resetState,
clearImageFile,
processFile,
selectOutputPath,
downloadResult,
openPreview,
closePreview,
onWheel,
onMouseDown,
onMouseMove,
onMouseUp,
resetPreview,
switchPreview,
openOutputFolder,
}
}