客户图片预览

This commit is contained in:
zhonghua.li
2026-05-02 20:13:42 +08:00
parent c73a2535fb
commit 8fd3aa00e2
2 changed files with 49 additions and 68 deletions

View File

@@ -89,50 +89,31 @@ export function updateCustomer(data) {
})
}
function isLikelyBackendOrProxyAsset(absoluteUrl) {
try {
const p = new URL(absoluteUrl).pathname || ''
return p.startsWith('/api/') || p.includes('/customerManagement')
} catch (e) {
return false
}
}
/**
* 按列表/详情中保存的地址拉取图片:相对路径或指向本系统接口的完整 URL 走 axios含 Token、业务头经 dev 代理);
* 其余完整 URL如公网图床、MinIO 外链)返回 { useDirect: true, url },由前端用 img 直链展示
* 预览客户照片(后端从 MinIO 拉流)。
* 方式一:传 url与 uploadPhoto 返回的 MinIO 访问 URL 一致)
* 方式二:传 id + photoTypefront | side | life由后端读库再拉 MinIO。
* @param {{ url?: string, id?: string|number, photoType?: 'front'|'side'|'life' }}=} params
*/
export function loadCustomerPhotoForDisplay(storedUrl) {
if (storedUrl == null || String(storedUrl).trim() === '') {
return Promise.reject(new Error('EMPTY_URL'))
export function previewCustomerPhoto(params) {
const p = params && typeof params === 'object' ? params : {}
const query = {}
if (p.url != null && String(p.url).trim() !== '') {
query.url = String(p.url).trim()
}
const raw = String(storedUrl).trim()
const isAbs = /^https?:\/\//i.test(raw)
if (isAbs && !isLikelyBackendOrProxyAsset(raw)) {
return Promise.resolve({ useDirect: true, url: raw })
if (p.id != null && String(p.id).trim() !== '') {
query.id = String(p.id).trim()
}
let path = raw
if (isAbs) {
try {
const u = new URL(raw)
path = u.pathname + (u.search || '')
} catch (e) {
return Promise.reject(e)
}
}
if (!path.startsWith('/')) {
path = `/${path}`
}
if (path.startsWith('/api/')) {
path = path.slice(4)
if (p.photoType != null && String(p.photoType).trim() !== '') {
query.photoType = String(p.photoType).trim()
}
return request({
url: path,
url: '/customerManagement/previewPhoto',
method: 'get',
params: query,
responseType: 'blob',
timeout: 120000
}).then(blob => ({ useDirect: false, blob }))
})
}
/** 客户照片上传至 MinIOid 可选,有则作为 query 传入;成功时响应 data 中含 url */

View File

@@ -578,7 +578,7 @@ import {
addCustomer,
updateCustomer,
uploadCustomerPhoto,
loadCustomerPhotoForDisplay,
previewCustomerPhoto,
deleteCustomer,
batchDeleteCustomer,
exportCustomerFlow,
@@ -989,16 +989,13 @@ export default {
})
if (!kind) return
const fieldMap = { front: 'frontPhotoUrl', side: 'sidePhotoUrl', life: 'lifePhotoUrl' }
const titleMap = { front: '正面照片', side: '侧面照片', life: '生活照片' }
const field = fieldMap[kind]
const stored = field && row[field] ? String(row[field]).trim() : ''
if (!stored) {
this.$message.warning(`该客户未设置${titleMap[kind] || '该类型'}地址`)
if (row.id == null || String(row.id).trim() === '') {
this.$message.warning('无法预览缺少客户ID')
return
}
this.photoPreviewTitle = `${row.customerName || '客户'}${titleMap[kind]}`
this.photoPreviewTitle = `${row.customerName || '客户'}${titleMap[kind] || ''}`
this.photoPreviewLoadError = false
this.revokePhotoPreviewObjectUrl()
this.photoPreviewSrc = ''
@@ -1006,13 +1003,10 @@ export default {
this.photoPreviewLoading = true
try {
const result = await loadCustomerPhotoForDisplay(stored)
if (result.useDirect) {
this.photoPreviewSrc = result.url
} else {
const blob = result.blob
const blob = await previewCustomerPhoto({ id: row.id, photoType: kind })
if (!(blob instanceof Blob) || blob.size === 0) {
this.$message.error('未获取到图片数据')
this.photoPreviewVisible = false
return
}
const ct = (blob.type || '').toLowerCase()
@@ -1031,10 +1025,16 @@ export default {
}
this.photoPreviewObjectUrl = URL.createObjectURL(blob)
this.photoPreviewSrc = this.photoPreviewObjectUrl
}
} catch (err) {
console.error('加载客户照片失败:', err)
const status = err && err.response && err.response.status
if (status === 404) {
this.$message.warning('未找到该照片或客户未上传此类型照片')
} else if (status === 400) {
this.$message.warning('请求参数无效')
} else {
this.$message.error((err && err.message) || '加载照片失败,请稍后重试')
}
this.photoPreviewVisible = false
} finally {
this.photoPreviewLoading = false