备份:PWA配置前的完整版本
包含所有最新开发的功能和修复,作为PWA正确配置前的备份点。
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
} from '@ant-design/icons'
|
||||
import type { ColumnsType } from 'antd/es/table'
|
||||
import dayjs from 'dayjs'
|
||||
import { useLanguageStore } from '../store/languageStore'
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
interface PaymentPlan {
|
||||
@@ -37,6 +38,7 @@ interface PurchaseOrder {
|
||||
|
||||
// ==================== 组件 ====================
|
||||
const PaymentPlansPage: React.FC = () => {
|
||||
const { t, currentLanguage } = useLanguageStore();
|
||||
// 状态
|
||||
const [paymentPlans, setPaymentPlans] = useState<PaymentPlan[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -63,11 +65,11 @@ const PaymentPlansPage: React.FC = () => {
|
||||
if (data.success) {
|
||||
setPaymentPlans(data.data)
|
||||
} else {
|
||||
message.error('获取付款计划列表失败')
|
||||
message.error(t('paymentPlan.getListFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取付款计划列表失败:', error)
|
||||
message.error('获取付款计划列表失败')
|
||||
message.error(t('paymentPlan.getListFailed'))
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -93,11 +95,11 @@ const PaymentPlansPage: React.FC = () => {
|
||||
setViewingPlan(data.data)
|
||||
setDetailModalVisible(true)
|
||||
} else {
|
||||
message.error('获取付款计划详情失败')
|
||||
message.error(t('paymentPlan.getDetailFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取付款计划详情失败:', error)
|
||||
message.error('获取付款计划详情失败')
|
||||
message.error(t('paymentPlan.getDetailFailed'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +121,7 @@ const PaymentPlansPage: React.FC = () => {
|
||||
currency: 'CNY',
|
||||
payment_type: 'partial',
|
||||
status: 'pending',
|
||||
created_by: '系统管理员'
|
||||
created_by: t('common.systemAdmin')
|
||||
})
|
||||
setModalVisible(true)
|
||||
}
|
||||
@@ -150,15 +152,15 @@ const PaymentPlansPage: React.FC = () => {
|
||||
payment_type: fullRecord.payment_type || 'partial',
|
||||
status: fullRecord.status || 'pending',
|
||||
description: fullRecord.description,
|
||||
created_by: fullRecord.created_by || '系统管理员'
|
||||
created_by: fullRecord.created_by || t('common.systemAdmin')
|
||||
});
|
||||
}, 100);
|
||||
} else {
|
||||
message.error('获取付款计划详情失败')
|
||||
message.error(t('paymentPlan.getDetailFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取付款计划详情失败:', error)
|
||||
message.error('获取付款计划详情失败')
|
||||
message.error(t('paymentPlan.getDetailFailed'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,15 +193,15 @@ const PaymentPlansPage: React.FC = () => {
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success) {
|
||||
message.success(editingPlan ? '保存成功' : '创建成功')
|
||||
message.success(editingPlan ? t('common.saveSuccess') : t('common.createSuccess'))
|
||||
setModalVisible(false)
|
||||
fetchPaymentPlans()
|
||||
} else {
|
||||
message.error(editingPlan ? '保存失败' : '创建失败')
|
||||
message.error(editingPlan ? t('common.saveFailed') : t('common.operationFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存失败:', error)
|
||||
message.error('保存失败')
|
||||
message.error(t('common.saveFailed'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,10 +209,10 @@ const PaymentPlansPage: React.FC = () => {
|
||||
|
||||
const getStatusTag = (status: string) => {
|
||||
const statusMap: Record<string, { color: string; text: string }> = {
|
||||
pending: { color: 'blue', text: '待处理' },
|
||||
approved: { color: 'green', text: '已审批' },
|
||||
executed: { color: 'purple', text: '已执行' },
|
||||
cancelled: { color: 'red', text: '已取消' }
|
||||
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 <Tag color={info.color}>{info.text}</Tag>
|
||||
@@ -218,8 +220,8 @@ const PaymentPlansPage: React.FC = () => {
|
||||
|
||||
const getPaymentTypeTag = (type: string) => {
|
||||
const typeMap: Record<string, { color: string; text: string }> = {
|
||||
partial: { color: 'blue', text: '部分付款' },
|
||||
full: { color: 'green', text: '全额付款' }
|
||||
partial: { color: 'blue', text: t('paymentPlan.partialPayment') },
|
||||
full: { color: 'green', text: t('paymentPlan.fullPayment') }
|
||||
}
|
||||
const info = typeMap[type] || { color: 'default', text: type }
|
||||
return <Tag color={info.color}>{info.text}</Tag>
|
||||
@@ -227,14 +229,14 @@ const PaymentPlansPage: React.FC = () => {
|
||||
|
||||
const columns: ColumnsType<PaymentPlan> = [
|
||||
{
|
||||
title: '计划编号',
|
||||
title: t('paymentPlan.planCode'),
|
||||
dataIndex: 'code',
|
||||
key: 'code',
|
||||
width: 150,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '采购订单',
|
||||
title: t('paymentPlan.purchaseOrder'),
|
||||
dataIndex: 'purchase_order_id',
|
||||
key: 'purchase_order_id',
|
||||
width: 140,
|
||||
@@ -244,14 +246,14 @@ const PaymentPlansPage: React.FC = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '付款日期',
|
||||
title: t('paymentPlan.paymentDate'),
|
||||
dataIndex: 'payment_date',
|
||||
key: 'payment_date',
|
||||
width: 110,
|
||||
render: (date) => dayjs(date).format('MM-DD')
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
title: t('paymentPlan.amount'),
|
||||
dataIndex: 'amount',
|
||||
key: 'amount',
|
||||
width: 120,
|
||||
@@ -263,7 +265,7 @@ const PaymentPlansPage: React.FC = () => {
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '付款类型',
|
||||
title: t('paymentPlan.paymentType'),
|
||||
dataIndex: 'payment_type',
|
||||
key: 'payment_type',
|
||||
width: 100,
|
||||
@@ -271,7 +273,7 @@ const PaymentPlansPage: React.FC = () => {
|
||||
render: getPaymentTypeTag
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
title: t('paymentPlan.status'),
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 90,
|
||||
@@ -279,13 +281,13 @@ const PaymentPlansPage: React.FC = () => {
|
||||
render: getStatusTag
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
title: t('paymentPlan.creator'),
|
||||
dataIndex: 'created_by',
|
||||
key: 'created_by',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: t('paymentPlan.action'),
|
||||
key: 'actions',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
@@ -297,7 +299,7 @@ const PaymentPlansPage: React.FC = () => {
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => fetchPlanDetail(record.id)}
|
||||
>
|
||||
详情
|
||||
{t('common.detail')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
@@ -305,7 +307,7 @@ const PaymentPlansPage: React.FC = () => {
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleEdit(record)}
|
||||
>
|
||||
编辑
|
||||
{t('common.edit')}
|
||||
</Button>
|
||||
</Space>
|
||||
)
|
||||
@@ -315,11 +317,11 @@ const PaymentPlansPage: React.FC = () => {
|
||||
return (
|
||||
<div style={{ padding: 24 }}>
|
||||
<div style={{ marginBottom: 24 }}>
|
||||
<h2 style={{ marginBottom: 8 }}>付款计划</h2>
|
||||
<p style={{ color: '#888', marginBottom: 0 }}>管理采购订单的付款计划</p>
|
||||
<h2 style={{ marginBottom: 8 }}>{t('paymentPlan.title')}</h2>
|
||||
<p style={{ color: '#888', marginBottom: 0 }}>{t('paymentPlan.description')}</p>
|
||||
</div>
|
||||
|
||||
<Card extra={<Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}>新建付款计划</Button>}>
|
||||
<Card extra={<Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}>{t('paymentPlan.newPlan')}</Button>}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={paymentPlans}
|
||||
@@ -333,19 +335,22 @@ const PaymentPlansPage: React.FC = () => {
|
||||
|
||||
{/* 编辑/新建弹窗 */}
|
||||
<Modal
|
||||
title={editingPlan ? '编辑付款计划' : '新建付款计划'}
|
||||
title={editingPlan ? t('paymentPlan.editPlan') : t('paymentPlan.newPlan')}
|
||||
open={modalVisible}
|
||||
onCancel={() => {
|
||||
setModalVisible(false)
|
||||
setEditingPlan(null)
|
||||
form.resetFields();
|
||||
setModalVisible(false);
|
||||
setEditingPlan(null);
|
||||
}}
|
||||
footer={[
|
||||
<Button key="cancel" onClick={() => {
|
||||
setModalVisible(false)
|
||||
setEditingPlan(null)
|
||||
}}>取消</Button>,
|
||||
<Button key="save" type="primary" onClick={handleSave}>保存</Button>
|
||||
form.resetFields();
|
||||
setModalVisible(false);
|
||||
setEditingPlan(null);
|
||||
}}>{t('common.cancel')}</Button>,
|
||||
<Button key="save" type="primary" onClick={handleSave}>{t('common.save')}</Button>
|
||||
]}
|
||||
destroyOnClose
|
||||
width={600}
|
||||
>
|
||||
<Form form={form} layout="vertical">
|
||||
@@ -353,10 +358,10 @@ const PaymentPlansPage: React.FC = () => {
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="purchase_order_id"
|
||||
label="关联采购订单"
|
||||
rules={[{ required: true, message: '请选择采购订单' }]}
|
||||
label={t('paymentPlan.purchaseOrder')}
|
||||
rules={[{ required: true, message: t('paymentPlan.selectOrder') }]}
|
||||
>
|
||||
<Select placeholder="请选择采购订单" allowClear>
|
||||
<Select placeholder={t('paymentPlan.selectOrder')} allowClear>
|
||||
{purchaseOrders.map(order => (
|
||||
<Select.Option key={order.id} value={order.id}>
|
||||
{order.code} - {order.supplier_name} ({order.currency} {order.total_amount})
|
||||
@@ -371,8 +376,8 @@ const PaymentPlansPage: React.FC = () => {
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="payment_date"
|
||||
label="付款日期"
|
||||
rules={[{ required: true, message: '请选择付款日期' }]}
|
||||
label={t('paymentPlan.paymentDate')}
|
||||
rules={[{ required: true, message: t('paymentPlan.selectDate') }]}
|
||||
>
|
||||
<DatePicker style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
@@ -380,10 +385,10 @@ const PaymentPlansPage: React.FC = () => {
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="amount"
|
||||
label="付款金额"
|
||||
rules={[{ required: true, message: '请输入付款金额' }]}
|
||||
label={t('paymentPlan.amount')}
|
||||
rules={[{ required: true, message: t('paymentPlan.inputAmount') }]}
|
||||
>
|
||||
<InputNumber min={0} precision={2} style={{ width: '100%' }} placeholder="付款金额" />
|
||||
<InputNumber min={0} precision={2} style={{ width: '100%' }} placeholder={t('paymentPlan.amountPlaceholder')} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -392,26 +397,26 @@ const PaymentPlansPage: React.FC = () => {
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="currency"
|
||||
label="币种"
|
||||
rules={[{ required: true, message: '请选择币种' }]}
|
||||
label={t('common.currency')}
|
||||
rules={[{ required: true, message: t('paymentPlan.selectCurrency') }]}
|
||||
>
|
||||
<Select placeholder="请选择币种">
|
||||
<Select.Option value="CNY">人民币</Select.Option>
|
||||
<Select.Option value="USD">美元</Select.Option>
|
||||
<Select.Option value="LAK">老挝基普</Select.Option>
|
||||
<Select.Option value="THB">泰铢</Select.Option>
|
||||
<Select placeholder={t('paymentPlan.selectCurrency')}>
|
||||
<Select.Option value="CNY">{t('paymentPlan.currencyCNY')}</Select.Option>
|
||||
<Select.Option value="USD">{t('paymentPlan.currencyUSD')}</Select.Option>
|
||||
<Select.Option value="LAK">{t('paymentPlan.currencyLAK')}</Select.Option>
|
||||
<Select.Option value="THB">{t('paymentPlan.currencyTHB')}</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="payment_type"
|
||||
label="付款类型"
|
||||
rules={[{ required: true, message: '请选择付款类型' }]}
|
||||
label={t('paymentPlan.paymentType')}
|
||||
rules={[{ required: true, message: t('paymentPlan.selectType') }]}
|
||||
>
|
||||
<Select placeholder="请选择付款类型">
|
||||
<Select.Option value="partial">部分付款</Select.Option>
|
||||
<Select.Option value="full">全额付款</Select.Option>
|
||||
<Select placeholder={t('paymentPlan.selectType')}>
|
||||
<Select.Option value="partial">{t('paymentPlan.partialPayment')}</Select.Option>
|
||||
<Select.Option value="full">{t('paymentPlan.fullPayment')}</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
@@ -421,40 +426,40 @@ const PaymentPlansPage: React.FC = () => {
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="status"
|
||||
label="状态"
|
||||
rules={[{ required: true, message: '请选择状态' }]}
|
||||
label={t('paymentPlan.status')}
|
||||
rules={[{ required: true, message: t('paymentPlan.selectStatus') }]}
|
||||
>
|
||||
<Select placeholder="请选择状态">
|
||||
<Select.Option value="pending">待处理</Select.Option>
|
||||
<Select.Option value="approved">已审批</Select.Option>
|
||||
<Select.Option value="executed">已执行</Select.Option>
|
||||
<Select.Option value="cancelled">已取消</Select.Option>
|
||||
<Select placeholder={t('paymentPlan.selectStatus')}>
|
||||
<Select.Option value="pending">{t('paymentPlan.pending')}</Select.Option>
|
||||
<Select.Option value="approved">{t('paymentPlan.approved')}</Select.Option>
|
||||
<Select.Option value="executed">{t('paymentPlan.executed')}</Select.Option>
|
||||
<Select.Option value="cancelled">{t('paymentPlan.cancelled')}</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="created_by"
|
||||
label="创建人"
|
||||
rules={[{ required: true, message: '请输入创建人' }]}
|
||||
label={t('paymentPlan.creator')}
|
||||
rules={[{ required: true, message: t('paymentPlan.inputCreator') }]}
|
||||
>
|
||||
<Input placeholder="请输入创建人" />
|
||||
<Input placeholder={t('paymentPlan.inputCreator')} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Form.Item
|
||||
name="description"
|
||||
label="描述"
|
||||
label={t('common.remark')}
|
||||
>
|
||||
<Input.TextArea rows={3} placeholder="请输入付款计划描述" />
|
||||
<Input.TextArea rows={3} placeholder={t('paymentPlan.descPlaceholder')} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
{/* 详情弹窗 */}
|
||||
<Modal
|
||||
title="付款计划详情"
|
||||
title={t('paymentPlan.detailTitle')}
|
||||
open={detailModalVisible}
|
||||
onCancel={() => setDetailModalVisible(false)}
|
||||
footer={null}
|
||||
@@ -463,20 +468,20 @@ const PaymentPlansPage: React.FC = () => {
|
||||
{viewingPlan && (
|
||||
<>
|
||||
<Descriptions bordered column={2} size="small">
|
||||
<Descriptions.Item label="计划编号">{viewingPlan.code}</Descriptions.Item>
|
||||
<Descriptions.Item label="状态">{getStatusTag(viewingPlan.status)}</Descriptions.Item>
|
||||
<Descriptions.Item label="采购订单">
|
||||
<Descriptions.Item label={t('paymentPlan.detailCode')}>{viewingPlan.code}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.status')}>{getStatusTag(viewingPlan.status)}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.purchaseOrder')}>
|
||||
{(() => {
|
||||
const order = purchaseOrders.find(o => o.id == viewingPlan.purchase_order_id)
|
||||
return order ? order.code : viewingPlan.purchase_order_id
|
||||
})()}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="付款类型">{getPaymentTypeTag(viewingPlan.payment_type)}</Descriptions.Item>
|
||||
<Descriptions.Item label="付款日期">{viewingPlan.payment_date}</Descriptions.Item>
|
||||
<Descriptions.Item label="币种">{viewingPlan.currency}</Descriptions.Item>
|
||||
<Descriptions.Item label="金额" span={2}>{viewingPlan.amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</Descriptions.Item>
|
||||
<Descriptions.Item label="描述" span={2}>{viewingPlan.description || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="创建人" span={2}>{viewingPlan.created_by}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.paymentType')}>{getPaymentTypeTag(viewingPlan.payment_type)}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.paymentDate')}>{viewingPlan.payment_date}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('common.currency')}>{viewingPlan.currency}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.amount')} span={2}>{viewingPlan.amount.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('common.remark')} span={2}>{viewingPlan.description || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label={t('paymentPlan.creator')} span={2}>{viewingPlan.created_by}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user