Files
yunhaifinance/frontend/src/pages/budget/ContractCreateModal.tsx
T

229 lines
6.5 KiB
TypeScript

import React, { useState, useEffect, useCallback } from 'react';
import { Modal, Form, Input, DatePicker, InputNumber, Select, Space, message } from 'antd';
import dayjs from 'dayjs';
import apiClient from '../../utils/request';
import useFormDraft from '../../hooks/useFormDraft';
interface ContractCreateModalProps {
visible: boolean;
projectId: number;
projectName: string;
onCancel: () => void;
onSuccess: () => void;
}
const ContractCreateModal: React.FC<ContractCreateModalProps> = ({
visible,
projectId,
projectName,
onCancel,
onSuccess
}) => {
const [form] = Form.useForm();
const [contractAmount, setContractAmount] = useState(0);
// 表单草稿保护
const { save: saveDraft, restore: restoreDraft, clear: clearDraft, hasDraft } = useFormDraft({
form,
storageKey: 'contract_create',
})
const handleFormChange = useCallback(() => {
saveDraft()
}, [saveDraft])
// 生成默认的合同编号(包含时间戳确保唯一性)
const today = dayjs();
const dateStr = today.format('YYYYMMDD');
const timeStr = today.format('HHmmss');
const defaultContractCode = `CONTRACT-${dateStr}-${timeStr}`;
useEffect(() => {
if (visible) {
form.setFieldsValue({
contract_code: defaultContractCode,
project_name: projectName,
contract_method: 'lump_sum',
currency: 'CNY',
contract_amount: 0,
contract_period: 180
});
setContractAmount(0);
}
}, [visible, form, projectName]);
// 处理工期变化
const handlePeriodChange = (value: number) => {
// 只需要设置工期天数,不需要计算开始和结束日期
};
// 提交表单
const handleSubmit = async (values: any) => {
// 构建提交数据(简化版)
const submitData = {
contract_code: values.contract_code,
project_name: values.project_name,
contract_method: values.contract_method || 'lump_sum',
currency: values.currency || 'CNY',
contract_amount: values.contract_amount || 0,
contract_period: values.contract_period || 180,
warranty_deposit_percentage: 5, // 默认5%
warranty_period: 12, // 默认12个月
// 其他字段留空,后续在项目管理中补充
project_overview: '',
other_requirements: '',
contract_file: null,
payment_nodes: [],
unit_price_items: []
};
try {
const res = await apiClient.put(`/budget-projects/${projectId}/sign`, submitData, {
headers: {
'x-user-role': 'admin' // 签约操作需要管理员权限
}
});
if (res.data.success) {
message.success('签约成功,项目已自动创建');
clearDraft()
onSuccess();
onCancel();
} else {
message.error(res.data.message || '操作失败');
}
} catch (error: any) {
console.error('签约失败:', error);
console.error('错误响应:', error.response);
const errorMessage = error.response?.data?.message || error.message || '操作失败';
message.error(errorMessage);
}
};
return (
<Modal
title="快速签约"
open={visible}
onOk={() => form.submit()}
onCancel={() => {
if (form.isFieldsTouched()) {
Modal.confirm({
title: '确认关闭',
content: '表单数据尚未保存,关闭后可通过草稿恢复。确定关闭吗?',
okText: '关闭',
cancelText: '继续编辑',
onOk: () => {
saveDraft()
onCancel()
},
})
} else {
onCancel()
}
}}
width={600}
okText="确认签约"
cancelText="取消"
maskClosable={false}
>
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
onValuesChange={handleFormChange}
>
{/* 基本信息 */}
<Form.Item
name="contract_code"
label="合同编号"
rules={[{ required: true, message: '请输入合同编号' }]}
>
<Input placeholder="请输入合同编号" />
</Form.Item>
<Form.Item
name="project_name"
label="项目名称"
rules={[{ required: true, message: '请输入项目名称' }]}
>
<Input placeholder="请输入项目名称" />
</Form.Item>
<Form.Item
name="contract_method"
label="承包方式"
rules={[{ required: true, message: '请选择承包方式' }]}
>
<Select
placeholder="请选择承包方式"
options={[
{ value: 'lump_sum', label: '总价包干' },
{ value: 'unit_price', label: '单价结算' }
]}
/>
</Form.Item>
<Form.Item
name="currency"
label="币种"
rules={[{ required: true, message: '请选择币种' }]}
>
<Select
placeholder="请选择币种"
options={[
{ value: 'CNY', label: '人民币' },
{ value: 'USD', label: '美元' },
{ value: 'LAK', label: '老挝基普' },
{ value: 'THB', label: '泰铢' }
]}
/>
</Form.Item>
<Form.Item
name="contract_amount"
label="总价"
rules={[
{
required: true,
message: '请输入总价'
}
]}
>
<InputNumber
style={{ width: '100%' }}
min={0}
placeholder="请输入总价"
formatter={(value) => ${value}`}
parser={(value) => value.replace(/¥\s?|(,*)/g, '')}
onChange={(value) => setContractAmount(value || 0)}
/>
</Form.Item>
{/* 工期 */}
<Form.Item
name="contract_period"
label="工期(天)"
rules={[{ required: true, message: '请输入工期' }]}
>
<InputNumber
style={{ width: '100%' }}
min={1}
placeholder="请输入工期(天)"
onChange={handlePeriodChange}
/>
</Form.Item>
<div style={{ marginTop: 16, padding: 16, background: '#f5f5f5', borderRadius: 8 }}>
<p style={{ margin: 0, fontSize: 14, color: '#666' }}>
注:此为快速签约流程,仅录入基本信息。详细的合同信息可在项目管理中补充。
</p>
</div>
</Form>
</Modal>
);
};
export default ContractCreateModal;