Gqingci пре 23 часа
родитељ
комит
82cceb0490

+ 40 - 0
src/api/system/withdraw/index.ts

@@ -0,0 +1,40 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { WithdrawQuery, WithdrawVO } from './types';
+
+/**
+ * 查询余额提现列表
+ */
+export function listWithdraw(query: WithdrawQuery): AxiosPromise<WithdrawVO[]> {
+  return request({
+    url: '/system/withdraw/list',
+    method: 'get',
+    params: query
+  });
+}
+
+/**
+ * 审核通过
+ */
+export function auditPassWithdraw(id: string | number, remark?: string) {
+  return request({
+    url: '/system/withdraw/audit/pass/' + id,
+    method: 'post',
+    params: {
+      remark: remark || ''
+    }
+  });
+}
+
+/**
+ * 审核驳回
+ */
+export function auditRejectWithdraw(id: string | number, remark: string) {
+  return request({
+    url: '/system/withdraw/audit/reject/' + id,
+    method: 'post',
+    params: {
+      remark
+    }
+  });
+}

+ 44 - 0
src/api/system/withdraw/types.ts

@@ -0,0 +1,44 @@
+export interface WithdrawAccountVO {
+  id: string | number;
+  companyId?: string | number;
+  accountType?: number;
+  accountName?: string;
+  accountNumber?: string;
+  bankName?: string;
+  bankBranch?: string;
+  isDefault?: number;
+  status?: number;
+  auditorId?: string | number;
+  auditTime?: string;
+  auditRemark?: string;
+  createTime?: string;
+}
+
+export interface WithdrawVO extends BaseEntity {
+  id: string | number;
+  withdrawNo: string;
+  companyId: string | number;
+  companyName?: string;
+  accountId: string | number;
+  withdrawAmount: number;
+  withdrawStatus: number;
+  tradeNo?: string;
+  auditorId?: string | number;
+  auditTime?: string;
+  auditRemark?: string;
+  failReason?: string;
+  createTime?: string;
+  transferTime?: string;
+  account?: WithdrawAccountVO;
+}
+
+export interface WithdrawQuery extends PageQuery {
+  withdrawNo?: string;
+  companyId?: string | number;
+  accountId?: string | number;
+  withdrawStatus?: string | number;
+  params?: {
+    beginTime?: string;
+    endTime?: string;
+  };
+}

+ 13 - 0
src/router/index.ts

@@ -254,6 +254,19 @@ export const constantRoutes: RouteRecordRaw[] = [
       }
     ]
   },
