Преглед изворни кода

feat: 前端收款记录 Tab — F2fTradeRecord 组件 + API

alphaH пре 2 недеља
родитељ
комит
4155d0f228

+ 44 - 0
frontend/src/api/module_payment/facetoface.ts

@@ -107,6 +107,50 @@ const facetofaceApi = {
       method: "post",
     });
   },
+
+  /** 收款记录列表 */
+  tradeList: (pageNo: number = 1, pageSize: number = 20, search: Record<string, any> = {}) => {
+    return request({
+      url: "/payment/facetoface/trade/list",
+      method: "get",
+      params: {
+        page_no: pageNo,
+        page_size: pageSize,
+        ...search,
+      },
+    });
+  },
+
+  /** 收款记录详情 */
+  tradeDetail: (id: number) => {
+    return request({
+      url: `/payment/facetoface/trade/${id}`,
+      method: "get",
+    });
+  },
+};
+
+// 交易状态标签
+export const TRADE_STATUS_TAG_TYPE: Record<string, string> = {
+  WAIT_BUYER_PAY: "warning",
+  TRADE_SUCCESS: "success",
+  TRADE_CLOSED: "danger",
+  TRADE_FINISHED: "success",
 };
 
+export const TRADE_STATUS_LABEL: Record<string, string> = {
+  WAIT_BUYER_PAY: "等待付款",
+  TRADE_SUCCESS: "支付成功",
+  TRADE_CLOSED: "交易关闭",
+  TRADE_FINISHED: "交易完成",
+};
+
+export const TRADE_STATUS_OPTIONS = [
+  { label: "全部", value: "" },
+  { label: "等待付款", value: "WAIT_BUYER_PAY" },
+  { label: "支付成功", value: "TRADE_SUCCESS" },
+  { label: "交易关闭", value: "TRADE_CLOSED" },
+  { label: "交易完成", value: "TRADE_FINISHED" },
+];
+
 export default facetofaceApi;

+ 156 - 0
frontend/src/views/module_payment/account/components/F2fTradeRecord.vue

