瀏覽代碼

feat: 退款处理页面增加订单视频展示,辅助确认退款信息

- admin-web: 退款详情弹窗并行获取订单媒体,展示购物视频
- admin-mp: 退款详情页增加订单视频区间,通过 getOrderMedia 查询

Co-Authored-By: Claude <noreply@anthropic.com>
skyline 1 月之前
父節點
當前提交
9006dbee82

+ 9 - 0
haha-admin-mp/src/api/order.ts

@@ -61,3 +61,12 @@ export async function handleRefund(
   if (data?.refundAmount) body.refundAmount = data.refundAmount;
   return post(`/order/${orderId}/refund`, body);
 }
+
+/**
+ * 获取订单开门前后图片/视频
+ */
+export async function getOrderMedia(orderId: string, activityId?: string): Promise<any> {
+  const params: any = { orderId };
+  if (activityId) params.activityId = activityId;
+  return get(`/orders/${orderId}/media`, params);
+}

+ 24 - 2
haha-admin-mp/src/pages/orders/refund-detail.vue

@@ -9,6 +9,16 @@
         <view class="info-row"><text class="info-label">申请时间</text><text class="info-value">{{ detail.createTime }}</text></view>
         <view class="info-row"><text class="info-label">状态</text><view class="card-status" :class="statusClass(detail.status)"><text>{{ RefundStatusText[detail.status] }}</text></view></view>
       </view>
+      <view class="section" v-if="orderVideoUrl">
+        <text class="section-title">订单视频</text>
+        <video
+          :src="orderVideoUrl"
+          controls
+          enable-play-gesture
+          object-fit="contain"
+          style="width:100%;height:400rpx;border-radius:12rpx;background:#000;"
+        />
+      </view>
     </scroll-view>
     <view class="bottom-actions" v-if="detail && detail.status === 0">
       <view class="action-row">
@@ -25,11 +35,23 @@ import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app';
 import NavBar from '@/components/NavBar.vue';
 import { getRefundDetail, reviewRefund } from '@/api/refund';
+import { getOrderMedia } from '@/api/order';
 import { RefundStatusText } from '@/utils/constants';
 import { formatMoney, showToast, showConfirm } from '@/utils/common';
-const detail = ref<any>(null); const remark = ref('');
+const detail = ref<any>(null); const remark = ref(''); const orderVideoUrl = ref('');
 onLoad((options?: Record<string, string>) => { const id = options?.id ? Number(options.id) : 0; if (id) loadDetail(id); });
-const loadDetail = async (id: number) => { try { detail.value = await getRefundDetail(id); } catch { showToast('加载失败'); uni.navigateBack(); } };
+const loadDetail = async (id: number) => {
+  try {
+    detail.value = await getRefundDetail(id);
+    if (detail.value?.orderId && detail.value?.activityId) {
+      try {
+        const media = await getOrderMedia(detail.value.orderId, detail.value.activityId);
+        if (media?.video_url) orderVideoUrl.value = media.video_url;
+        else if (media?.main_video?.length) orderVideoUrl.value = media.main_video[0];
+      } catch { /* 媒体获取失败不影响详情展示 */ }
+    }
+  } catch { showToast('加载失败'); uni.navigateBack(); }
+};
 const statusClass = (status: number) => status === 0 ? 'pending' : status === 1 ? 'approved' : 'rejected';
 const handleReview = async (approved: boolean) => {
   if (!(await showConfirm(approved ? '确认通过?' : '确认驳回?'))) return;

+ 29 - 4
haha-admin-web/src/views/order/refund/utils/hook.tsx

@@ -16,7 +16,8 @@ import {
   getRefundApplicationList,
   getRefundApplicationDetail,
   reviewRefundApplication,
-  getOrderById
+  getOrderById,
+  getOrderMedia
 } from "@/api/order";
 import type { RefundApplicationItem, RefundApplicationSearchForm } from "../../utils/types";
 import { type Ref, ref, reactive, onMounted } from "vue";
@@ -136,8 +137,19 @@ export function useRefund(tableRef: Ref) {
 
   async function handleOrderDetail(row: RefundApplicationItem) {
     try {
-      const { data } = await getOrderById(row.orderId);
-      const order = data as any;
+      // 并行获取订单详情和媒体信息
+      const [orderRes, mediaRes] = await Promise.allSettled([
+        getOrderById(row.orderId),
+        getOrderMedia({ orderId: row.orderNo })
+      ]);
+      const order = orderRes.status === "fulfilled" ? (orderRes.value.data as any) : null;
+      const media = mediaRes.status === "fulfilled" ? (mediaRes.value.data as any) : null;
+      if (!order) { message("获取订单详情失败", { type: "error" }); return; }
+
+      // 提取视频URL
+      const videoUrl: string | null = media?.video_url || media?.videoUrl
+        || (media?.main_video?.length ? media.main_video[0] : null)
+        || order.videoUrl || null;
 
       const payStatusMap: Record<string, { text: string; type: string }> = {
         "UNPAID": { text: "未支付", type: "warning" },
@@ -149,7 +161,7 @@ export function useRefund(tableRef: Ref) {
 
       addDialog({
         title: `订单详情 - ${row.orderNo}`,
-        width: "700px",
+        width: "780px",
         draggable: true,
         closeOnClickModal: false,
         contentRenderer: () => (
@@ -224,6 +236,19 @@ export function useRefund(tableRef: Ref) {
                 </ElTable>
               </>
             )}
+
+            {videoUrl && (
+              <>
+                <div style="font-size: 15px; font-weight: 600; margin: 14px 0 10px; color: var(--el-text-color-primary);">订单视频</div>
+                <video
+                  src={videoUrl}
+                  controls
+                  style="width:100%;max-height:400px;border-radius:8px;background:#000;"
+                >
+                  您的浏览器不支持视频播放
+                </video>
+              </>
+            )}
           </div>
         ),
         hideFooter: true