+  {
+    path: '/main',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'balanceReview',
+        component: () => import('@/views/main/balanceReview.vue'),
+        name: 'BalanceReview',
+        meta: { title: '余额审核', activeMenu: '/main/balanceReview' }
+      }
+    ]
+  },
 
   {
     path: '/system/audit-hidden',

+ 255 - 0
src/views/balanceReview.vue

@@ -0,0 +1,255 @@
+<template>
+  <div class="app-container">
+    <el-card shadow="never">
+      <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="90px">
+        <el-form-item label="提现单号" prop="withdrawNo">
+          <el-input
+            v-model="queryParams.withdrawNo"
+            placeholder="请输入提现单号"
+            clearable
+            style="width: 220px"
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="审核状态" prop="withdrawStatus">
+          <el-select v-model="queryParams.withdrawStatus" placeholder="请选择状态" clearable style="width: 180px">
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="申请时间">
+          <el-date-picker
+            v-model="dateRange"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="YYYY-MM-DD"
+            style="width: 260px"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <el-table v-loading="loading" :data="withdrawList">
+        <el-table-column label="提现单号" prop="withdrawNo" min-width="180" show-overflow-tooltip />
+        <el-table-column label="企业ID" prop="companyId" width="120" />
+        <el-table-column label="企业名称" prop="companyName" min-width="160" show-overflow-tooltip />
+        <el-table-column label="提现金额" prop="withdrawAmount" width="120">
+          <template #default="scope">
+            <span>¥ {{ Number(scope.row.withdrawAmount || 0).toFixed(2) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="账户类型" min-width="120">
+          <template #default="scope">
+            <span>{{ getAccountTypeLabel(scope.row.account?.accountType) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="收款账户" min-width="180" show-overflow-tooltip>
+          <template #default="scope">
+            <span>{{ scope.row.account?.accountNumber || '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="账户名称" min-width="140" show-overflow-tooltip>
+          <template #default="scope">
+            <span>{{ scope.row.account?.accountName || '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核状态" width="110">
+          <template #default="scope">
+            <el-tag :type="getStatusTagType(scope.row.withdrawStatus)">
+              {{ getStatusLabel(scope.row.withdrawStatus) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核备注" prop="auditRemark" min-width="180" show-overflow-tooltip />
+        <el-table-column label="失败原因" prop="failReason" min-width="180" show-overflow-tooltip />
+        <el-table-column label="申请时间" prop="createTime" width="170" />
+        <el-table-column label="审核时间" prop="auditTime" width="170" />
+        <el-table-column label="打款时间" prop="transferTime" width="170" />
+        <el-table-column label="操作" align="center" width="180" fixed="right">
+          <template #default="scope">
+            <el-button
+              v-if="scope.row.withdrawStatus === 0"
+              link
+              type="success"
+              @click="openAuditDialog(scope.row, 'pass')"
+            >
+              通过
+            </el-button>
+            <el-button
+              v-if="scope.row.withdrawStatus === 0"
+              link
+              type="danger"
+              @click="openAuditDialog(scope.row, 'reject')"
+            >
+              驳回
+            </el-button>
+            <span v-else>-</span>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <el-dialog v-model="auditDialog.visible" :title="auditDialog.mode === 'pass' ? '通过审核' : '驳回审核'" width="520px">
+      <el-form label-width="80px">
+        <el-form-item label="提现单号">
+          <span>{{ auditDialog.row?.withdrawNo }}</span>
+        </el-form-item>
+        <el-form-item label="提现金额">
+          <span>¥ {{ Number(auditDialog.row?.withdrawAmount || 0).toFixed(2) }}</span>
+        </el-form-item>
+        <el-form-item :label="auditDialog.mode === 'pass' ? '备注' : '驳回原因'" required>
+          <el-input
+            v-model="auditDialog.remark"
+            type="textarea"
+            :rows="4"
+            :placeholder="auditDialog.mode === 'pass' ? '请输入审核备注,选填' : '请输入驳回原因'"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="auditDialog.visible = false">取消</el-button>
+          <el-button type="primary" @click="submitAudit">确定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from 'vue';
+import { ElMessage } from 'element-plus';
+import { listWithdraw, auditPassWithdraw, auditRejectWithdraw } from '@/api/system/withdraw';
+import type { WithdrawQuery, WithdrawVO } from '@/api/system/withdraw/types';
+
+const loading = ref(false);
+const total = ref(0);
+const withdrawList = ref<WithdrawVO[]>([]);
+const queryRef = ref();
+const dateRange = ref<string[]>([]);
+
+const queryParams = reactive<WithdrawQuery>({
+  pageNum: 1,
+  pageSize: 10,
+  withdrawNo: undefined,
+  withdrawStatus: undefined,
+  params: {}
+});
+
+const statusOptions = [
+  { label: '待审核', value: 0 },
+  { label: '审核通过', value: 1 },
+  { label: '打款中', value: 2 },
+  { label: '已完成', value: 3 },
+  { label: '失败', value: 4 },
+  { label: '已拒绝', value: 5 }
+];
+
+const auditDialog = reactive<{
+  visible: boolean;
+  mode: 'pass' | 'reject';
+  row: WithdrawVO | null;
+  remark: string;
+}>({
+  visible: false,
+  mode: 'pass',
+  row: null,
+  remark: ''
+});
+
+const getList = async () => {
+  loading.value = true;
+  try {
+    queryParams.params = {
+      beginTime: dateRange.value?.[0],
+      endTime: dateRange.value?.[1]
+    };
+    const res = await listWithdraw(queryParams);
+    withdrawList.value = res.rows || [];
+    total.value = res.total || 0;
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleQuery = () => {
+  queryParams.pageNum = 1;
+  getList();
+};
+
+const resetQuery = () => {
+  queryRef.value?.resetFields();
+  dateRange.value = [];
+  queryParams.params = {};
+  handleQuery();
+};
+
+const openAuditDialog = (row: WithdrawVO, mode: 'pass' | 'reject') => {
+  auditDialog.visible = true;
+  auditDialog.mode = mode;
+  auditDialog.row = row;
+  auditDialog.remark = '';
+};
+
+const submitAudit = async () => {
+  if (!auditDialog.row) {
+    return;
+  }
+  if (auditDialog.mode === 'reject' && !auditDialog.remark.trim()) {
+    ElMessage.warning('请输入驳回原因');
+    return;
+  }
+
+  if (auditDialog.mode === 'pass') {
+    await auditPassWithdraw(auditDialog.row.id, auditDialog.remark);
+    ElMessage.success('审核通过成功');
+  } else {
+    await auditRejectWithdraw(auditDialog.row.id, auditDialog.remark);
+    ElMessage.success('驳回成功');
+  }
+
+  auditDialog.visible = false;
+  await getList();
+};
+
+const getStatusLabel = (status?: number) => {
+  return statusOptions.find((item) => item.value === status)?.label || '未知';
+};
+
+const getStatusTagType = (status?: number) => {
+  const map: Record<number, string> = {
+    0: 'warning',
+    1: 'primary',
+    2: 'info',
+    3: 'success',
+    4: 'danger',
+    5: 'danger'
+  };
+  return map[status || 0] || 'info';
+};
+
+const getAccountTypeLabel = (type?: number) => {
+  if (type === 2) return '微信';
+  if (type === 1) return '支付宝';
+  return '-';
+};
+
+getList();
+</script>

+ 7 - 0
src/views/main/balanceReview.vue

@@ -0,0 +1,7 @@
+<template>
+  <BalanceReview />
+</template>
+
+<script setup lang="ts">
+import BalanceReview from '../balanceReview.vue';
+</script>

+ 7 - 0
src/views/main/balanceReview/index.vue

@@ -0,0 +1,7 @@
+<template>
+  <BalanceReview />
+</template>
+
+<script setup lang="ts">
+import BalanceReview from '../../balanceReview.vue';
+</script>