import React, { useState, useEffect, useCallback } from 'react'; import { Card, Typography, Button, Form, Input, Select, DatePicker, InputNumber, Radio, Space, message, Divider, Row, Col, Modal } from 'antd'; import { SaveOutlined, ArrowLeftOutlined } from '@ant-design/icons'; import { useNavigate } from 'react-router-dom'; import apiClient from '../../utils/request'; import dayjs from 'dayjs'; import FileUpload from '../../components/FileUpload'; import { useAuthStore } from '../../store/authStore'; import { useLanguageStore } from '../../store/languageStore'; import useFormDraft from '../../hooks/useFormDraft'; const { Title, Paragraph } = Typography; const { Option } = Select; const { TextArea } = Input; interface Customer { id: number; name: string; } interface User { id: number; name: string; department?: string; } const BudgetProjectCreate: React.FC = () => { const [isMobile, setIsMobile] = useState(false); const [loading, setLoading] = useState(false); const [customers, setCustomers] = useState([]); const [users, setUsers] = useState([]); const [form] = Form.useForm(); const [attachments, setAttachments] = useState([]); const [surveyPhotos, setSurveyPhotos] = useState([]); const navigate = useNavigate(); const { user: currentUser } = useAuthStore(); const { t, currentLanguage } = useLanguageStore(); const isAdmin = currentUser?.role === 'admin'; const { save: saveDraft, restore: restoreDraft, clear: clearDraft, hasDraft } = useFormDraft({ form, storageKey: 'budget_project_create', onRestore: (data) => { if (data.attachments) setAttachments(data.attachments); if (data.surveyPhotos) setSurveyPhotos(data.surveyPhotos); }, }); const handleFormChange = useCallback(() => { saveDraft({ attachments, surveyPhotos }); }, [saveDraft, attachments, surveyPhotos]); useEffect(() => { const handler = (e: BeforeUnloadEvent) => { if (form.isFieldsTouched()) { e.preventDefault(); } }; window.addEventListener('beforeunload', handler); return () => window.removeEventListener('beforeunload', handler); }, [form]); useEffect(() => { const handler = () => { if (document.visibilityState === 'hidden' && form.isFieldsTouched()) { saveDraft({ attachments, surveyPhotos }); } }; document.addEventListener('visibilitychange', handler); const pageHideHandler = () => { if (form.isFieldsTouched()) saveDraft({ attachments, surveyPhotos }); }; window.addEventListener('pagehide', pageHideHandler); return () => { document.removeEventListener('visibilitychange', handler); window.removeEventListener('pagehide', pageHideHandler); }; }, [form, saveDraft, attachments, surveyPhotos]); useEffect(() => { if (hasDraft()) { Modal.confirm({ title: t('common.draftFound'), content: t('common.draftRestore'), okText: t('common.restoreDraft'), cancelText: t('common.reFill'), onOk: () => { restoreDraft(); }, onCancel: () => { clearDraft(); }, }); } }, []); useEffect(() => { if (!isAdmin) { message.error(t('budget.noAccess')); navigate('/budget-projects'); } }, [isAdmin, navigate]); const intermediaryFeeType = Form.useWatch('intermediary_fee_type', form); useEffect(() => { const checkMobile = () => setIsMobile(window.innerWidth <= 768); checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); useEffect(() => { fetchCustomers(); fetchUsers(); }, []); const fetchCustomers = async () => { try { const res = await apiClient.get('/customers'); if (res.data.success) setCustomers(res.data.data); } catch (error) { console.error('获取客户列表失败:', error); } }; const fetchUsers = async () => { try { const res = await apiClient.get('/users'); if (res.data.success) setUsers(res.data.data); } catch (error) { console.error('获取用户列表失败:', error); } }; const handleSubmit = async () => { try { const values = await form.validateFields(); setLoading(true); const projectData = { ...values, attachments, survey_photos: surveyPhotos, survey_date: values.survey_date?.format('YYYY-MM-DD'), status: 'negotiating', }; const res = await apiClient.post('/budget-projects', projectData, { headers: { 'x-user-role': 'admin' } }); if (res.data.success) { message.success(t('budget.createSuccess')); clearDraft(); navigate('/budget-projects'); } } catch (error: any) { if (error.response?.data?.error) { message.error(error.response.data.error); } else { message.error(t('budget.createFailed')); } } finally { setLoading(false); } }; return (
{t('budget.createTitle')}
{t('budget.createDesc')}
{t('budget.basicInfo')} {t('budget.intermediary')} {t('budget.fixedAmount')} {t('budget.percentage')} {t('budget.projectDetail')}