chore: initial import
This commit is contained in:
@@ -0,0 +1,638 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import { Form, Input, Button, Tabs, DatePicker, InputNumber, Upload, Card, message, Space, Checkbox, Divider, Select, Alert } from 'antd';
|
||||
import { UploadOutlined, PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
|
||||
import axios from 'axios';
|
||||
import API_BASE_URL from '../config';
|
||||
import UserSearchSelect from '../components/UserSearchSelect';
|
||||
import { maskPhone } from '../utils/phoneMask';
|
||||
import {
|
||||
achievementTypes,
|
||||
uploadTips,
|
||||
contributorTips,
|
||||
dateTips,
|
||||
nameLabels,
|
||||
contributorLabels,
|
||||
dateLabels,
|
||||
roleOptions,
|
||||
contributorAddButtonLabels,
|
||||
contributorMainLabels,
|
||||
nameTips,
|
||||
sourceTips
|
||||
} from '../constants/achievements';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const UploadPage = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [type, setType] = useState('project');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [fileList, setFileList] = useState([]);
|
||||
// 项目类专用文件列表
|
||||
const [projectProofFiles, setProjectProofFiles] = useState([]); // 立项证明
|
||||
const [projectPlanFiles, setProjectPlanFiles] = useState([]); // 实施方案
|
||||
const [projectSummaryFiles, setProjectSummaryFiles] = useState([]); // 验收总结
|
||||
|
||||
const [dicts, setDicts] = useState({
|
||||
organizations: [],
|
||||
'award-types': [],
|
||||
'award-levels': [],
|
||||
'paper-types': [],
|
||||
'standard-types': [],
|
||||
'project-categories': []
|
||||
});
|
||||
|
||||
const fetchDicts = useMemo(() => async () => {
|
||||
const types = ['organizations', 'award-types', 'award-levels', 'paper-types', 'standard-types', 'project-categories'];
|
||||
const token = localStorage.getItem('token');
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
types.map(t => axios.get(`${API_BASE_URL}/api/dictionaries/${t}`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
}))
|
||||
);
|
||||
const newDicts = {};
|
||||
types.forEach((t, index) => {
|
||||
newDicts[t] = results[index].data;
|
||||
});
|
||||
setDicts(newDicts);
|
||||
} catch (error) {
|
||||
console.error('获取字典失败', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDicts();
|
||||
}, [fetchDicts]);
|
||||
|
||||
const renderDictSelectWithCustom = (name, label, dictData, rules = []) => {
|
||||
return (
|
||||
<>
|
||||
<Form.Item name={name} label={label} rules={rules}>
|
||||
<Select placeholder={`请选择${label}`}>
|
||||
<Option value="无">无</Option>
|
||||
{dictData.filter(d => d.name !== '待定').map(d => (
|
||||
<Option key={d.id} value={d.name}>{d.name}</Option>
|
||||
))}
|
||||
<Option value="其他">其他</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prev, current) => prev[name] !== current[name]}
|
||||
>
|
||||
{({ getFieldValue }) =>
|
||||
getFieldValue(name) === '其他' ? (
|
||||
<Form.Item
|
||||
name={`${name}_custom`}
|
||||
label={`请输入${label}`}
|
||||
rules={[{ required: true, message: `请输入${label}` }]}
|
||||
>
|
||||
<Input placeholder={`请输入${label}`} />
|
||||
</Form.Item>
|
||||
) : null
|
||||
}
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const onFinish = async (values) => {
|
||||
setLoading(true);
|
||||
|
||||
// 处理“其他”选项的自定义输入
|
||||
const customFields = ['first_unit', 'assignee', 'owner_unit'];
|
||||
customFields.forEach(field => {
|
||||
if (values[field] === '其他') {
|
||||
values[field] = values[`${field}_custom`];
|
||||
}
|
||||
delete values[`${field}_custom`];
|
||||
});
|
||||
|
||||
// 前端去重校验
|
||||
const contributors = values.contributors || [];
|
||||
const phoneSet = new Set();
|
||||
for (const c of contributors) {
|
||||
if (c.user) {
|
||||
const u = JSON.parse(c.user);
|
||||
if (phoneSet.has(u.phone)) {
|
||||
message.error(`完成人列表中存在重复的员工:${u.real_name} (${maskPhone(u.phone)})。请删除重复项。`);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
phoneSet.add(u.phone);
|
||||
}
|
||||
}
|
||||
|
||||
// 排名去重校验
|
||||
if (!['project', 'transformation'].includes(type)) {
|
||||
const rankingSet = new Set();
|
||||
for (const c of contributors) {
|
||||
if (c.ranking) {
|
||||
if (rankingSet.has(c.ranking)) {
|
||||
message.error(`完成人排名不能重复:第 ${c.ranking} 名出现了多次。`);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
rankingSet.add(c.ranking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 附件校验
|
||||
if (type === 'project') {
|
||||
if (projectProofFiles.length === 0) {
|
||||
message.error('请上传立项证明');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
if (projectPlanFiles.length === 0) {
|
||||
message.error('请上传实施方案');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
if (projectSummaryFiles.length === 0) {
|
||||
message.error('请上传验收总结');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (fileList.length === 0) {
|
||||
message.error('请至少上传一个附件');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('type', type);
|
||||
|
||||
const finalContributors = (values.contributors || []).map(c => {
|
||||
const u = c.user ? JSON.parse(c.user) : {};
|
||||
return {
|
||||
name: u.real_name,
|
||||
phone: u.phone,
|
||||
role: c.role,
|
||||
isMain: c.isMain,
|
||||
ranking: c.ranking
|
||||
};
|
||||
}).filter(c => c.name);
|
||||
|
||||
const { name, achievement_date, remarks, contributors: _ignoredContributors, approver, ...details } = values;
|
||||
|
||||
formData.append('name', name);
|
||||
formData.append('contributors', JSON.stringify(finalContributors));
|
||||
formData.append('achievement_date', achievement_date ? achievement_date.format('YYYY-MM-DD') : '');
|
||||
formData.append('remarks', remarks || '');
|
||||
|
||||
// 处理签批领导
|
||||
if (type === 'report' && approver) {
|
||||
try {
|
||||
const approverUser = JSON.parse(approver);
|
||||
details.approver_id = approverUser.id;
|
||||
details.approver_name = approverUser.real_name;
|
||||
} catch (e) {
|
||||
console.error('解析签批领导信息失败', e);
|
||||
}
|
||||
}
|
||||
|
||||
formData.append('details', JSON.stringify(details));
|
||||
|
||||
if (type === 'project') {
|
||||
// 项目类附件处理:添加前缀以区分
|
||||
projectProofFiles.forEach(file => {
|
||||
const newFile = new File([file.originFileObj], `[立项证明]-${file.name}`, { type: file.type });
|
||||
formData.append('attachments', newFile);
|
||||
});
|
||||
projectPlanFiles.forEach(file => {
|
||||
const newFile = new File([file.originFileObj], `[实施方案]-${file.name}`, { type: file.type });
|
||||
formData.append('attachments', newFile);
|
||||
});
|
||||
projectSummaryFiles.forEach(file => {
|
||||
const newFile = new File([file.originFileObj], `[验收总结]-${file.name}`, { type: file.type });
|
||||
formData.append('attachments', newFile);
|
||||
});
|
||||
} else {
|
||||
fileList.forEach(file => {
|
||||
formData.append('attachments', file.originFileObj);
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
await axios.post(`${API_BASE_URL}/api/achievements`, formData, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
message.success('成果上传成功,请等待管理员审核');
|
||||
form.resetFields();
|
||||
setFileList([]);
|
||||
setProjectProofFiles([]);
|
||||
setProjectPlanFiles([]);
|
||||
setProjectSummaryFiles([]);
|
||||
} catch (error) {
|
||||
message.error(error.response?.data?.message || '上传失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const renderCommonFields = () => {
|
||||
const hasRanking = !['project', 'transformation'].includes(type);
|
||||
const useCheckbox = ['project', 'transformation'].includes(type);
|
||||
const isPaper = type === 'paper';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Divider orientation="center" style={{ fontWeight: 'bold', fontSize: '16px', margin: '24px 0', color: '#1890ff' }}>成果名称</Divider>
|
||||
{nameTips[type] && (
|
||||
<Alert
|
||||
message={nameTips[type]}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 16, width: 'fit-content' }}
|
||||
/>
|
||||
)}
|
||||
<Form.Item
|
||||
name="name"
|
||||
label={nameLabels[type] || "成果名称"}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Divider orientation="center" style={{ fontWeight: 'bold', fontSize: '16px', margin: '24px 0', color: '#1890ff' }}>完成人信息</Divider>
|
||||
{contributorTips[type] && (
|
||||
<Alert
|
||||
message={contributorTips[type]}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 16, width: 'fit-content' }}
|
||||
/>
|
||||
)}
|
||||
<Form.Item label={contributorLabels[type]} style={{ marginBottom: 0 }}>
|
||||
<Form.List
|
||||
name="contributors"
|
||||
initialValue={[{
|
||||
user: undefined,
|
||||
role: isPaper ? '第一作者' : undefined,
|
||||
isMain: useCheckbox,
|
||||
ranking: hasRanking ? 1 : undefined
|
||||
}]}
|
||||
>
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.length > 0 && (
|
||||
<Space style={{ display: 'flex', marginBottom: 4 }} align="baseline">
|
||||
<span style={{ display: 'inline-block', width: 250 }}>
|
||||
<span style={{ color: '#ff4d4f', marginRight: 4 }}>*</span>姓名
|
||||
</span>
|
||||
|
||||
{hasRanking && (
|
||||
<span style={{ display: 'inline-block', width: 80 }}>
|
||||
<span style={{ color: '#ff4d4f', marginRight: 4 }}>*</span>排名
|
||||
</span>
|
||||
)}
|
||||
|
||||
{isPaper && (
|
||||
<span style={{ display: 'inline-block', width: 150 }}>
|
||||
<span style={{ color: '#ff4d4f', marginRight: 4 }}>*</span>角色
|
||||
</span>
|
||||
)}
|
||||
|
||||
{useCheckbox && (
|
||||
<span>
|
||||
{contributorMainLabels[type] || contributorMainLabels.default}
|
||||
</span>
|
||||
)}
|
||||
</Space>
|
||||
)}
|
||||
{fields.map(({ key, name, ...restField }) => (
|
||||
<Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'user']}
|
||||
rules={[{ required: true, message: '请搜索并选择员工' }]}
|
||||
>
|
||||
<UserSearchSelect placeholder="搜索姓名/手机号" style={{ width: 250 }} />
|
||||
</Form.Item>
|
||||
|
||||
{hasRanking && (
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'ranking']}
|
||||
rules={[{ required: true, message: '请输入排名' }]}
|
||||
>
|
||||
<InputNumber min={1} placeholder="排名" style={{ width: 80 }} />
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{isPaper && (
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'role']}
|
||||
rules={[{ required: true, message: '请选择角色' }]}
|
||||
>
|
||||
<Select placeholder="角色" style={{ width: 150 }}>
|
||||
{roleOptions.map(r => <Option key={r} value={r}>{r}</Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{useCheckbox && (
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'isMain']}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Checkbox>
|
||||
{contributorMainLabels[type] || contributorMainLabels.default}
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{fields.length > 1 && (
|
||||
<MinusCircleOutlined onClick={() => remove(name)} />
|
||||
)}
|
||||
</Space>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
|
||||
{contributorAddButtonLabels[type] || contributorAddButtonLabels.default}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form.Item>
|
||||
<Divider orientation="center" style={{ fontWeight: 'bold', fontSize: '16px', margin: '24px 0', color: '#1890ff' }}>成果信息</Divider>
|
||||
|
||||
{dateTips[type] && (
|
||||
<Alert
|
||||
message={dateTips[type]}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 12, width: 'fit-content' }}
|
||||
/>
|
||||
)}
|
||||
<Form.Item
|
||||
name="achievement_date"
|
||||
label={dateLabels[type] || "成果时间"}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<DatePicker style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item name="remarks" label="备注"><Input.TextArea rows={3} /></Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderSpecificFields = () => {
|
||||
switch (type) {
|
||||
case 'paper':
|
||||
return (
|
||||
<>
|
||||
{renderDictSelectWithCustom('first_unit', '完成单位', dicts['organizations'], [{ required: true, message: '请选择完成单位' }])}
|
||||
|
||||
<Form.Item name="paper_type" label="论文水平" rules={[{ required: true, message: '请选择论文水平' }]}>
|
||||
<Select placeholder="请选择论文水平">
|
||||
{dicts['paper-types'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="journal_name" label="期刊名称"><Input /></Form.Item>
|
||||
<Form.Item name="doi" label="DOI"><Input /></Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'project':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="project_category" label="项目分类">
|
||||
<Select placeholder="请选择项目分类">
|
||||
{dicts['project-categories'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{sourceTips[type] && (
|
||||
<Alert
|
||||
message={sourceTips[type]}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 16, width: 'fit-content' }}
|
||||
/>
|
||||
)}
|
||||
<Form.Item name="source" label="项目来源"><Input /></Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'award':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="award_type" label="奖励种类">
|
||||
<Select placeholder="请选择奖励种类">
|
||||
{dicts['award-types'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="award_level" label="奖励等级">
|
||||
<Select placeholder="请选择奖励等级">
|
||||
{dicts['award-levels'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="award_unit" label="授奖单位">
|
||||
<Input placeholder="请输入授奖单位" />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'standard':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="standard_type" label="标准种类">
|
||||
<Select placeholder="请选择标准种类">
|
||||
{dicts['standard-types'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="standard_no" label="标准编号" rules={[{ required: true }]}><Input /></Form.Item>
|
||||
<Form.Item name="implement_date" label="实施日期"><DatePicker style={{ width: '100%' }} /></Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'monograph':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="publisher" label="出版社"><Input /></Form.Item>
|
||||
<Form.Item name="isbn" label="ISBN"><Input /></Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'report':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="report_type" label="技术报告类型" rules={[{ required: true }]}><Input /></Form.Item>
|
||||
<Form.Item name="recipient" label="发布(提报)对象" rules={[{ required: true }]}><Input /></Form.Item>
|
||||
<Form.Item
|
||||
name="approver"
|
||||
label="签批院领导"
|
||||
rules={[{ required: true, message: '请选择签批院领导' }]}
|
||||
tooltip="仅显示领导层部门的用户"
|
||||
>
|
||||
<UserSearchSelect placeholder="搜索并选择签批领导" leaderOnly={true} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'plan':
|
||||
return null;
|
||||
case 'patent':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="patent_no" label="专利号" rules={[{ required: true }]}><Input /></Form.Item>
|
||||
{renderDictSelectWithCustom('assignee', '权利人', dicts['organizations'], [{ required: true, message: '请选择权利人' }])}
|
||||
<Form.Item name="patent_type" label="专利类型" rules={[{ required: true }]}>
|
||||
<Select placeholder="请选择专利类型">
|
||||
<Select.Option value="发明专利">发明专利</Select.Option>
|
||||
<Select.Option value="实用新型专利">实用新型专利</Select.Option>
|
||||
<Select.Option value="外观设计专利">外观设计专利</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'transformation':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="project_category" label="项目分类">
|
||||
<Select placeholder="请选择项目分类">
|
||||
{dicts['project-categories'].filter(d => d.name !== '待定').map(d => <Select.Option key={d.id} value={d.name}>{d.name}</Select.Option>)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="trans_method" label="转化方式"><Input /></Form.Item>
|
||||
<Form.Item name="trans_amount" label="转化金额 (元)"><InputNumber style={{ width: '100%' }} /></Form.Item>
|
||||
</>
|
||||
);
|
||||
case 'software':
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="reg_no" label="登记号" rules={[{ required: true }]}><Input /></Form.Item>
|
||||
{renderDictSelectWithCustom('owner_unit', '著作权人', dicts['organizations'], [{ required: true, message: '请选择著作权人' }])}
|
||||
<Form.Item name="acquisition_method" label="权利取得方式" rules={[{ required: true }]}>
|
||||
<Select placeholder="请选择权利取得方式">
|
||||
<Select.Option value="原始取得">原始取得</Select.Option>
|
||||
<Select.Option value="继受取得">继受取得</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="scope" label="权利范围" rules={[{ required: true }]}>
|
||||
<Select placeholder="请选择权利范围">
|
||||
<Select.Option value="全部权利">全部权利</Select.Option>
|
||||
<Select.Option value="部分权利">部分权利</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return <p>未知类型</p>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card title="上传科技成果">
|
||||
<Tabs
|
||||
type="card"
|
||||
size="large"
|
||||
tabBarStyle={{ marginBottom: 24, fontWeight: 'bold' }}
|
||||
activeKey={type}
|
||||
onChange={(key) => {
|
||||
setType(key);
|
||||
form.resetFields();
|
||||
setFileList([]);
|
||||
setProjectProofFiles([]);
|
||||
setProjectPlanFiles([]);
|
||||
setProjectSummaryFiles([]);
|
||||
}}
|
||||
items={achievementTypes.map(t => ({
|
||||
key: t.key,
|
||||
label: t.label,
|
||||
}))}
|
||||
/>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={onFinish}
|
||||
style={{ marginTop: 24 }}
|
||||
>
|
||||
{renderCommonFields()}
|
||||
{renderSpecificFields()}
|
||||
|
||||
<Divider orientation="center" style={{ fontWeight: 'bold', fontSize: '16px', margin: '24px 0', color: '#1890ff' }}>附件上传</Divider>
|
||||
|
||||
{type === 'project' ? (
|
||||
<>
|
||||
<Alert
|
||||
message="项目类成果必须上传以下三类附件"
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 16, width: 'fit-content' }}
|
||||
/>
|
||||
<Form.Item label="立项证明" required>
|
||||
<Upload
|
||||
beforeUpload={() => false}
|
||||
fileList={projectProofFiles}
|
||||
onChange={({ fileList }) => setProjectProofFiles(fileList)}
|
||||
multiple
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传立项证明</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
<Form.Item label="实施方案" required>
|
||||
<Upload
|
||||
beforeUpload={() => false}
|
||||
fileList={projectPlanFiles}
|
||||
onChange={({ fileList }) => setProjectPlanFiles(fileList)}
|
||||
multiple
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传实施方案</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
<Form.Item label="验收总结" required>
|
||||
<Upload
|
||||
beforeUpload={() => false}
|
||||
fileList={projectSummaryFiles}
|
||||
onChange={({ fileList }) => setProjectSummaryFiles(fileList)}
|
||||
multiple
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传验收总结</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</>
|
||||
) : (
|
||||
<Form.Item>
|
||||
{uploadTips[type] && (
|
||||
<Alert
|
||||
message={uploadTips[type]}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: 12, width: 'fit-content' }}
|
||||
/>
|
||||
)}
|
||||
<Upload
|
||||
beforeUpload={() => false}
|
||||
fileList={fileList}
|
||||
onChange={({ fileList }) => setFileList(fileList)}
|
||||
multiple
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>选择文件</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit" loading={loading}>
|
||||
提交审核
|
||||
</Button>
|
||||
<Button onClick={() => form.resetFields()}>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadPage;
|
||||
Reference in New Issue
Block a user