detail.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <div class="page-container">
  3. <div class="page-header">
  4. <el-button type="primary" link @click="handleBack">
  5. <el-icon><ArrowLeft /></el-icon>返回
  6. </el-button>
  7. <span class="page-title">对账单详情</span>
  8. </div>
  9. <div v-loading="loading">
  10. <el-descriptions title="基本信息" :column="2" border class="margin-bottom">
  11. <el-descriptions-item label="对账编号">{{ form.statementOrderNo }}</el-descriptions-item>
  12. <el-descriptions-item label="客户名称">{{ form.customerName || '-' }}</el-descriptions-item>
  13. <el-descriptions-item label="对账金额(元)">¥{{ form.amount != null ? Number(form.amount).toFixed(2) : '-' }}</el-descriptions-item>
  14. <el-descriptions-item label="对账日期">{{ parseTime(form.statementDate, '{y}-{m}-{d}') || '-' }}</el-descriptions-item>
  15. <el-descriptions-item label="对账人">{{ form.statementSelf || '-' }}</el-descriptions-item>
  16. <el-descriptions-item label="联系电话">{{ form.statementSelfPhone || '-' }}</el-descriptions-item>
  17. <el-descriptions-item label="对账状态">
  18. {{ getDictLabel(statement_status, form.statementStatus) }}
  19. </el-descriptions-item>
  20. <el-descriptions-item label="开票状态">
  21. {{ getDictLabel(invoice_issuance_status, form.isInvoiceStatus) }}
  22. </el-descriptions-item>
  23. <el-descriptions-item label="支付状态">
  24. {{ getDictLabel(payment_status, form.isPaymentStatus) }}
  25. </el-descriptions-item>
  26. <el-descriptions-item label="备注" :span="2">{{ form.remark || '-' }}</el-descriptions-item>
  27. </el-descriptions>
  28. <!-- 订单明细列表 -->
  29. <div v-if="form.detailList && form.detailList.length > 0">
  30. <el-divider content-position="left">对账明细</el-divider>
  31. <el-table :data="form.detailList" border style="width: 100%; margin-bottom: 20px">
  32. <el-table-column prop="orderNo" label="订单编号" min-width="150" align="center" />
  33. <el-table-column prop="deliverCode" label="发货单号" min-width="150" align="center" />
  34. <el-table-column prop="amount" label="金额(元)" min-width="100" align="center">
  35. <template #default="{ row }"> ¥{{ row.amount != null ? Number(row.amount).toFixed(2) : '-' }} </template>
  36. </el-table-column>
  37. <el-table-column prop="orderTime" label="订单时间" min-width="150" align="center">
  38. <template #default="{ row }">
  39. <span>{{ parseTime(row.orderTime) || '-' }}</span>
  40. </template>
  41. </el-table-column>
  42. </el-table>
  43. </div>
  44. <!-- 商品明细列表 -->
  45. <div v-if="form.productList && form.productList.length > 0">
  46. <el-divider content-position="left">商品清单</el-divider>
  47. <el-table :data="form.productList" border style="width: 100%">
  48. <el-table-column prop="itemName" label="商品名称" min-width="150" align="center" show-overflow-tooltip />
  49. <el-table-column prop="productNo" label="商品编号" min-width="120" align="center" />
  50. <el-table-column prop="unitPrice" label="单价" min-width="90" align="center" />
  51. <el-table-column prop="quantity" label="数量" min-width="90" align="center" />
  52. <el-table-column prop="unitName" label="单位" min-width="60" align="center" />
  53. </el-table>
  54. </div>
  55. <!-- 对账附件 -->
  56. <div v-if="form.annexAddress">
  57. <el-divider content-position="left">对账附件</el-divider>
  58. <el-table :data="attachmentList" border style="width: 100%">
  59. <el-table-column type="index" label="序号" width="80" align="center" />
  60. <el-table-column prop="name" label="文件名称" min-width="200" align="center" />
  61. <el-table-column label="操作" width="150" align="center">
  62. <template #default="{ row }">
  63. <el-button type="primary" link @click="handlePreview(row.url)">预览</el-button>
  64. </template>
  65. </el-table-column>
  66. </el-table>
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <script setup lang="ts">
  72. import { ref, computed, getCurrentInstance, toRefs, onMounted } from 'vue';
  73. import { useRoute, useRouter } from 'vue-router';
  74. import { ArrowLeft } from '@element-plus/icons-vue';
  75. import { ElMessage } from 'element-plus';
  76. import { getStatementInfo } from '@/api/pc/enterprise/statement';
  77. import type { StatementOrder } from '@/api/pc/enterprise/statementTypes';
  78. const { proxy } = getCurrentInstance() as any;
  79. const { statement_status, invoice_issuance_status, payment_status } = toRefs<any>(
  80. proxy?.useDict('statement_status', 'invoice_issuance_status', 'payment_status')
  81. );
  82. const route = useRoute();
  83. const router = useRouter();
  84. const loading = ref(false);
  85. const form = ref<Partial<StatementOrder>>({});
  86. // 附件列表
  87. const attachmentList = computed(() => {
  88. if (!form.value.annexAddress) return [];
  89. const urls = form.value.annexAddress.split(',').filter(Boolean);
  90. return urls.map((url, index) => {
  91. const fileName = url.split('/').pop() || `附件${index + 1}`;
  92. return {
  93. name: decodeURIComponent(fileName),
  94. url: url.trim()
  95. };
  96. });
  97. });
  98. const getDictLabel = (dictOptions: any[], value: string) => {
  99. if (!dictOptions || !value) return value;
  100. const dict = dictOptions.find((item) => item.value === value);
  101. return dict ? dict.label : value;
  102. };
  103. // 预览附件
  104. const handlePreview = (url: string) => {
  105. if (!url) {
  106. ElMessage.warning('文件地址不存在');
  107. return;
  108. }
  109. window.open(url, '_blank');
  110. };
  111. const handleBack = () => {
  112. router.back();
  113. };
  114. const loadDetail = async (id: number | string) => {
  115. loading.value = true;
  116. try {
  117. const res = await getStatementInfo(id);
  118. if (res.code === 200) {
  119. form.value = res.data || {};
  120. } else {
  121. ElMessage.error(res.msg || '获取详情失败');
  122. }
  123. } catch (error) {
  124. console.error('获取对账单详情失败:', error);
  125. ElMessage.error('获取对账单详情失败');
  126. } finally {
  127. loading.value = false;
  128. }
  129. };
  130. onMounted(() => {
  131. const id = route.query.id;
  132. if (id) {
  133. loadDetail(id as string);
  134. } else {
  135. ElMessage.error('缺少对账单ID');
  136. handleBack();
  137. }
  138. });
  139. </script>
  140. <style scoped lang="scss">
  141. .page-container {
  142. padding: 20px;
  143. background: #fff;
  144. min-height: 100%;
  145. flex: 1;
  146. }
  147. .page-header {
  148. display: flex;
  149. align-items: center;
  150. gap: 10px;
  151. margin-bottom: 25px;
  152. .page-title {
  153. font-size: 16px;
  154. font-weight: bold;
  155. color: #333;
  156. }
  157. }
  158. .margin-bottom {
  159. margin-bottom: 20px;
  160. }
  161. </style>