Files
property-resident-side/property-uniapp-project/pageSubPack/api/useImageUpload.js

173 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 服务器地址(与 request.js 保持一致)
const baseUrl = 'http://192.168.0.224:8080';
/**
* 图片上传 Hook
* 支持 uniapp 和微信小程序
* 解决编辑回显后重新上传的问题
*/
import { ref } from 'vue'
/**
* @param {Object} options 配置
* @param {string} options.uploadUrl - 上传接口地址
* @param {string} options.fileKey - 上传文件的字段名,默认 'file'
* @returns {Object}
*/
export function useImageUpload(options = {}) {
const {
uploadUrl = '/api/resident/file/uploadImage',
fileKey = 'file'
} = options
// 当前显示的图片(前端展示用,支持 base64/blob URL/网络URL
const previewUrl = ref('')
// 服务器返回的 URL提交时使用
const serverUrl = ref('')
// 临时的文件路径(重新上传时用)
const tempFilePath = ref(null)
// 上传状态
const uploading = ref(false)
/**
* 设置回显图片(编辑时从后端获取)
* @param {string} url - 后端返回的图片URL
*/
const setPreviewUrl = (url) => {
if (url) {
previewUrl.value = url
serverUrl.value = url
tempFilePath.value = null // 重置临时文件,表示没有重新上传
}
}
/**
* 选择图片并预览(不上传)
* @returns {Promise<string>} 返回临时文件路径
*/
const chooseImage = () => {
return new Promise((resolve, reject) => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['camera', 'album'],
success: (res) => {
const path = res.tempFilePaths[0]
// 设置预览
previewUrl.value = path
// 记录临时文件路径
tempFilePath.value = path
// 置空服务器URL等实际上传后再获取
serverUrl.value = ''
resolve(path)
},
fail: (err) => {
reject(err)
}
})
})
}
/**
* 上传图片到服务器
* @returns {Promise<string>} 返回服务器上的URL
*/
const uploadImage = () => {
// 如果没有新选择临时文件直接返回已有的服务器URL
if (!tempFilePath.value) {
return Promise.resolve(serverUrl.value)
}
// 如果已经有服务器URL且没有重新选择也直接返回
if (serverUrl.value && !tempFilePath.value) {
return Promise.resolve(serverUrl.value)
}
uploading.value = true
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + uploadUrl,
filePath: tempFilePath.value,
name: fileKey,
header: {
'Authorization': 'Bearer ' + (uni.getStorageSync('token') || ''),
'clientid': 'resident'
},
success: (res) => {
try {
const data = JSON.parse(res.data)
if (data.code === 200 && data.data) {
// 更新服务器URL确保存的是字符串
const url = typeof data.data === 'string' ? data.data : (data.data?.url || '')
serverUrl.value = url
// 清空临时文件
tempFilePath.value = null
resolve(url)
} else {
uni.showToast({
title: data.msg || '上传失败',
icon: 'none'
})
reject(new Error(data.msg || '上传失败'))
}
} catch (e) {
uni.showToast({
title: '上传失败',
icon: 'none'
})
reject(e)
}
},
fail: (err) => {
uni.showToast({
title: err.message || '上传失败',
icon: 'none'
})
reject(err)
},
complete: () => {
uploading.value = false
}
})
})
}
/**
* 获取最终可提交的URL
* 如果有新上传的图片先上传再返回URL
* 如果没有新上传直接返回已有的服务器URL
* @returns {Promise<string>}
*/
const getSubmitUrl = async () => {
// 如果重新选择了新图片,先上传
if (tempFilePath.value) {
return await uploadImage()
}
// 否则返回已有的服务器URL
return serverUrl.value
}
/**
* 重置状态
*/
const reset = () => {
previewUrl.value = ''
serverUrl.value = ''
tempFilePath.value = null
uploading.value = false
}
return {
previewUrl, // 前端展示用
serverUrl, // 提交时使用的URL
tempFilePath, // 临时文件路径
uploading, // 上传中状态
setPreviewUrl, // 设置回显图片(编辑时用)
chooseImage, // 选择图片(预览用,不上传)
uploadImage, // 上传到服务器
getSubmitUrl, // 获取最终可提交的URL自动处理上传
reset // 重置
}
}