gaoluyang
昨天 352fbcfaa09e261918f5a7b50bcd9ba15583b1aa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<template>
  <el-dialog v-model="dialogVisible" title="退货单详情" width="90%" @close="closeDia">
    <div v-loading="loading">
      <span class="descriptions">基本信息</span>
      <el-descriptions :column="4" border>
        <el-descriptions-item label="退货单号">{{ detail.returnNo }}</el-descriptions-item>
        <el-descriptions-item label="单据状态">
          <el-tag :type="getStatusType(detail.status)">{{ getStatusText(detail.status) }}</el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="客户名称">{{ detail.customerName }}</el-descriptions-item>
        <el-descriptions-item label="销售单号">{{ detail.salesContractNo }}</el-descriptions-item>
        <el-descriptions-item label="业务员">{{ detail.salesman }}</el-descriptions-item>
        <el-descriptions-item label="关联出库单号">{{ detail.shippingNo }}</el-descriptions-item>
        <el-descriptions-item label="项目名称">{{ detail.projectName }}</el-descriptions-item>
        <el-descriptions-item label="制单人">{{ detail.maker }}</el-descriptions-item>
        <el-descriptions-item label="制单时间">{{ detail.makeTime }}</el-descriptions-item>
        <el-descriptions-item label="退货原因">{{ detail.returnReason }}</el-descriptions-item>
        <el-descriptions-item label="退款总额">{{ detail.refundAmount }}</el-descriptions-item>
      </el-descriptions>
 
      <div style="padding-top: 20px">
        <span class="descriptions">产品列表</span>
        <PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData" />
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="closeDia">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>
 
<script setup>
import { ref } from "vue";
import { returnManagementGetById, returnManagementGetByShippingId } from "@/api/salesManagement/returnOrder.js";
 
const dialogVisible = ref(false);
const loading = ref(false);
const detail = ref({});
const tableData = ref([]);
const availableProducts = ref([]);
 
const tableColumn = [
  {align: "center", label: "产品大类", prop: "productCategory"},
  {align: "center", label: "规格型号", prop: "specificationModel"},
  {align: "center", label: "单位", prop: "unit", width: 80},
  {align: "center", label: "总数量", prop: "quantity", width: 120},
  {align: "center", label: "已退货数量", prop: "totalReturnNum", width: 120},
  {align: "center", label: "未退货数量", prop: "unQuantity", width: 120},
  {align: "center", label: "退货数量", prop: "returnQuantity", width: 120},
  {align: "center", label: "退货产品单价", prop: "price", width: 120},
  {align: "center", label: "退货产品金额", prop: "amount", width: 120},
  {align: "center", label: "是否有质量问题", prop: "isQuality", width: 140, formatData: (v) => ({ "1": "是", "2": "否" }[String(v)] ?? v)},
  {align: "center", label: "备注", prop: "remark", width: 150},
];
 
const getStatusType = (status) => {
  const statusMap = {
    0: "warning",
    1: "success"
  };
  return statusMap[status] || "info";
};
 
const getStatusText = (status) => {
  const statusMap = {
    0: "待处理",
    1: "已处理"
  };
  return statusMap[status] || "未知";
};
 
const openDialog = async (row) => {
  if (!row?.id) return;
  dialogVisible.value = true;
  loading.value = true;
  try {
    const res = await returnManagementGetById({ returnManagementId: row.id });
    detail.value = res?.data ?? res ?? {};
    
    if (detail.value.shippingId) {
      const productRes = await returnManagementGetByShippingId({ shippingId: detail.value.shippingId });
      if (productRes.code === 200) {
        availableProducts.value = productRes.data.productDtoData || [];
      }
    }
    
    const list =
      detail.value?.returnSaleProducts ||
        detail.value?.returnSaleProductList ||
        detail.value?.returnSaleProductDtoData ||
        [];
    
    tableData.value = Array.isArray(list) ? list.map(raw => {
      const productId = raw?.returnSaleLedgerProductId ?? raw?.saleLedgerProductId ?? raw?.id;
      const product = availableProducts.value.find((p) => p.id === productId);
      const normalized = {
        ...raw,
        id: productId,
        returnQuantity: Number(raw?.num ?? raw?.returnQuantity ?? 0),
        price: Number(raw?.taxInclusiveUnitPrice ?? raw?.price ?? 0),
        amount: Number(raw?.amount ?? 0).toFixed(2),
        isQuality: raw?.isQuality ?? 2,
        remark: raw?.remark ?? "",
      };
      return product ? { ...product, ...normalized } : normalized;
    }) : [];
  } catch (e) {
    console.error("Failed to load detail", e);
  } finally {
    loading.value = false;
  }
};
 
const closeDia = () => {
  dialogVisible.value = false;
  detail.value = {};
  tableData.value = [];
  availableProducts.value = [];
};
 
defineExpose({ openDialog });
</script>
 
<style scoped lang="scss">
.descriptions {
  margin-bottom: 20px;
  display: inline-block;
  font-size: 1rem;
  font-weight: 600;
  padding-left: 12px;
  position: relative;
}
.descriptions::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 1rem;
  background-color: #002FA7;
  border-radius: 2px;
}
</style>