| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- 'use client';
- import { useState, useEffect } from 'react';
- import api from '@/lib/api';
- import { RefreshCw, Search, CheckCheck } from 'lucide-react';
- import Pagination from '@/components/common/Pagination';
- import ConfirmationTable from '@/components/admin/payments/ConfirmationTable';
- import ConfirmationDetailModal from '@/components/admin/payments/ConfirmationDetailModal';
- import { PaymentConfirmation } from '@/types/payment';
- export default function PaymentConfirmationsPage() {
- const [list, setList] = useState<PaymentConfirmation[]>([]);
- const [loading, setLoading] = useState(true);
-
- // 分页与搜索
- const [page, setPage] = useState(1);
- const [pageSize] = useState(10);
- const [total, setTotal] = useState(0);
- const [keyword, setKeyword] = useState('');
- // 弹窗状态
- const [selectedItem, setSelectedItem] = useState<PaymentConfirmation | null>(null);
- const [isDetailOpen, setIsDetailOpen] = useState(false);
- useEffect(() => {
- fetchData(1);
- }, []);
- const fetchData = async (targetPage: number) => {
- setLoading(true);
- try {
- const res = await api.post('/api/vas/payment_confirmation/list_all', {}, {
- params: {
- page: targetPage,
- size: pageSize,
- keyword: keyword
- }
- });
- const data = res.data.data;
- if (data && Array.isArray(data.items)) {
- setList(data.items);
- setTotal(data.total || 0);
- } else {
- setList([]);
- setTotal(0);
- }
- setPage(targetPage);
- } catch (error) {
- console.error("Fetch confirmations failed", error);
- setList([]);
- } finally {
- setLoading(false);
- }
- };
- const handleSearch = () => fetchData(1);
- // 打开详情
- const handleViewDetail = (item: PaymentConfirmation) => {
- setSelectedItem(item);
- setIsDetailOpen(true);
- };
- // 确认收款
- const handleApprove = async (item: PaymentConfirmation) => {
- const moneyStr = `${(item.amount / 100).toFixed(2)} ${item.currency}`;
- if (!confirm(`确认已收到支付单 #${item.payment_id} 的款项 (${moneyStr}) 吗?`)) return;
- try {
- // 使用新的确认接口
- await api.post('/api/vas/payment/confirm_by_admin', {
- status: 'confirmed',
- admin_confirmed_at: new Date().toISOString()
- }, {
- params: { id: item.id } // 这里的 id 是 confirmation record id
- });
-
- alert('已确认收款');
- fetchData(page);
- } catch (e: any) {
- alert('操作失败: ' + (e.response?.data?.message || '未知错误'));
- }
- };
- return (
- <div className="p-4 md:p-6">
-
- {/* Header */}
- <div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6">
- <div>
- <h1 className="text-2xl font-bold text-slate-800 flex items-center gap-2">
- <CheckCheck className="text-blue-600" /> 支付确认管理
- </h1>
- <p className="text-sm text-slate-500 mt-1">处理用户提交的“我已付款”确认请求</p>
- </div>
-
- <div className="flex flex-col sm:flex-row gap-3 w-full md:w-auto">
- <div className="relative w-full sm:w-auto md:w-64">
- <input
- type="text"
- placeholder="搜索 Payment ID / User ID"
- className="w-full pl-9 pr-4 py-2 border rounded-lg text-sm focus:ring-2 focus:ring-blue-500 outline-none transition"
- value={keyword}
- onChange={e => setKeyword(e.target.value)}
- onKeyDown={e => e.key === 'Enter' && handleSearch()}
- />
- <Search size={16} className="absolute left-3 top-2.5 text-gray-400" />
- </div>
-
- <button
- onClick={() => fetchData(page)}
- className="flex items-center justify-center gap-2 px-4 py-2 bg-white border border-slate-300 rounded-lg hover:bg-slate-50 text-slate-600 transition w-full sm:w-auto"
- title="刷新"
- >
- <RefreshCw size={18} />
- <span className="md:hidden text-sm font-medium">刷新列表</span>
- </button>
- </div>
- </div>
- {/* Table */}
- <ConfirmationTable
- data={list}
- loading={loading}
- onApprove={handleApprove}
- onViewDetail={handleViewDetail}
- />
- <div className="mt-4">
- <Pagination
- currentPage={page}
- total={total}
- pageSize={pageSize}
- onPageChange={fetchData}
- />
- </div>
- {/* Modal */}
- <ConfirmationDetailModal
- isOpen={isDetailOpen}
- onClose={() => setIsDetailOpen(false)}
- data={selectedItem}
- onApprove={handleApprove}
- />
- </div>
- );
- }
|