diff --git a/src/api/customer.js b/src/api/customer.js index 1e7be9e..2836709 100644 --- a/src/api/customer.js +++ b/src/api/customer.js @@ -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 + photoType(front | 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 })) + }) } /** 客户照片上传至 MinIO;id 可选,有则作为 query 传入;成功时响应 data 中含 url */ diff --git a/src/views/customer/index.vue b/src/views/customer/index.vue index 760e426..ca25af3 100644 --- a/src/views/customer/index.vue +++ b/src/views/customer/index.vue @@ -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,35 +1003,38 @@ export default { this.photoPreviewLoading = true try { - const result = await loadCustomerPhotoForDisplay(stored) - if (result.useDirect) { - this.photoPreviewSrc = result.url - } else { - const blob = result.blob - if (!(blob instanceof Blob) || blob.size === 0) { - this.$message.error('未获取到图片数据') - return - } - const ct = (blob.type || '').toLowerCase() - if (ct.includes('json') || ct === 'text/plain') { - const text = await blob.text() - let msg = '加载失败' - try { - const j = JSON.parse(text) - msg = j.message || j.msg || msg - } catch (e) { - if (text) msg = text.slice(0, 200) - } - this.$message.error(msg) - this.photoPreviewVisible = false - return - } - this.photoPreviewObjectUrl = URL.createObjectURL(blob) - this.photoPreviewSrc = this.photoPreviewObjectUrl + 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() + if (ct.includes('json') || ct === 'text/plain') { + const text = await blob.text() + let msg = '加载失败' + try { + const j = JSON.parse(text) + msg = j.message || j.msg || msg + } catch (e) { + if (text) msg = text.slice(0, 200) + } + this.$message.error(msg) + this.photoPreviewVisible = false + return + } + this.photoPreviewObjectUrl = URL.createObjectURL(blob) + this.photoPreviewSrc = this.photoPreviewObjectUrl } catch (err) { console.error('加载客户照片失败:', err) - this.$message.error((err && err.message) || '加载照片失败,请稍后重试') + 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