张田田 hace 2 meses
padre
commit
4155f85230
Se han modificado 5 ficheros con 258 adiciones y 158 borrados
  1. 1 1
      src/model/order.model.ts
  2. 25 10
      src/order/Amount.vue
  3. 106 48
      src/order/Negotiations.vue
  4. 88 41
      src/order/Review.vue
  5. 38 58
      src/pages/index/order/afterSale.vue

+ 1 - 1
src/model/order.model.ts

@@ -254,7 +254,7 @@ export interface AfterSaleNegotiateModel {
   content: string; // 内容描述
   createTime: string; // 操作时间
   createBy: string;//操作者
-  aftersaleContent: string; // 售后申请信息
+  aftersaleContent: Record<string, any>; // 售后申请信息
 }
 
 // 售后审核

+ 25 - 10
src/order/Amount.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { ref, computed, watch } from 'vue';
 import { Button, Input, message } from 'ant-design-vue';
+import { getConfirmAmountMethod } from '@/request/api/order.api';
 
 const props = defineProps<{
   data?: any;
@@ -13,7 +14,7 @@ const emit = defineEmits<{
 
 // 初始申请金额
 const originalAmount = computed(() => {
-  return props.data?.refundAmount || 240.00;
+  return props.data?.applyAmount || 0;
 });
 
 // 最终退款金额 (双向绑定)
@@ -21,8 +22,10 @@ const finalAmount = ref<string | number>(originalAmount.value.toFixed(2));
 
 // 监听数据变化同步初始值
 watch(() => props.data, (newVal) => {
-  if (newVal?.refundAmount) {
-    finalAmount.value = newVal.refundAmount.toFixed(2);
+  if (newVal?.reviewAmount != null) {
+    finalAmount.value = newVal.reviewAmount.toFixed(2);
+  } else if (newVal?.applyAmount != null) {
+    finalAmount.value = newVal.applyAmount.toFixed(2);
   }
 }, { immediate: true });
 
@@ -40,23 +43,35 @@ function handleBlur() {
     val = 0;
   }
   
-  // 不能超过商品原金额
   if (val > originalAmount.value) {
-    message.warning(`退款金额不能超过申请金额 ¥${originalAmount.value.toFixed(2)}`);
-    val = originalAmount.value;
+    return;
   }
-  
+
   finalAmount.value = val.toFixed(2);
 }
 
 // 提交
-function handleConfirm() {
+const submitting = ref(false);
+async function handleConfirm() {
+  if (submitting.value) return;
   const val = parseFloat(finalAmount.value as string);
   if (isNaN(val) || val < 0) {
     message.error('请输入有效的退款金额');
     return;
   }
-  emit('submit', val);
+  if (val > originalAmount.value) {
+    message.warning(`退款金额不能超过申请金额 ¥${originalAmount.value.toFixed(2)}`);
+    return;
+  }
+  if (!props.data?.id) return;
+  submitting.value = true;
+  try {
+    await getConfirmAmountMethod(props.data.id, val);
+    message.success('金额确认成功');
+    emit('submit', val);
+  } finally {
+    submitting.value = false;
+  }
 }
 
 // 取消
@@ -98,7 +113,7 @@ function handleCancel() {
       <!-- 底部按钮 -->
       <div class="footer-actions">
         <Button @click="handleCancel" class="btn-cancel">取消</Button>
-        <Button type="primary" @click="handleConfirm" class="btn-confirm">确定</Button>
+        <Button type="primary" :loading="submitting" @click="handleConfirm" class="btn-confirm">确定</Button>
       </div>
     </div>
   </div>

+ 106 - 48
src/order/Negotiations.vue

@@ -1,6 +1,8 @@
 <script setup lang="ts">
-import { computed } from 'vue';
+import { ref, onMounted } from 'vue';
 import { Avatar, Image } from 'ant-design-vue';
+import type { AfterSaleNegotiateModel } from '@/model/order.model';
+import { getAftersaleLogMethod } from '@/request/api/order.api';
 
 const props = defineProps<{
   data?: any;
@@ -8,7 +10,6 @@ const props = defineProps<{
 
 // 协商历史条目类型
 interface NegotiationItem {
-  avatar: string;
   name: string;
   time: string;
   action: string;
@@ -18,48 +19,106 @@ interface NegotiationItem {
   images?: string[];
 }
 
-// 默认假数据 (模拟图片中的内容)
-const mockNegotiationHistory: NegotiationItem[] = [
-  {
-    avatar: 'https://img.yzcdn.cn/vant/cat.jpeg',
-    name: '谢芳',
-    time: '2025-02-19 14:30:35',
-    action: '撤销退款申请',
-  },
-  {
-    avatar: 'https://img0.baidu.com/it/u=670138986,218049280&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
-    name: '平台',
-    time: '2025-02-19 14:30:35',
-    action: '平台拒绝了申请',
-    title: '平台拒绝了申请',
-    content: '请选择原因为与卖家协商一致',
-  },
-  {
-    avatar: 'https://img.yzcdn.cn/vant/cat.jpeg',
-    name: '谢芳',
-    time: '2025-02-19 14:30:27',
-    action: '发起了退款申请',
-    fields: [
-      { label: '商品状态', value: '未收货' },
-      { label: '退款类型', value: '退款' },
-      { label: '退款金额', value: '¥240.00' },
-      { label: '退款原因', value: '少件(含缺少配件)' },
-      { label: '退款说明', value: '1111' },
-    ],
-    images: [
-      'https://img2.baidu.com/it/u=1784082031,1597724266&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1360',
-      'https://img1.baidu.com/it/u=3479126922,3943933034&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=732',
-      'https://img2.baidu.com/it/u=1784082031,1597724266&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1360',
-      'https://img2.baidu.com/it/u=1784082031,1597724266&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1360',
-      'https://img2.baidu.com/it/u=1784082031,1597724266&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=1360',
-    ],
-  },
-];
-
-// 实际使用的数据 (如果有 props.data 则可进行转换,暂用 mock)
-const displayHistory = computed(() => {
-  return mockNegotiationHistory;
+const progressMap: Record<string, string> = {
+  '0': '发起了售后申请',
+  '1': '撤销售后申请',
+  '2': '审核拒绝了申请',
+  '3': '审核通过了申请',
+  '4': '退款完成',
+};
+
+// aftersaleContent 字段中文映射
+const fieldLabelMap: Record<string, string> = {
+  applyAmount: '退款金额',
+  reason: '退款原因',
+  receiptStatus: '商品状态',
+  remark: '退款说明',
+  type: '退款类型',
+  finishRatio: '完成比例',
+};
+
+// 需要过滤掉的字段(ID类字段)
+const hiddenFields = new Set([
+  'patientConditioningProgramId',
+  'patientConditioningRecordId',
+  'id',
+  'orderNo',
+]);
+
+// 特殊值的中文映射
+const valueMap: Record<string, Record<string, string>> = {
+  receiptStatus: { '1': '已收到货', '2': '未收到货' },
+  type: { '0': '退款', '1': '退货退款' },
+};
+
+const logList = ref<AfterSaleNegotiateModel[]>([]);
+const loading = ref(false);
+
+onMounted(async () => {
+  if (props.data?.id) {
+    loading.value = true;
+    try {
+      const res = await getAftersaleLogMethod(props.data.id);
+      logList.value = (res as any) || [];
+    } finally {
+      loading.value = false;
+    }
+  }
 });
+
+// 将接口数据转换为展示格式
+const displayHistory = ref<NegotiationItem[]>([]);
+
+// 监听 logList 变化后转换
+function transformData() {
+  displayHistory.value = logList.value.map(item => {
+    const result: NegotiationItem = {
+      name: item.createBy || '',
+      time: item.createTime || '',
+      action: progressMap[item.progress] || item.title || '',
+      title: item.title || undefined,
+      content: item.content || undefined,
+    };
+    // 解析 aftersaleContent 中的字段和图片
+    let contentObj = item.aftersaleContent;
+    if (typeof contentObj === 'string') {
+      try { contentObj = JSON.parse(contentObj); } catch { contentObj = null; }
+    }
+    if (contentObj && typeof contentObj === 'object') {
+      const fields: { label: string; value: string }[] = [];
+      const images: string[] = [];
+      Object.entries(contentObj).forEach(([key, val]) => {
+        if (key === 'images' || key === 'voucherImgs') {
+          if (Array.isArray(val)) {
+            images.push(...val);
+          }
+        } else if (hiddenFields.has(key)) {
+          // 过滤掉ID类字段
+          return;
+        } else if (fieldLabelMap[key] && val !== undefined && val !== null && val !== '') {
+          const label = fieldLabelMap[key];
+          let displayVal = String(val);
+          // 特殊值转换
+          if (valueMap[key] && valueMap[key][String(val)]) {
+            displayVal = valueMap[key][String(val)];
+          }
+          // 金额字段加前缀
+          if (key === 'applyAmount') {
+            displayVal = `¥${displayVal}`;
+          }
+          fields.push({ label, value: displayVal });
+        }
+      });
+      if (fields.length) result.fields = fields;
+      if (images.length) result.images = images;
+    }
+    return result;
+  });
+}
+
+// 数据加载后转换
+import { watch } from 'vue';
+watch(logList, () => transformData(), { immediate: true });
 </script>
 
 <template>
@@ -68,7 +127,7 @@ const displayHistory = computed(() => {
       <div v-for="(item, index) in displayHistory" :key="index" class="negotiation-item">
         <!-- 头部信息: 头像、名称、时间 -->
         <div class="item-header">
-          <Avatar :src="item.avatar" :size="40" class="user-avatar" />
+          <Avatar :size="40" class="user-avatar">{{ item.name?.charAt(0) }}</Avatar>
           <div class="header-info">
             <span class="user-name">{{ item.name }}</span>
             <span class="action-time">{{ item.time }}</span>
@@ -80,10 +139,9 @@ const displayHistory = computed(() => {
           <!-- 简单动作标题 -->
           <div class="action-title" v-if="item.action">{{ item.action }}</div>
 
-          <!-- 平台拒绝等详情 -->
-          <div class="detail-box" v-if="item.title || item.content">
-            <div class="detail-row" v-if="item.title">【标题】{{ item.title }}</div>
-            <div class="detail-row" v-if="item.content">【内容】{{ item.content }}</div>
+          <!-- 平台拒绝等详情(content 为 JSON 字符串时不显示) -->
+          <div class="detail-box" v-if="item.content && !item.content.startsWith('{')">
+            <div class="detail-row">{{ item.content }}</div>
           </div>
 
           <!-- 发起申请详情 -->

+ 88 - 41
src/order/Review.vue

@@ -1,9 +1,12 @@
 <script setup lang="ts">
-import { ref, computed, h } from 'vue';
-import { Avatar, Image, Radio, Button, Input } from 'ant-design-vue';
+import { ref, computed, h, onMounted } from 'vue';
+import { Avatar, Image, Radio, Button, Input, message } from 'ant-design-vue';
 import { VxeUI } from 'vxe-pc-ui';
 import Negotiations from './Negotiations.vue';
 import LogisticsDetails from './LogisticsDetails.vue';
+import type { AfterSaleModel } from '@/model/order.model';
+import { getAfterSaleDetailMethod, getAftersaleReviewMethod } from '@/request/api/order.api';
+
 const props = defineProps<{
   data?: any;
 }>();
@@ -13,6 +16,23 @@ const emit = defineEmits<{
   'close': [];
 }>();
 
+// 售后详情数据
+const detailData = ref<AfterSaleModel>();
+const loading = ref(false);
+
+// 获取售后详情
+onMounted(async () => {
+  if (props.data?.id) {
+    loading.value = true;
+    try {
+      const res = await getAfterSaleDetailMethod(props.data.id);
+      detailData.value = res as any;
+    } finally {
+      loading.value = false;
+    }
+  }
+});
+
 // 是否收起协商历史
 const isNegotiationCollapsed = ref(false);
 
@@ -20,22 +40,42 @@ const isNegotiationCollapsed = ref(false);
 const reviewStatus = ref('agree');
 // 理由
 const reviewReason = ref('');
+const reasonValidated = ref(false);
 
-// 模拟顶部的商品数据
+// 商品信息
 const productInfo = computed(() => {
+  const d = detailData.value;
   return {
-    name: props.data?.productName || '肝血虚穴位贴',
-    price: 30,
-    qty: 8,
-    totalPrice: 240,
-    specs: '10贴',
-    imageUrl: 'https://img.yzcdn.cn/vant/cat.jpeg'
+    name: d?.conditioningProgramName || '',
+    price: d?.unitPrice || 0,
+    qty: d?.totalMeasure || 0,
+    totalPrice: d?.totalPrice || 0,
+    specs: d?.convertDose ? `${d.convertDose}${d.convertUnit || ''}` : '',
+    imageUrl: d?.conditioningProgramPhoto || '',
   };
 });
 
 // 处理提交
-function handleConfirm() {
-  emit('submit', reviewStatus.value, reviewReason.value);
+const submitting = ref(false);
+async function handleConfirm() {
+  if (submitting.value) return;
+  if (!detailData.value?.id) return;
+  if (reviewStatus.value === 'reject' && !reviewReason.value.trim()) {
+    reasonValidated.value = true;
+    return;
+  }
+  submitting.value = true;
+  try {
+    await getAftersaleReviewMethod({
+      id: detailData.value.id,
+      isAgree: reviewStatus.value === 'agree',
+      reason: reviewStatus.value === 'reject' ? reviewReason.value : '',
+    });
+    message.success('审核成功');
+    emit('submit', reviewStatus.value, reviewReason.value);
+  } finally {
+    submitting.value = false;
+  }
 }
 
 // 查看物流
@@ -50,7 +90,7 @@ function viewLogistics() {
     slots: {
       default() {
         return h(LogisticsDetails, {
-          data: props.data
+          data: detailData.value
         });
       }
     }
@@ -64,11 +104,11 @@ function handleCancel() {
 </script>
 
 <template>
-  <div class="review-page-container">
+  <div class="review-page-container" v-if="!loading">
     <!-- 商品信息头部 -->
     <div class="product-info-section">
       <div class="product-card">
-        <Image :src="productInfo.imageUrl" :width="70" :height="70" class="product-image" />
+        <Image v-if="productInfo.imageUrl" :src="productInfo.imageUrl" :width="70" :height="70" class="product-image" />
         <div class="product-details">
           <div class="detail-row header-row">
             <span class="product-name">{{ productInfo.name }}</span>
@@ -95,42 +135,41 @@ function handleCancel() {
         <div class="info-list">
           <div class="info-item">
             <span class="label">申请时间:</span>
-            <span class="value">2025-02-19 14:30:27</span>
+            <span class="value">{{ detailData?.applyTime }}</span>
           </div>
-          <div class="info-item">
-            <span class="label">商品状态:</span>
-            <span class="value">未收货</span>
-          </div>
-          <div class="info-item methods-item">
-            <span class="label">发货方式:</span>
-            <span class="value">线下取货</span>
-            <span class="label method-label">发货方式:</span>
-            <span class="value">配送</span>
-            <a href="javascript:;" class="shipping-link" @click="viewLogistics">运输中</a>
+          <div class="info-item" style="gap: 20px;">
+            <span>
+              <span class="label">商品状态:</span>
+              <span class="value">{{ detailData?.receiptStatusStr }}</span>
+            </span>
+            <span>
+              <span class="label">发货方式:</span>
+              <span class="value">{{ detailData?.receiptTypeStr }}</span>
+            </span>
           </div>
           <div class="info-item">
             <span class="label">退款类型:</span>
-            <span class="value">退款</span>
+            <span class="value">{{ detailData?.typeStr }}</span>
           </div>
           <div class="info-item">
             <span class="label">退款金额:</span>
-            <span class="value amount-value">¥240.00</span>
+            <span class="value amount-value">¥{{ detailData?.applyAmount }}</span>
           </div>
           <div class="info-item">
             <span class="label">退款原因:</span>
-            <span class="value">少件(含缺少配件)</span>
+            <span class="value">{{ detailData?.reason }}</span>
           </div>
           <div class="info-item">
             <span class="label">退款说明:</span>
-            <span class="value">111</span>
+            <span class="value">{{ detailData?.remark }}</span>
           </div>
         </div>
 
         <!-- 凭证图片 -->
-        <div class="proof-images">
+        <div class="proof-images" v-if="detailData?.voucherImgs?.length">
           <Image.PreviewGroup>
-            <div v-for="i in 5" :key="i" class="image-wrapper">
-              <Image :src="`https://img.yzcdn.cn/vant/cat.jpeg#${i}`" :width="40" :height="40" />
+            <div v-for="(img, index) in detailData.voucherImgs" :key="index" class="image-wrapper">
+              <Image :src="img" :width="40" :height="40" />
             </div>
           </Image.PreviewGroup>
         </div>
@@ -148,7 +187,7 @@ function handleCancel() {
           </a>
         </div>
         <div class="negotiation-content" v-show="!isNegotiationCollapsed">
-          <Negotiations />
+          <Negotiations :data="detailData" />
         </div>
       </div>
     </div>
@@ -166,16 +205,18 @@ function handleCancel() {
           </Radio.Group>
         </div>
         <div class="reason-row" v-if="reviewStatus === 'reject'">
-          <div class="reason-label">拒绝理由</div>
-          <Input.TextArea 
-            v-model:value="reviewReason" 
-            placeholder="请输入拒绝退款的理由" 
-            :rows="4" />
+          <div class="reason-label">拒绝理由<span style="color: #ff4d4f;"> *</span></div>
+          <Input.TextArea
+            v-model:value="reviewReason"
+            placeholder="请输入拒绝退款的理由"
+            :rows="4"
+            :status="reviewReason.trim() === '' && reasonValidated ? 'error' : undefined" />
+          <div v-if="reviewReason.trim() === '' && reasonValidated" class="reason-error">请输入拒绝理由</div>
         </div>
       </div>
       <div class="action-buttons">
         <Button @click="handleCancel">取消</Button>
-        <Button type="primary" @click="handleConfirm" class="confirm-btn">确定</Button>
+        <Button type="primary" :loading="submitting" @click="handleConfirm" class="confirm-btn">确定</Button>
       </div>
     </div>
   </div>
@@ -211,7 +252,7 @@ function handleCancel() {
         justify-content: space-between;
         margin-bottom: 4px;
         width: 20%;
-        
+
         &.header-row {
           .product-name {
             font-size: 14px;
@@ -360,7 +401,7 @@ function handleCancel() {
       flex: 1;
       overflow-y: auto;
       max-height: 340px;
-      
+
       :deep(.negotiations-container) {
         padding: 5px 0;
       }
@@ -390,6 +431,12 @@ function handleCancel() {
         margin-bottom: 12px;
         font-weight: 500;
       }
+
+      .reason-error {
+        color: #ff4d4f;
+        font-size: 12px;
+        margin-top: 4px;
+      }
     }
   }
 

+ 38 - 58
src/pages/index/order/afterSale.vue

@@ -10,21 +10,11 @@ defineOptions({
   name: 'AfterSalePage',
 });
 // 接口数据
-import {
-  getAfterSaleMethod,
-} from '@/request/api/order.api';
+import { getAfterSaleMethod } from '@/request/api/order.api';
 import { usePagination } from 'alova/client';
 
-import {
-  type VxeFormListeners,
-  type VxeFormProps,
-  VxeUI,
-} from 'vxe-pc-ui';
-import type {
-  VxeGridInstance,
-  VxeGridListeners,
-  VxeGridProps,
-} from 'vxe-table';
+import { type VxeFormListeners, type VxeFormProps, VxeUI } from 'vxe-pc-ui';
+import type { VxeGridInstance, VxeGridListeners, VxeGridProps } from 'vxe-table';
 
 const progressOptions = [
   { label: '退款申请中', value: '0' },
@@ -113,7 +103,7 @@ const gridOptions = reactive<VxeGridProps<AfterSaleModel>>({
   },
   columns: [
     { type: 'seq', width: 70, fixed: 'left' },
-    { field: 'orderNo', title: '订单编号', slots: { default: 'orderNoCell' } },
+    { field: 'orderNo', title: '订单编号' },
     { field: 'typeStr', title: '售后类型' },
     { field: 'updateTime', title: '退款更新时间' },
     { field: 'conditioningProgramName', title: '项目名称' },
@@ -121,8 +111,8 @@ const gridOptions = reactive<VxeGridProps<AfterSaleModel>>({
     { field: 'totalPrice', title: '总价(元)' },
     { field: 'liaison', title: '收货人' },
     { field: 'progressStr', title: '退款状态' },
-    { field: 'expressStatus', title: '物流状态' },
-    { field: 'finishRatio', title: '核销情况' },
+    { field: 'expressStatus', title: '物流状态', slots: { default: 'expressStatusCell' } },
+    { field: 'finishRatio', title: '核销情况', slots: { default: 'finishRatioCell' } },
     { field: 'refundAmount', title: '退款金额' },
     { field: 'reason', title: '退款原因' },
     { field: 'remark', title: '退款说明', slots: { default: 'refundReasonCell' } },
@@ -139,16 +129,13 @@ const gridOptions = reactive<VxeGridProps<AfterSaleModel>>({
 });
 const gridEvents: VxeGridListeners = {};
 
-const { loading, page, pageSize, total, onSuccess, refresh } = usePagination(
-  (page, size) => getAfterSaleMethod(page, size, model.value),
-  {
-    initialData: { data: [], total: 0 },
-    initialPage: 1,
-    initialPageSize: 100,
-    watchingStates: [model],
-    immediate: false,
-  }
-);
+const { loading, page, pageSize, total, onSuccess, refresh } = usePagination((page, size) => getAfterSaleMethod(page, size, model.value), {
+  initialData: { data: [], total: 0 },
+  initialPage: 1,
+  initialPageSize: 100,
+  watchingStates: [model],
+  immediate: false,
+});
 onSuccess(({ data: { data } }) => {
   gridRef.value?.loadData(data);
 });
@@ -157,7 +144,6 @@ onMounted(() => {
   model.value = toRaw(searchFormProps.data);
 });
 
-
 // 点击订单编号查看订单详情
 function serviceDetail(row?: AfterSaleModel) {
   if (!row) return;
@@ -211,10 +197,10 @@ async function goShipment(row?: AfterSaleModel) {
             },
             onClose: () => {
               VxeUI.modal.close('review-modal');
-            }
+            },
           });
-        }
-      }
+        },
+      },
     });
   } else {
     // 金额 or 查看金额
@@ -232,16 +218,15 @@ async function goShipment(row?: AfterSaleModel) {
           return h(component, {
             data: row,
             onSubmit: (amount: number) => {
-              console.log('Final Amount:', amount);
               refresh(page.value);
               VxeUI.modal.close('amount-edit-modal');
             },
             onClose: () => {
               VxeUI.modal.close(isEditAmount ? 'amount-edit-modal' : 'amount-see-modal');
-            }
+            },
           });
-        }
-      }
+        },
+      },
     });
   }
 }
@@ -258,10 +243,10 @@ function goAfterSale(row?: AfterSaleModel) {
     slots: {
       default() {
         return h(Negotiations, {
-          data: row
+          data: row,
         });
-      }
-    }
+      },
+    },
   });
 }
 </script>
@@ -272,19 +257,20 @@ function goAfterSale(row?: AfterSaleModel) {
     </header>
     <main class="flex-auto overflow-hidden">
       <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents" :loading="loading">
-        <template #orderNoCell="{ row }">
-          <span class="order-no-link" @click="serviceDetail(row)">{{ row.orderNo }}</span>
-        </template>
         <template #refundReasonCell="{ row }">
           <span class="order-no-link" @click="goAfterSale(row)">{{ row.remark }}</span>
         </template>
+        <template #expressStatusCell="{ row }">
+          {{ row.expressStatus || '/' }}
+        </template>
+        <template #finishRatioCell="{ row }">
+          {{ row.sellType === '2' ? row.finishRatio || '/' : '/' }}
+        </template>
         <template #action="{ row }">
-          <vxe-button mode="text" status="primary" @click="goAfterSale(row)">
-            协商历史
-          </vxe-button>
-          <vxe-button mode="text" status="primary" @click="goShipment(row)">
-            {{ row.progress === '0' ? '审核' : row.progress === '3' ? '金额' : '查看金额' }}
-          </vxe-button>
+          <vxe-button mode="text" status="primary" @click="goAfterSale(row)"> 协商历史 </vxe-button>
+          <vxe-button v-if="row.progress === '0'" mode="text" status="primary" @click="goShipment(row)"> 审核 </vxe-button>
+          <vxe-button v-if="row.progress === '3'" mode="text" status="primary" @click="goShipment(row)"> 金额 </vxe-button>
+          <vxe-button v-if="row.progress === '4'" mode="text" status="primary" @click="goShipment(row)"> 查看金额 </vxe-button>
         </template>
         <template #toolbar-extra>
           <vxe-button style="margin-right: 12px" icon="vxe-icon-repeat" circle @click="refresh(page)"></vxe-button>
@@ -292,18 +278,12 @@ function goAfterSale(row?: AfterSaleModel) {
       </vxe-grid>
     </main>
     <footer class="flex-none">
-      <vxe-pager v-model:current-page="page" v-model:page-size="pageSize" :total="total" :layouts="[
-        'Home',
-        'PrevJump',
-        'PrevPage',
-        'Number',
-        'NextPage',
-        'NextJump',
-        'End',
-        'Sizes',
-        'FullJump',
-        'Total',
-      ]" />
+      <vxe-pager
+        v-model:current-page="page"
+        v-model:page-size="pageSize"
+        :total="total"
+        :layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']"
+      />
     </footer>
   </div>
 </template>