|
|
@@ -98,11 +98,11 @@
|
|
|
</div>
|
|
|
<el-descriptions :column="2" size="small" class="pet-desc" border>
|
|
|
<el-descriptions-item label="宠物品种">{{ order.petBreed || '-'
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="疫苗状态"><span style="color:#67c23a">{{ order.petVaccine || '-'
|
|
|
- }}</span></el-descriptions-item>
|
|
|
+ }}</span></el-descriptions-item>
|
|
|
<el-descriptions-item label="性格特点">{{ order.petPersonality || order.petCharacter || '-'
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="健康状况">{{ order.petHealth || '-' }}</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
</div>
|
|
|
@@ -115,7 +115,7 @@
|
|
|
<div class="user-content">
|
|
|
<div class="u-row">
|
|
|
<el-avatar :size="40" :src="order.userAvatar">{{ (order.userName || '').charAt(0)
|
|
|
- }}</el-avatar>
|
|
|
+ }}</el-avatar>
|
|
|
<div class="u-info">
|
|
|
<div class="nm">{{ order.userName }}</div>
|
|
|
<div class="ph">{{ order.contactPhone }}</div>
|
|
|
@@ -148,19 +148,19 @@
|
|
|
<el-descriptions-item label="归属门店">{{ order.merchantName }}
|
|
|
({{ Number(order.platformId) === 1 ? '门店下单' : '平台代下单' }})</el-descriptions-item>
|
|
|
<el-descriptions-item label="宠主信息">{{ order.userName }} / {{ order.contactPhone
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="履约佣金" label-class-name="money-label">
|
|
|
<span style="color:#f56c6c; font-weight:bold;">¥ {{ order.fulfillerFee }}</span>
|
|
|
</el-descriptions-item>
|
|
|
|
|
|
<el-descriptions-item label="预约时间">{{ getServiceTimeRange(order.serviceTime)
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="团购套餐">{{ order.groupBuyPackage || '-'
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="创建时间">{{ order.createTime }}</el-descriptions-item>
|
|
|
<el-descriptions-item label="订单佣金" label-class-name="money-label">
|
|
|
<span style="color:#f56c6c; font-weight:bold;">¥ {{ order.orderCommission || 0
|
|
|
- }}</span>
|
|
|
+ }}</span>
|
|
|
</el-descriptions-item>
|
|
|
|
|
|
<el-descriptions-item label="订单备注" :span="3">
|
|
|
@@ -180,7 +180,7 @@
|
|
|
<div class="t-row">
|
|
|
<span class="t-k">起点</span>
|
|
|
<span class="t-v">{{ order.detail?.fromAddress || order.detail?.pickAddr || '-'
|
|
|
- }}</span>
|
|
|
+ }}</span>
|
|
|
</div>
|
|
|
<div class="t-row">
|
|
|
<span class="t-k">终点</span>
|
|
|
@@ -200,7 +200,7 @@
|
|
|
<div class="sec-title-bar">服务执行要求</div>
|
|
|
<el-descriptions :column="2" border size="default" class="custom-desc">
|
|
|
<el-descriptions-item label="服务地址" :span="2">{{ order.detail.area || order.address
|
|
|
- }}</el-descriptions-item>
|
|
|
+ }}</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -212,7 +212,7 @@
|
|
|
<div v-if="order.fulfillerName" class="fulfiller-card">
|
|
|
<div class="f-left">
|
|
|
<el-avatar :size="60" :src="order.fulfillerAvatar">{{ order.fulfillerName.charAt(0)
|
|
|
- }}</el-avatar>
|
|
|
+ }}</el-avatar>
|
|
|
</div>
|
|
|
<div class="f-right">
|
|
|
<div class="f-row1">
|
|
|
@@ -437,13 +437,13 @@
|
|
|
<!-- 时间 -->
|
|
|
<div style="font-size: 14px; color: #909399; margin-bottom: 10px; font-weight: 500;">{{
|
|
|
step.time
|
|
|
- }}</div>
|
|
|
+ }}</div>
|
|
|
<!-- 进度卡片 -->
|
|
|
<div
|
|
|
style="background: #f8fcfb; border-radius: 8px; padding: 20px; border: 1px solid #ebeef5; width: calc(100% - 10px); box-sizing: border-box;">
|
|
|
<h4 style="margin: 0 0 12px; font-size: 17px; font-weight: bold; color: #303133;">{{
|
|
|
step.title
|
|
|
- }}</h4>
|
|
|
+ }}</h4>
|
|
|
<p
|
|
|
style="margin: 0 0 18px; color: #606266; font-size: 14px; line-height: 1.7; text-align: justify;">
|
|
|
{{ step.desc }}</p>
|
|
|
@@ -492,7 +492,6 @@ import { getFulfiller } from '@/api/fulfiller/fulfiller/index'
|
|
|
import { listSubOrderLog, exportSubOrderLogUrl } from '@/api/order/subOrderLog/index'
|
|
|
import { listComplaintByOrder } from '@/api/fulfiller/complaint'
|
|
|
import { listSubOrderAppealByOrderId } from '@/api/order/subOrderAppeal'
|
|
|
-import { listByIds, downloadOssBlob } from '@/api/system/oss'
|
|
|
import ImagePreview from '@/components/ImagePreview/index.vue'
|
|
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
@@ -551,24 +550,7 @@ const loadOrderLogs = async (order) => {
|
|
|
const list = res?.data?.data || res?.data || []
|
|
|
const arr = Array.isArray(list) ? list : []
|
|
|
orderLogs.value = arr.filter(i => Number(i?.logType) === 0)
|
|
|
-
|
|
|
- // 对履约者日志中含有 photos(ossId 串)的条目,调用 listByIds 解析出可访问的 OSS URL
|
|
|
- const fLogs = arr.filter(i => Number(i?.logType) === 1)
|
|
|
- await Promise.all(fLogs.map(async (item) => {
|
|
|
- const photoIds = item?.photos
|
|
|
- if (photoIds) {
|
|
|
- try {
|
|
|
- const ossRes = await listByIds(photoIds)
|
|
|
- const ossList = ossRes?.data || []
|
|
|
- item._resolvedUrls = ossList.map(o => ({ type: isVideo(o.url) ? 'video' : 'image', url: o.url, ossId: o.ossId }))
|
|
|
- } catch {
|
|
|
- item._resolvedUrls = []
|
|
|
- }
|
|
|
- } else {
|
|
|
- item._resolvedUrls = []
|
|
|
- }
|
|
|
- }))
|
|
|
- fulfillerLogs.value = fLogs
|
|
|
+ fulfillerLogs.value = arr.filter(i => Number(i?.logType) === 1)
|
|
|
} catch {
|
|
|
orderLogs.value = []
|
|
|
fulfillerLogs.value = []
|
|
|
@@ -827,8 +809,10 @@ const acceptTime = computed(() => orderLogs.value.find(l => l.title === '接单
|
|
|
const serviceProgressSteps = computed(() => {
|
|
|
const list = fulfillerLogs.value || []
|
|
|
return list.map((i) => {
|
|
|
- // 使用 _resolvedUrls(通过 listByIds 解析后的 OSS 可访问 URL),而非直接使用 photoUrls
|
|
|
- const media = Array.isArray(i?._resolvedUrls) ? i._resolvedUrls : []
|
|
|
+ const urls = i?.photoUrls || []
|
|
|
+ const media = Array.isArray(urls)
|
|
|
+ ? urls.map(url => ({ type: isVideo(url) ? 'video' : 'image', url }))
|
|
|
+ : []
|
|
|
|
|
|
return {
|
|
|
title: i?.title || '--',
|
|
|
@@ -872,28 +856,20 @@ const captureTime = ref('')
|
|
|
const captureBase64Cache = ref({})
|
|
|
|
|
|
/**
|
|
|
- * 将图片/OSS对象转换为 base64 DataURL @Author: Antigravity
|
|
|
- * 优先采用后端代理下载以解决跨域问题,如果无 ossId 则尝试直接 fetch
|
|
|
+ * 将图片URL转换为 base64 DataURL @Author: Antigravity
|
|
|
*/
|
|
|
-const loadImageAsBase64 = async (item) => {
|
|
|
- const { ossId, url } = item;
|
|
|
+const loadImageAsBase64 = async (url) => {
|
|
|
try {
|
|
|
- let blob;
|
|
|
- if (ossId) {
|
|
|
- blob = await downloadOssBlob(ossId);
|
|
|
- } else if (url) {
|
|
|
- const response = await fetch(url);
|
|
|
- blob = await response.blob();
|
|
|
- }
|
|
|
+ const response = await fetch(url);
|
|
|
+ const blob = await response.blob();
|
|
|
|
|
|
if (!blob || blob.size === 0) {
|
|
|
- console.warn('[FlowChart] 下载到的 Blob 为空:', url || ossId);
|
|
|
+ console.warn('[FlowChart] 下载到的 Blob 为空:', url);
|
|
|
return '';
|
|
|
}
|
|
|
|
|
|
- console.log(`[FlowChart] 成功获取 Blob: 尺寸=${blob.size}, 类型=${blob.type}, ID=${ossId || 'N/A'}`);
|
|
|
+ console.log(`[FlowChart] 成功获取 Blob: 尺寸=${blob.size}, 类型=${blob.type}`);
|
|
|
|
|
|
- // 如果是报错返回的 JSON
|
|
|
if (blob.type === 'application/json') {
|
|
|
const text = await blob.text();
|
|
|
console.error('[FlowChart] 图片下载返回了错误 JSON:', text);
|
|
|
@@ -904,11 +880,10 @@ const loadImageAsBase64 = async (item) => {
|
|
|
const reader = new FileReader();
|
|
|
reader.onloadend = () => {
|
|
|
const result = reader.result;
|
|
|
- // 只要是有效的 DataURL 且长度合理就通过,不再严格限制 image/ 前缀
|
|
|
if (typeof result === 'string' && result.length > 100) {
|
|
|
resolve(result);
|
|
|
} else {
|
|
|
- console.warn('[FlowChart] 生成的 Base64 长度不足或无效:', url || ossId);
|
|
|
+ console.warn('[FlowChart] 生成的 Base64 长度不足或无效:', url);
|
|
|
resolve('');
|
|
|
}
|
|
|
};
|
|
|
@@ -919,7 +894,7 @@ const loadImageAsBase64 = async (item) => {
|
|
|
reader.readAsDataURL(blob);
|
|
|
});
|
|
|
} catch (err) {
|
|
|
- console.error('[FlowChart] 图片加载异常:', url || ossId, err);
|
|
|
+ console.error('[FlowChart] 图片加载异常:', url, err);
|
|
|
return '';
|
|
|
}
|
|
|
}
|
|
|
@@ -942,15 +917,14 @@ const handleExportProgressImage = async () => {
|
|
|
captureTime.value = new Date().toLocaleString()
|
|
|
captureBase64Cache.value = {}
|
|
|
|
|
|
- // 收集所有需要预加载的图片 @Author: Antigravity
|
|
|
+ // 收集所有需要预加载的图片URL @Author: Antigravity
|
|
|
const itemsToLoad = []
|
|
|
for (const step of serviceProgressSteps.value) {
|
|
|
if (!step.media || !step.media.length) continue
|
|
|
for (const mediaItem of step.media) {
|
|
|
if (mediaItem.type === 'image' && mediaItem.url) {
|
|
|
- // 仅收集还未加载过的
|
|
|
if (!captureBase64Cache.value[mediaItem.url]) {
|
|
|
- itemsToLoad.push(mediaItem)
|
|
|
+ itemsToLoad.push(mediaItem.url)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -960,9 +934,9 @@ const handleExportProgressImage = async () => {
|
|
|
if (itemsToLoad.length > 0) {
|
|
|
console.log(`[FlowChart] 开始预加载 ${itemsToLoad.length} 张图片...`);
|
|
|
const results = await Promise.all(
|
|
|
- itemsToLoad.map(async (item) => {
|
|
|
- const b64 = await loadImageAsBase64(item);
|
|
|
- return { url: item.url, b64 };
|
|
|
+ itemsToLoad.map(async (url) => {
|
|
|
+ const b64 = await loadImageAsBase64(url);
|
|
|
+ return { url, b64 };
|
|
|
})
|
|
|
);
|
|
|
|