@@ -0,0 +1,156 @@
+<template>
+  <div class="tab-content">
+    <el-card>
+      <template #header>
+        <div class="card-header">
+          <span>收款记录列表</span>
+        </div>
+      </template>
+      <div class="mb-4">
+        <el-form :inline="true" :model="searchForm">
+          <el-form-item label="企业">
+            <el-select v-model="searchForm.enterprise_id" placeholder="选择企业" clearable filterable>
+              <el-option v-for="e in enterpriseStore.getEnterpriseList" :key="e.enterprise_id" :label="e.name" :value="e.enterprise_id" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="交易状态">
+            <el-select v-model="searchForm.trade_status" placeholder="全部" clearable>
+              <el-option
+                v-for="opt in TRADE_STATUS_OPTIONS"
+                :key="opt.value"
+                :label="opt.label"
+                :value="opt.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="时间范围">
+            <el-date-picker
+              v-model="searchForm.dateRange"
+              type="daterange"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              value-format="YYYY-MM-DD"
+              @change="handleDateChange"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="handleSearch">查询</el-button>
+            <el-button @click="handleSearchReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <el-table :data="list" border stripe v-loading="loading">
+        <template #empty>
+          <el-empty description="暂无数据" />
+        </template>
+        <el-table-column prop="outTradeNo" label="商户订单号" min-width="200" />
+        <el-table-column prop="tradeNo" label="支付宝交易号" min-width="200">
+          <template #default="{ row }">
+            {{ row.tradeNo || '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="totalAmount" label="收款金额" min-width="120">
+          <template #default="{ row }">¥{{ row.totalAmount }}</template>
+        </el-table-column>
+        <el-table-column prop="subject" label="收款标题" min-width="150" />
+        <el-table-column prop="tradeStatus" label="交易状态" min-width="100">
+          <template #default="{ row }">
+            <el-tag :type="TRADE_STATUS_TAG_TYPE[row.tradeStatus] || 'info'">
+              {{ TRADE_STATUS_LABEL[row.tradeStatus] || row.tradeStatus }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="buyerLogonId" label="付款方" min-width="180">
+          <template #default="{ row }">
+            {{ row.buyerLogonId || '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="gmtPayment" label="付款时间" min-width="160">
+          <template #default="{ row }">
+            {{ row.gmtPayment || '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdTime" label="创建时间" min-width="160" />
+      </el-table>
+      <div class="mt-4 flex justify-end">
+        <el-pagination
+          v-model:current-page="page.page_no"
+          v-model:page-size="page.page_size"
+          :total="page.total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="fetchList"
+          @current-change="fetchList"
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import facetofaceApi, {
+  TRADE_STATUS_TAG_TYPE,
+  TRADE_STATUS_LABEL,
+  TRADE_STATUS_OPTIONS,
+} from "@/api/module_payment/facetoface";
+import { useEnterpriseStore } from "@/store";
+import { ref, reactive, onMounted } from "vue";
+
+const enterpriseStore = useEnterpriseStore();
+
+const loading = ref(false);
+const list = ref<any[]>([]);
+const page = reactive({ page_no: 1, page_size: 10, total: 0 });
+
+const searchForm = reactive({
+  enterprise_id: undefined as string | undefined,
+  trade_status: undefined as string | undefined,
+  start_date: undefined as string | undefined,
+  end_date: undefined as string | undefined,
+  dateRange: null as Date[] | null,
+});
+
+function handleDateChange() {
+  if (searchForm.dateRange && searchForm.dateRange.length === 2) {
+    searchForm.start_date = (searchForm.dateRange as any)[0];
+    searchForm.end_date = (searchForm.dateRange as any)[1];
+  } else {
+    searchForm.start_date = undefined;
+    searchForm.end_date = undefined;
+  }
+}
+
+async function fetchList() {
+  loading.value = true;
+  try {
+    const res = await facetofaceApi.tradeList(page.page_no, page.page_size, {
+      enterprise_id: searchForm.enterprise_id || undefined,
+      trade_status: searchForm.trade_status || undefined,
+      start_date: searchForm.start_date || undefined,
+      end_date: searchForm.end_date || undefined,
+    });
+    list.value = res.data.data?.list || [];
+    page.total = res.data.data.total || 0;
+  } finally {
+    loading.value = false;
+  }
+}
+
+function handleSearch() { page.page_no = 1; fetchList(); }
+function handleSearchReset() {
+  searchForm.enterprise_id = undefined;
+  searchForm.trade_status = undefined;
+  searchForm.start_date = undefined;
+  searchForm.end_date = undefined;
+  searchForm.dateRange = null;
+  handleSearch();
+}
+
+onMounted(async () => {
+  await enterpriseStore.loadEnterpriseList();
+  searchForm.enterprise_id = enterpriseStore.getCurrentEnterprise?.enterprise_id;
+  fetchList();
+});
+</script>

+ 5 - 0
frontend/src/views/module_payment/account/index.vue

@@ -449,6 +449,10 @@
         </div>
       </el-tab-pane>
 
+      <el-tab-pane label="收款记录" name="f2f-trade">
+        <F2fTradeRecord v-if="activeTab === 'f2f-trade'" />
+      </el-tab-pane>
+
       <!-- <el-tab-pane label="账单查询" name="consume">
         <div class="tab-content">
           <el-card>
@@ -703,6 +707,7 @@ import AccountAPI from "@/api/module_payment/account";
 import AccountOverview from "./components/AccountOverview.vue";
 import TransferDetail from "./components/TransferDetail.vue";
 import ConsumeDetail from "./components/ConsumeDetail.vue";
+import F2fTradeRecord from "./components/F2fTradeRecord.vue";
 import TenantAPI, { TenantTable } from "@/api/module_system/tenant";
 import { ref, reactive, computed, onMounted, watch } from "vue";
 import { Refresh, Loading } from "@element-plus/icons-vue";