index.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <div class="layout-padding">
  3. <div class="layout-padding-auto layout-padding-view">
  4. <el-row class="ml10" v-show="showSearch">
  5. <el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
  6. <el-form-item label="商户订单号" prop="mchOrderNo">
  7. <el-input placeholder="请输入商户订单号" style="max-width: 180px" v-model="state.queryForm.mchOrderNo" clearable />
  8. </el-form-item>
  9. <el-form-item label="平台订单号" prop="transactionId">
  10. <el-input placeholder="请输入平台订单号" style="max-width: 180px" v-model="state.queryForm.transactionId" clearable />
  11. </el-form-item>
  12. <el-form-item label="商户名称" prop="merchantName">
  13. <el-input placeholder="请输入商户名称" style="max-width: 180px" v-model="state.queryForm.merchantName" clearable />
  14. </el-form-item>
  15. <el-form-item label="订单状态" prop="orderStatus">
  16. <el-select v-model="state.queryForm.orderStatus" placeholder="请选择订单状态" style="max-width: 180px" clearable>
  17. <el-option label="创建订单" value="CREATE_ORDER" />
  18. <el-option label="支付成功" value="PAY_SUCCESS" />
  19. <el-option label="支付失败" value="PAY_FAIL" />
  20. <el-option label="取消订单" value="CANCEL_ORDER" />
  21. <el-option label="支付超时" value="PAY_TIMEOUT" />
  22. </el-select>
  23. </el-form-item>
  24. <el-form-item>
  25. <el-button @click="getDataList" icon="search" type="primary">查询</el-button>
  26. <el-button @click="resetQuery" icon="Refresh">重置</el-button>
  27. </el-form-item>
  28. </el-form>
  29. </el-row>
  30. <el-row>
  31. <div class="mb8" style="width: 100%">
  32. <right-toolbar
  33. @queryTable="getDataList"
  34. class="ml10"
  35. style="float: right; margin-right: 20px"
  36. v-model:showSearch="showSearch"
  37. ></right-toolbar>
  38. </div>
  39. </el-row>
  40. <!-- 统计信息卡片 -->
  41. <el-row :gutter="20" class="mb20" v-if="statistics">
  42. <el-col :span="6">
  43. <el-card shadow="hover">
  44. <div class="statistic-item">
  45. <div class="statistic-label">提交订单数</div>
  46. <div class="statistic-value">{{ statistics.numberOrders || 0 }}</div>
  47. </div>
  48. </el-card>
  49. </el-col>
  50. <el-col :span="6">
  51. <el-card shadow="hover">
  52. <div class="statistic-item">
  53. <div class="statistic-label">订单总金额</div>
  54. <div class="statistic-value">¥{{ (statistics.totalOrderAmount || 0).toFixed(2) }}</div>
  55. </div>
  56. </el-card>
  57. </el-col>
  58. <el-col :span="6">
  59. <el-card shadow="hover">
  60. <div class="statistic-item">
  61. <div class="statistic-label">已付订单数</div>
  62. <div class="statistic-value success">{{ statistics.paidOrders || 0 }}</div>
  63. </div>
  64. </el-card>
  65. </el-col>
  66. <el-col :span="6">
  67. <el-card shadow="hover">
  68. <div class="statistic-item">
  69. <div class="statistic-label">已付总金额</div>
  70. <div class="statistic-value success">¥{{ (statistics.totalAmountPaid || 0).toFixed(2) }}</div>
  71. </div>
  72. </el-card>
  73. </el-col>
  74. </el-row>
  75. <el-table
  76. :data="state.dataList"
  77. @selection-change="handleSelectionChange"
  78. @sort-change="sortChangeHandle"
  79. style="width: 100%"
  80. v-loading="state.loading"
  81. border
  82. :cell-style="tableStyle.cellStyle"
  83. :header-cell-style="tableStyle.headerCellStyle"
  84. >
  85. <el-table-column align="center" type="selection" width="40" />
  86. <el-table-column label="商户订单号" prop="mchOrderNo" show-overflow-tooltip>
  87. <template #default="scope">
  88. {{ scope.row.mchOrderNo || '--' }}
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="平台订单号" prop="transactionId" show-overflow-tooltip>
  92. <template #default="scope">
  93. {{ scope.row.transactionId || '--' }}
  94. </template>
  95. </el-table-column>
  96. <el-table-column label="商户名称" prop="merchantName" show-overflow-tooltip>
  97. <template #default="scope">
  98. {{ scope.row.merchantName || '--' }}
  99. </template>
  100. </el-table-column>
  101. <el-table-column label="通道名称" prop="paymentChannelName" show-overflow-tooltip>
  102. <template #default="scope">
  103. {{ scope.row.paymentChannelName || '--' }}
  104. </template>
  105. </el-table-column>
  106. <el-table-column label="提交金额" prop="amount" show-overflow-tooltip>
  107. <template #default="scope">
  108. <!-- 橙色 -->
  109. <span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.amount ? scope.row.amount.toFixed(2) : '0.00' }}</span>
  110. </template>
  111. </el-table-column>
  112. <el-table-column label="实际金额" prop="noticeAmount" show-overflow-tooltip>
  113. <template #default="scope">
  114. <span style="color: #f56c6c; font-weight: bold">¥{{ scope.row.noticeAmount ? scope.row.noticeAmount.toFixed(2) : '0.00' }}</span>
  115. </template>
  116. </el-table-column>
  117. <el-table-column label="订单状态" prop="orderStatus" show-overflow-tooltip>
  118. <template #default="scope">
  119. <el-tag :type="orderStatusMap[scope.row.orderStatus]?.type || 'info'" size="small">
  120. {{ orderStatusMap[scope.row.orderStatus]?.label || scope.row.orderStatus }}
  121. </el-tag>
  122. </template>
  123. </el-table-column>
  124. <el-table-column label="创建时间" prop="createTime" show-overflow-tooltip width="180">
  125. <template #default="scope">
  126. {{ scope.row.createTime || '--' }}
  127. </template>
  128. </el-table-column>
  129. <el-table-column label="操作">
  130. <template #default="scope">
  131. <!-- <el-button icon="View" @click="handleView(scope.row)" text type="primary" size="small">查看</el-button> -->
  132. <el-button icon="Document" @click="handleNotifyLog(scope.row)" text type="warning" size="small">回调日志</el-button>
  133. </template>
  134. </el-table-column>
  135. </el-table>
  136. <pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" />
  137. </div>
  138. <!-- 回调日志弹窗 -->
  139. <notify-log-dialog ref="notifyLogDialogRef" />
  140. </div>
  141. </template>
  142. <script lang="ts" name="orderPayOrder" setup>
  143. import { BasicTableProps, useTable } from '/@/hooks/table';
  144. import { fetchPayOrderList, fetchPayOrderStatistics } from '/@/api/order';
  145. import { useMessage } from '/@/hooks/message';
  146. // 引入组件
  147. const NotifyLogDialog = defineAsyncComponent(() => import('./notifyLog.vue'));
  148. // 订单状态映射
  149. const orderStatusMap: Record<string, { label: string; type: any }> = {
  150. CREATE_ORDER: { label: '创建订单', type: 'info' },
  151. PAY_SUCCESS: { label: '支付成功', type: 'success' },
  152. PAY_FAIL: { label: '支付失败', type: 'danger' },
  153. CANCEL_ORDER: { label: '取消订单', type: 'warning' },
  154. PAY_TIMEOUT: { label: '支付超时', type: 'info' },
  155. };
  156. // 定义变量内容
  157. const notifyLogDialogRef = ref();
  158. const queryRef = ref();
  159. const showSearch = ref(true);
  160. const selectObjs = ref([]);
  161. const multiple = ref(true);
  162. const statistics = ref<any>(null);
  163. // 定义表格查询、变更
  164. const state: BasicTableProps = reactive<BasicTableProps>({
  165. queryForm: {
  166. mchOrderNo: '',
  167. transactionId: '',
  168. merchantName: '',
  169. agentName: '',
  170. orderStatus: '',
  171. },
  172. pageList: fetchPayOrderList,
  173. descs: ['create_time'],
  174. createdIsNeed: false, // 禁用自动加载,由 getDataListWithStats 手动调用
  175. });
  176. const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, tableStyle } = useTable(state);
  177. // 加载统计数据
  178. const loadStatistics = async () => {
  179. try {
  180. const res = await fetchPayOrderStatistics(state.queryForm);
  181. statistics.value = res.data;
  182. } catch (err: any) {
  183. useMessage().error(err.msg);
  184. }
  185. };
  186. // 重写 getDataList,同时加载统计数据
  187. const originalGetDataList = getDataList;
  188. const getDataListWithStats = async (reload = true) => {
  189. await originalGetDataList(reload);
  190. await loadStatistics();
  191. };
  192. // 重置查询
  193. const resetQuery = () => {
  194. queryRef.value?.resetFields();
  195. getDataListWithStats();
  196. };
  197. // 多选事件
  198. const handleSelectionChange = (objs: any) => {
  199. selectObjs.value = objs.map((val: any) => val.id);
  200. multiple.value = !objs.length;
  201. };
  202. // 查看回调日志
  203. const handleNotifyLog = (row: any) => {
  204. notifyLogDialogRef.value.openDialog(row.appId, row.mchOrderNo);
  205. };
  206. // 初始化加载数据
  207. onMounted(() => {
  208. getDataListWithStats();
  209. });
  210. </script>
  211. <style scoped>
  212. .statistic-item {
  213. text-align: center;
  214. padding: 10px 0;
  215. }
  216. .statistic-label {
  217. font-size: 14px;
  218. color: #909399;
  219. margin-bottom: 8px;
  220. }
  221. .statistic-value {
  222. font-size: 24px;
  223. font-weight: bold;
  224. color: #303133;
  225. }
  226. .statistic-value.success {
  227. color: #67c23a;
  228. }
  229. </style>