import React, { useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { Table, Button, Modal, Form, Input, Select, message, Space, Tag, Card, Row, Col, DatePicker, InputNumber, Descriptions, Divider } from 'antd' import { PlusOutlined, EditOutlined, EyeOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons' import type { ColumnsType } from 'antd/es/table' import dayjs from 'dayjs' import { useLanguageStore } from '../store/languageStore' // ==================== 类型定义 ==================== interface PaymentPlan { id: number purchase_order_id: number code: string payment_date: string amount: number currency: string payment_type: string status: string description: string created_by: string created_at: string updated_at: string } interface PurchaseOrder { id: number code: string supplier_name: string total_amount: number currency: string } // ==================== 组件 ==================== const PaymentPlansPage: React.FC = () => { const { t, currentLanguage } = useLanguageStore(); // 状态 const [paymentPlans, setPaymentPlans] = useState([]) const [loading, setLoading] = useState(false) const [purchaseOrders, setPurchaseOrders] = useState([]) // 弹窗状态 const [modalVisible, setModalVisible] = useState(false) const [detailModalVisible, setDetailModalVisible] = useState(false) const [editingPlan, setEditingPlan] = useState(null) const [viewingPlan, setViewingPlan] = useState(null) // 表单 const [form] = Form.useForm() const navigate = useNavigate() // ==================== 数据加载 ==================== const fetchPaymentPlans = async () => { setLoading(true) try { const response = await fetch('/api/payment-plans') const data = await response.json() if (data.success) { setPaymentPlans(data.data) } else { message.error(t('paymentPlan.getListFailed')) } } catch (error) { console.error('获取付款计划列表失败:', error) message.error(t('paymentPlan.getListFailed')) } finally { setLoading(false) } } const fetchPurchaseOrders = async () => { try { const response = await fetch('/api/purchase-orders') const data = await response.json() if (data.success) { setPurchaseOrders(data.data) } } catch (error) { console.error('获取采购订单列表失败:', error) } } const fetchPlanDetail = async (id: number) => { try { const response = await fetch(`/api/payment-plans/${id}`) const data = await response.json() if (data.success) { setViewingPlan(data.data) setDetailModalVisible(true) } else { message.error(t('paymentPlan.getDetailFailed')) } } catch (error) { console.error('获取付款计划详情失败:', error) message.error(t('paymentPlan.getDetailFailed')) } } useEffect(() => { fetchPurchaseOrders() }, []) useEffect(() => { fetchPaymentPlans() }, []) // ==================== 操作函数 ==================== const handleCreate = () => { setEditingPlan(null) form.resetFields() form.setFieldsValue({ payment_date: dayjs(), currency: 'CNY', payment_type: 'partial', status: 'pending', created_by: t('common.systemAdmin') }) setModalVisible(true) } const handleEdit = async (record: PaymentPlan) => { try { // 获取完整的付款计划详情 const response = await fetch(`/api/payment-plans/${record.id}`) const data = await response.json() if (data.success && data.data) { const fullRecord = data.data setEditingPlan(fullRecord) // 打开模态框 setModalVisible(true); // 使用 setTimeout 确保模态框已渲染后再设置表单值 setTimeout(() => { form.resetFields(); // 设置表单值 form.setFieldsValue({ purchase_order_id: fullRecord.purchase_order_id, payment_date: fullRecord.payment_date ? dayjs(fullRecord.payment_date) : dayjs(), amount: fullRecord.amount, currency: fullRecord.currency || 'CNY', payment_type: fullRecord.payment_type || 'partial', status: fullRecord.status || 'pending', description: fullRecord.description, created_by: fullRecord.created_by || t('common.systemAdmin') }); }, 100); } else { message.error(t('paymentPlan.getDetailFailed')) } } catch (error) { console.error('获取付款计划详情失败:', error) message.error(t('paymentPlan.getDetailFailed')) } } const handleSave = async () => { try { const values = await form.validateFields() const requestData = { ...values, payment_date: values.payment_date.format('YYYY-MM-DD') } let response if (editingPlan) { // 更新现有付款计划 response = await fetch(`/api/payment-plans/${editingPlan.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }) } else { // 创建新付款计划 response = await fetch('/api/payment-plans', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }) } const data = await response.json() if (data.success) { message.success(editingPlan ? t('common.saveSuccess') : t('common.createSuccess')) setModalVisible(false) fetchPaymentPlans() } else { message.error(editingPlan ? t('common.saveFailed') : t('common.operationFailed')) } } catch (error) { console.error('保存失败:', error) message.error(t('common.saveFailed')) } } // ==================== 渲染 ==================== const getStatusTag = (status: string) => { const statusMap: Record = { pending: { color: 'blue', text: t('paymentPlan.pending') }, approved: { color: 'green', text: t('paymentPlan.approved') }, executed: { color: 'purple', text: t('paymentPlan.executed') }, cancelled: { color: 'red', text: t('paymentPlan.cancelled') } } const info = statusMap[status] || { color: 'default', text: status } return {info.text} } const getPaymentTypeTag = (type: string) => { const typeMap: Record = { partial: { color: 'blue', text: t('paymentPlan.partialPayment') }, full: { color: 'green', text: t('paymentPlan.fullPayment') } } const info = typeMap[type] || { color: 'default', text: type } return {info.text} } const columns: ColumnsType = [ { title: t('paymentPlan.planCode'), dataIndex: 'code', key: 'code', width: 150, ellipsis: true }, { title: t('paymentPlan.purchaseOrder'), dataIndex: 'purchase_order_id', key: 'purchase_order_id', width: 140, render: (id) => { const order = purchaseOrders.find(o => o.id == id) return order ? order.code : id } }, { title: t('paymentPlan.paymentDate'), dataIndex: 'payment_date', key: 'payment_date', width: 110, render: (date) => dayjs(date).format('MM-DD') }, { title: t('paymentPlan.amount'), dataIndex: 'amount', key: 'amount', width: 120, align: 'right', render: (amount, record) => ( {record.currency} {amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ) }, { title: t('paymentPlan.paymentType'), dataIndex: 'payment_type', key: 'payment_type', width: 100, align: 'center', render: getPaymentTypeTag }, { title: t('paymentPlan.status'), dataIndex: 'status', key: 'status', width: 90, align: 'center', render: getStatusTag }, { title: t('paymentPlan.creator'), dataIndex: 'created_by', key: 'created_by', width: 100 }, { title: t('paymentPlan.action'), key: 'actions', width: 150, fixed: 'right', render: (_, record) => ( ) } ] return (

{t('paymentPlan.title')}

{t('paymentPlan.description')}

} onClick={handleCreate}>{t('paymentPlan.newPlan')}}> {/* 编辑/新建弹窗 */} { form.resetFields(); setModalVisible(false); setEditingPlan(null); }} footer={[ , ]} destroyOnClose width={600} >
{/* 详情弹窗 */} setDetailModalVisible(false)} footer={null} width={600} > {viewingPlan && ( <> {viewingPlan.code} {getStatusTag(viewingPlan.status)} {(() => { const order = purchaseOrders.find(o => o.id == viewingPlan.purchase_order_id) return order ? order.code : viewingPlan.purchase_order_id })()} {getPaymentTypeTag(viewingPlan.payment_type)} {viewingPlan.payment_date} {viewingPlan.currency} {viewingPlan.amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} {viewingPlan.description || '-'} {viewingPlan.created_by} )} ) } export default PaymentPlansPage;