/**
|
* @author 韩天尊
|
* @time 2024-01-15
|
* @version 1.0.0
|
* @description 申报表单页面组件
|
*/
|
import React, { useState, useEffect } from 'react';
|
import { useNavigate } from 'react-router-dom';
|
import PageHeader from '../components/PageHeader';
|
|
const DeclarationFormPage: React.FC = () => {
|
const navigate = useNavigate();
|
const [formData, setFormData] = useState({
|
primaryCategory: '',
|
secondaryOption: '',
|
activityName: '',
|
startTime: '',
|
endTime: '',
|
proofFile: null as File | null
|
});
|
|
const [volunteerInfo, setVolunteerInfo] = useState({
|
name: '寂寞江二娃',
|
phone: '13800138000'
|
});
|
|
const [secondaryOptions, setSecondaryOptions] = useState<Array<{value: string, text: string, points: number}>>([]);
|
const [selectedPoints, setSelectedPoints] = useState(0);
|
const [serviceHours, setServiceHours] = useState(0);
|
|
// 二级选项配置
|
const secondaryOptionsConfig = {
|
'party': [
|
{ value: 'advanced_collective', text: '所在支部被评选为"先进集体"等荣誉,或事迹获得媒体报道,区级奖100分', points: 100 },
|
{ value: 'advanced_collective_city', text: '所在支部被评选为"先进集体"等荣誉,或事迹获得媒体报道,市级300分', points: 300 },
|
{ value: 'advanced_collective_national', text: '所在支部被评选为"先进集体"等荣誉,或事迹获得媒体报道,国家级奖500分', points: 500 }
|
],
|
'economy': [
|
{ value: 'investment', text: '利用自身资源成功为大渡口落实招商引资,每件奖500分', points: 500 },
|
{ value: 'public_facility', text: '爱护公物,对公共场所的设施进行维修维护,一次奖20分', points: 20 },
|
{ value: 'civilization', text: '按照十项文明行动主动参与文明创建活动,一次奖30分', points: 30 }
|
],
|
'security': [
|
{ value: 'military_service', text: '主动报名参军,考核过关以及服役期间,奖励军属、军人300分', points: 300 },
|
{ value: 'good_deed', text: '见义勇为、舍己救人、拾到财物,主动上交或交还失主等好人好事,300分', points: 300 },
|
{ value: 'risk_report', text: '发现偷盗、火灾、自然灾害等险情,及时向物业、社区以及公安机关提供有效信息,一次奖100分', points: 100 }
|
],
|
'service': [
|
{ value: 'outstanding_district', text: '因工作、生活中表现突出,获得表彰或媒体正面宣传报道,区级一次奖100分', points: 100 },
|
{ value: 'outstanding_city', text: '因工作、生活中表现突出,获得表彰或媒体正面宣传报道,市级一次300奖分', points: 300 },
|
{ value: 'outstanding_national', text: '因工作、生活中表现突出,获得表彰或媒体正面宣传报道,国家级一次500奖分', points: 500 }
|
],
|
'illegal': [
|
{ value: 'illegal_organization', text: '组织或加入邪教组织,及参加违法乱纪犯罪活动,罚减1000分', points: -1000 },
|
{ value: 'waste_ceremony', text: '举办婚礼、寿礼、葬礼等活动时铺张浪费,罚减100', points: -100 },
|
{ value: 'illegal_advertisement', text: '在车站、街道、厕所、小区等公共场所张贴或涂写小广告,罚减100', points: -100 }
|
]
|
};
|
|
// 初始化时间选择器
|
useEffect(() => {
|
const now = new Date();
|
const currentTimeStr = now.toISOString().slice(0, 16);
|
setFormData(prev => ({
|
...prev,
|
startTime: currentTimeStr,
|
endTime: currentTimeStr
|
}));
|
}, []);
|
|
// 处理一级分类变化
|
const handlePrimaryCategoryChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
const category = e.target.value;
|
setFormData(prev => ({
|
...prev,
|
primaryCategory: category,
|
secondaryOption: ''
|
}));
|
setSecondaryOptions(category ? secondaryOptionsConfig[category as keyof typeof secondaryOptionsConfig] || [] : []);
|
setSelectedPoints(0);
|
};
|
|
// 处理二级选项变化
|
const handleSecondaryOptionChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
const option = e.target.value;
|
setFormData(prev => ({ ...prev, secondaryOption: option }));
|
|
if (option) {
|
const selectedOption = secondaryOptions.find(opt => opt.value === option);
|
setSelectedPoints(selectedOption?.points || 0);
|
} else {
|
setSelectedPoints(0);
|
}
|
};
|
|
// 处理时间变化
|
const handleTimeChange = (field: 'startTime' | 'endTime', value: string) => {
|
setFormData(prev => ({ ...prev, [field]: value }));
|
calculateServiceHours();
|
};
|
|
// 计算服务时长
|
const calculateServiceHours = () => {
|
if (formData.startTime && formData.endTime) {
|
const startTime = new Date(formData.startTime);
|
const endTime = new Date(formData.endTime);
|
|
if (endTime > startTime) {
|
const timeDiff = endTime.getTime() - startTime.getTime();
|
const hours = (timeDiff / (1000 * 60 * 60)).toFixed(1);
|
setServiceHours(parseFloat(hours));
|
} else {
|
setServiceHours(0);
|
}
|
} else {
|
setServiceHours(0);
|
}
|
};
|
|
// 处理文件上传
|
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const file = e.target.files?.[0];
|
if (file) {
|
setFormData(prev => ({ ...prev, proofFile: file }));
|
}
|
};
|
|
// 处理表单提交
|
const handleSubmit = (e: React.FormEvent) => {
|
e.preventDefault();
|
console.log('提交申报:', formData);
|
navigate('/points-declaration');
|
};
|
|
return (
|
<div className="page points-declaration-page">
|
<PageHeader title="自主申报" />
|
|
<div className="declaration-form">
|
{/* 申报分类 */}
|
<div className="form-section">
|
<h3 className="section-title">申报分类</h3>
|
<div className="form-group">
|
<label>类别</label>
|
<select
|
className="form-select"
|
value={formData.primaryCategory}
|
onChange={handlePrimaryCategoryChange}
|
required
|
>
|
<option value="">请选择类别</option>
|
<option value="party">党的建设</option>
|
<option value="economy">经济发展</option>
|
<option value="security">平安法治</option>
|
<option value="service">民生服务</option>
|
<option value="illegal">失信违法</option>
|
</select>
|
</div>
|
<div className="form-group">
|
<label>积分选项</label>
|
<select
|
className="form-select"
|
value={formData.secondaryOption}
|
onChange={handleSecondaryOptionChange}
|
required
|
disabled={!formData.primaryCategory}
|
>
|
<option value="">请先选择积分选项</option>
|
{secondaryOptions.map(option => (
|
<option key={option.value} value={option.value} data-points={option.points}>
|
{option.text}
|
</option>
|
))}
|
</select>
|
</div>
|
<div className="form-group">
|
<label>预计积分</label>
|
<div className="points-display">
|
<span className="points-value">{selectedPoints}</span>
|
<span className="points-unit">分</span>
|
</div>
|
</div>
|
</div>
|
|
{/* 服务记录 */}
|
<div className="form-section">
|
<h3 className="section-title">服务记录</h3>
|
<div className="form-group">
|
<label>活动名称</label>
|
<input
|
type="text"
|
placeholder="请输入活动名称"
|
className="form-input"
|
value={formData.activityName}
|
onChange={(e) => setFormData(prev => ({ ...prev, activityName: e.target.value }))}
|
required
|
/>
|
</div>
|
<div className="form-group">
|
<label>参加活动时间</label>
|
<div className="time-range-container">
|
<div className="time-input-group">
|
<label className="time-label">开始时间</label>
|
<input
|
type="datetime-local"
|
className="form-input time-input"
|
value={formData.startTime}
|
onChange={(e) => handleTimeChange('startTime', e.target.value)}
|
required
|
/>
|
</div>
|
<div className="time-input-group">
|
<label className="time-label">结束时间</label>
|
<input
|
type="datetime-local"
|
className="form-input time-input"
|
value={formData.endTime}
|
onChange={(e) => handleTimeChange('endTime', e.target.value)}
|
required
|
/>
|
</div>
|
</div>
|
</div>
|
<div className="form-group">
|
<label>服务时长</label>
|
<div className="service-hours-display">
|
<span className="hours-value">{serviceHours}</span>
|
<span className="hours-unit">小时</span>
|
</div>
|
</div>
|
<div className="form-group">
|
<label>证明文件(现场照片或荣誉文书)</label>
|
<div className="file-upload">
|
<input
|
type="file"
|
accept="image/*,.pdf"
|
className="file-input-hidden"
|
onChange={handleFileChange}
|
id="proof-file"
|
/>
|
<button
|
type="button"
|
className="upload-btn"
|
onClick={() => {
|
const fileInput = document.getElementById('proof-file') as HTMLInputElement;
|
if (fileInput) fileInput.click();
|
}}
|
>
|
<i className="fas fa-cloud-upload-alt"></i>
|
<span>点击上传证明文件</span>
|
</button>
|
</div>
|
</div>
|
</div>
|
|
{/* 基础信息 */}
|
<div className="form-section">
|
<h3 className="section-title">基础信息</h3>
|
<div className="form-group">
|
<label>姓名</label>
|
<input
|
type="text"
|
className="form-input"
|
value={volunteerInfo.name}
|
readOnly
|
/>
|
</div>
|
<div className="form-group">
|
<label>联系方式</label>
|
<input
|
type="tel"
|
className="form-input"
|
value={volunteerInfo.phone}
|
readOnly
|
/>
|
</div>
|
</div>
|
|
{/* 提交按钮 */}
|
<div className="form-actions">
|
<button type="submit" className="submit-btn" onClick={handleSubmit}>
|
<i className="fas fa-paper-plane"></i>
|
提交申报
|
</button>
|
</div>
|
</div>
|
</div>
|
);
|
};
|
|
export default DeclarationFormPage;
|