forked from Gitlink/forgeplus-react
349 lines
15 KiB
JavaScript
349 lines
15 KiB
JavaScript
import React , { useCallback, useEffect , useState } from 'react';
|
||
import { Button, Form, Input, Select, Upload, message, Popconfirm, Checkbox, Icon, Tooltip } from 'antd';
|
||
import {getUploadActionUrl} from 'educoder';
|
||
import {applyGlcc, findStudentTaskByTaskId, updateApplyGlcc} from '../api';
|
||
import TextArea from 'antd/lib/input/TextArea';
|
||
import { main_site_url } from '../fetch';
|
||
import TaskApply from './taskApply';
|
||
import './index.scss';
|
||
import { FlexAJ } from '../../forge/Component/layout';
|
||
const Option = Select.Option;
|
||
// 编辑项目、课题报名信息
|
||
function EditRepoApplyInfo(props) {
|
||
const {form, applyInfo, current_user, round, cateList, setReload, isAddRepo, setIsAddRepo, setIsEdit, setEditRepoCount, rewardList} = props;
|
||
const phonereg = /(^|\s*\+?0?0?86|\D)(1\d{2})[-\s]{0,3}(\d{4})[-\s]{0,3}(\d{4})(?=\D|$)/
|
||
const emailreg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
|
||
const {getFieldDecorator, validateFields, setFieldsValue, validateFieldsAndScroll, getFieldValue, resetFields } = form;
|
||
const [imageUrl, setImageUrl] = useState(undefined);
|
||
// 提交按钮loading效果
|
||
const [loading, setLoading] = useState(false);
|
||
// 课题报名个数
|
||
const [taskCount, setTaskCount] = useState(undefined);
|
||
|
||
useEffect(()=>{
|
||
if(applyInfo){
|
||
const {projectName, projectType, gitlinkUrl, contactName, contactPhone, projectIntro, registrationTaskList, projectLogoId, contactMail, joinCooperativeCommunity} = applyInfo;
|
||
const taskInfo = {};
|
||
const taskRewardRemark = {};
|
||
const taskCountArr = []
|
||
registrationTaskList.map((item, index)=>{
|
||
taskCountArr.push(index+1);
|
||
const{taskName, taskUrl, taskDifficulty, tutorName, tutorMail, taskDesc, tutorPhone, id, settingRewardId, settingRewardRemark, tutorAddress} = item;
|
||
taskInfo[`taskName${index+1}`] = taskName;
|
||
taskInfo[`taskUrl${index+1}`] = taskUrl;
|
||
taskInfo[`taskDifficulty${index+1}`] = taskDifficulty;
|
||
taskInfo[`tutorName${index+1}`] = tutorName;
|
||
taskInfo[`tutorMail${index+1}`] = tutorMail;
|
||
taskInfo[`taskDesc${index+1}`] = taskDesc;
|
||
taskInfo[`tutorPhone${index+1}`] = tutorPhone;
|
||
taskInfo[`tutorAddress${index+1}`] = tutorAddress;
|
||
taskInfo[`taskId${index+1}`] = id;
|
||
taskInfo[`settingRewardId${index+1}`] = parseInt(settingRewardId);
|
||
// taskInfo[`settingRewardRemark${index+1}`] = settingRewardRemark;
|
||
taskRewardRemark[`settingRewardRemark${index+1}`] = settingRewardRemark;
|
||
})
|
||
setTaskCount(taskCountArr);
|
||
setTimeout(() => {
|
||
setFieldsValue({
|
||
projectName, projectType, gitlinkUrl, contactName, contactPhone, projectIntro, contactMail,
|
||
...taskInfo,
|
||
logo: {file:{response:{id: projectLogoId}}},
|
||
joinCooperativeCommunity,
|
||
})
|
||
}, 100);
|
||
// 课题奖励备注要根据奖励方式注入select/input
|
||
setTimeout(() => {
|
||
setFieldsValue({
|
||
...taskRewardRemark,
|
||
})
|
||
}, 300);
|
||
}else{
|
||
setTaskCount([1])
|
||
}
|
||
}, [])
|
||
|
||
const helper = useCallback(
|
||
(label, extra, name, rules, widget) => (
|
||
<Form.Item label={label} extra={extra}>
|
||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||
</Form.Item>
|
||
),
|
||
[]
|
||
);
|
||
|
||
// 当用户输入结束时 检验用户输入是否符合规范
|
||
function verify(dataIndex){
|
||
validateFields([dataIndex],(error, values)=>{
|
||
if(error && error[dataIndex]){
|
||
return;
|
||
}
|
||
})
|
||
}
|
||
|
||
// 报名夏令营
|
||
function handleSubmit(e){
|
||
e.preventDefault();
|
||
validateFieldsAndScroll((err, values) => {
|
||
if (!err) {
|
||
const registrationTaskList = []
|
||
taskCount && taskCount.map(item=>{
|
||
registrationTaskList.push({
|
||
id: values[`taskId${item}`],
|
||
taskName: values[`taskName${item}`],
|
||
taskUrl: values[`taskUrl${item}`],
|
||
taskDifficulty: values[`taskDifficulty${item}`],
|
||
settingRewardId: values[`settingRewardId${item}`],
|
||
settingRewardRemark: values[`settingRewardRemark${item}`],
|
||
tutorName: values[`tutorName${item}`],
|
||
tutorMail: values[`tutorMail${item}`],
|
||
tutorAddress: values[`tutorAddress${item}`],
|
||
taskDesc: values[`taskDesc${item}`],
|
||
tutorPhone: values[`tutorPhone${item}`],
|
||
round
|
||
})
|
||
})
|
||
const {projectName, projectType, gitlinkUrl, contactName, contactPhone, projectIntro, contactMail, joinCooperativeCommunity=false} = values;
|
||
const params ={
|
||
projectName, projectType, gitlinkUrl, contactName, contactPhone, projectIntro, registrationTaskList, round, contactMail, joinCooperativeCommunity,
|
||
projectLogoId: values.logo.file.response.id+"",
|
||
userId: current_user.user_id,
|
||
userName: current_user.username
|
||
}
|
||
setLoading(true);
|
||
if(applyInfo){
|
||
// 用户已经报名项目
|
||
params[`id`] = applyInfo.id;
|
||
updateApplyGlcc(params).then(response=>{
|
||
setLoading(false);
|
||
if(response && response.message === "success"){
|
||
message.success("修改成功");
|
||
setReload();
|
||
}
|
||
setIsEdit(false);
|
||
setEditRepoCount(0);
|
||
setTimeout(() => {
|
||
scrollToRepoInfo()
|
||
}, 100);
|
||
}).catch(error=>{
|
||
setLoading(false);
|
||
})
|
||
return
|
||
}
|
||
applyGlcc(params).then(response=>{
|
||
setLoading(false);
|
||
if(response && response.message === "success"){
|
||
message.success("报名成功");
|
||
isAddRepo && setIsAddRepo(false);
|
||
setReload();
|
||
}
|
||
window.scrollTo(0,950);
|
||
}).catch(error=>{
|
||
setLoading(false);
|
||
})
|
||
}
|
||
});
|
||
};
|
||
|
||
// 检查文件上传是否符合规定
|
||
function beforeUpload(file){
|
||
const isLt100M = file.size / 1024 / 1024 < 20;
|
||
if (!isLt100M) {
|
||
message.error(`文件大小必须小于${20}M!`);
|
||
}
|
||
const isType = file.type === "image/png" || file.type === "image/jpg" || file.type === "image/jpeg";
|
||
if (!isType) {
|
||
message.error("只能上传png、jpg、jpeg格式文件");
|
||
}
|
||
return isLt100M && isType;
|
||
}
|
||
function getBase64(img, callback) {
|
||
const reader = new FileReader();
|
||
reader.addEventListener('load', () => callback(reader.result));
|
||
reader.readAsDataURL(img);
|
||
reader.onload = function(e) {
|
||
setImageUrl(e.target.result); // 上传的图片的编码
|
||
}
|
||
}
|
||
|
||
// 上传完成后
|
||
function handleChange(info){
|
||
if(info && info.file && info.file.status === "done"){
|
||
getBase64(info.file.originFileObj, imageUrl =>
|
||
setImageUrl(imageUrl)
|
||
);
|
||
}
|
||
}
|
||
|
||
// 添加课题输入框
|
||
function addTaskApplyForm(){
|
||
setTaskCount(taskCount.concat([taskCount[taskCount.length-1]+1]));
|
||
}
|
||
|
||
// 删除课题报名
|
||
async function deleteTaskApply(index){
|
||
const delTaskId = getFieldValue(`taskId${index}`);
|
||
const res = delTaskId ? await findStudentTaskByTaskId({ taskId: delTaskId }) : "newTask";
|
||
if((res && res.data && res.data.length)){
|
||
message.error("已有学生报名,不允许删除");
|
||
}else{
|
||
const arr = taskCount.filter(item=>item!== index);
|
||
setTaskCount(arr);
|
||
}
|
||
}
|
||
|
||
// 取消编辑点击函数
|
||
function cancelEdit(){
|
||
if(isAddRepo){
|
||
// 新增项目信息
|
||
setIsAddRepo(false);
|
||
return
|
||
}
|
||
// 编辑项目信息
|
||
setIsEdit(false);
|
||
setEditRepoCount(0);
|
||
setTimeout(() => {
|
||
scrollToRepoInfo()
|
||
}, 100);
|
||
}
|
||
|
||
// 屏幕滚动到当前项目区域
|
||
function scrollToRepoInfo(){
|
||
const element = document.getElementById(`repoShowId${applyInfo.id}`);
|
||
window.scrollTo(0, element.offsetTop-100);
|
||
}
|
||
|
||
return(
|
||
<div className='applyInfoBox'>
|
||
<div className='titleG font-18 mb10' id="editRepoInfoId">项目信息</div>
|
||
{taskCount && <Form className="pt20 glcc_info_form" onSubmit={handleSubmit}>
|
||
{helper('项目名称',
|
||
'',
|
||
'projectName',
|
||
[{ required: true, message: "请输入项目名称,长度限制32个字符" },
|
||
{ max: 32, message: '超出限制长度32位字符,请重新编辑' }],
|
||
<Input placeholder="请输入项目名称,长度限制32个字符" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
{helper('项目分类',
|
||
'',
|
||
'projectType',
|
||
[{ required: true, message: "请选择项目分类" }],
|
||
<Select placeholder="请选择项目分类">
|
||
{cateList && cateList.map(item=> {return <Option value={item.name} key={item.id}>{item.name}</Option>})}
|
||
</Select>
|
||
)}
|
||
|
||
<div className='hasQuestionBox'>
|
||
{helper('GitLink地址',
|
||
'',
|
||
'gitlinkUrl',
|
||
[{ required: true, message: "请输入GitLink项目地址" },
|
||
{ max: 252, message: '超出限制长度252位字符,请重新编辑' }],
|
||
<Input placeholder="请输入GitLink项目地址" onBlur={()=>{verify("gitlink")}}/>
|
||
)}
|
||
<Tooltip title={<div>
|
||
指项目在GitLink的托管地址,详见<a href='https://forum.gitlink.org.cn/forums/10594/detail' target="_blank" style={{color: "#466aff"}}>迁移说明文档</a>
|
||
</div>}
|
||
>
|
||
<Icon type="question-circle" theme="filled" className="question mt15 ml10"/>
|
||
</Tooltip>
|
||
</div>
|
||
<Form.Item label="联系人姓名">
|
||
{getFieldDecorator("contactName", { rules: [{ required: true, message: "请输入项目联系人姓名" },
|
||
{ max: 32, message: '超出限制长度32位字符,请重新编辑' }], validateFirst: true, initialValue: current_user.username })(
|
||
<Input placeholder="请输入项目联系人姓名" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
</Form.Item>
|
||
<Form.Item label="联系人电话">
|
||
{getFieldDecorator("contactPhone", { rules: [{ required: true, message: "输入项目联系人手机号码" },
|
||
{ pattern: phonereg, message: "请输入正确的手机号码"},], validateFirst: true, initialValue: current_user.phone })(
|
||
<Input placeholder="输入项目联系人手机号码" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
</Form.Item>
|
||
<Form.Item label="联系人邮箱">
|
||
{getFieldDecorator("contactMail", { rules: [{ required: true, message: "输入项目联系人邮箱" },
|
||
{ pattern: emailreg, message: "请输入正确的邮箱地址"},], validateFirst: true, initialValue: current_user.email })(
|
||
<Input placeholder="输入项目联系人邮箱" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
</Form.Item>
|
||
{/* {helper('联系人姓名',
|
||
'',
|
||
'contactName',
|
||
[{ required: true, message: "请输入项目联系人姓名" },
|
||
{ max: 32, message: '超出限制长度32位字符,请重新编辑' }],
|
||
<Input placeholder="请输入项目联系人姓名" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
{helper('联系人电话',
|
||
'',
|
||
'contactPhone',
|
||
[{ required: true, message: "输入项目联系人手机号码" },
|
||
{ pattern: phonereg, message: "请输入正确的手机号码"},],
|
||
<Input placeholder="输入项目联系人手机号码" onBlur={()=>{verify("name")}}/>
|
||
)}
|
||
{helper('联系人邮箱',
|
||
'',
|
||
'contactMail',
|
||
[{ required: true, message: "输入项目联系人邮箱" },
|
||
{ pattern: emailreg, message: "请输入正确的邮箱地址"},],
|
||
<Input placeholder="输入项目联系人邮箱" onBlur={()=>{verify("name")}}/>
|
||
)} */}
|
||
<div className='introArea'>{helper('项目简介',
|
||
'',
|
||
'projectIntro',
|
||
[{ required: true, message: "请输入项目简介" },
|
||
{ max: 200, message: '超出限制长度200位字符,请重新编辑' }],
|
||
<TextArea placeholder="请输入项目简介" onBlur={()=>{verify("intro")}} rows={4}/>
|
||
)}</div>
|
||
<div className='introArea'>{helper('项目logo',
|
||
'限制上传格式为:png、jpg、jpeg,限制20M。建议上传大小为382*228',
|
||
'logo',
|
||
[{ required: true, message: "请正确上传项目logo" }],
|
||
<Upload
|
||
listType="picture-card"
|
||
className="avatar-uploader"
|
||
showUploadList={false}
|
||
action={getUploadActionUrl()}
|
||
accept=".png,.jpg,.jpeg"
|
||
beforeUpload={beforeUpload}
|
||
onChange={handleChange}
|
||
>
|
||
{(imageUrl || applyInfo) ? <img src={imageUrl || `${main_site_url}/api/attachments/${applyInfo && applyInfo.projectLogoId}`} alt="avatar" style={{ maxWidth: '100px', maxHeight: '100px' }} /> : <div>
|
||
<i className='iconfont icon-tianjiadaohang font-30'></i>
|
||
<div className="ant-upload-text font-13">请上传logo图片</div>
|
||
</div>}
|
||
</Upload>
|
||
)}</div>
|
||
<div className='introArea' style={{paddingLeft: '128px'}}>
|
||
<Form.Item>
|
||
{getFieldDecorator("joinCooperativeCommunity", { rules: [], validateFirst: true, valuePropName: "checked" })(
|
||
<Checkbox>授权将社区加入合作社区名单,项目logo可用于GLCC网站和海报宣传</Checkbox>
|
||
)}
|
||
</Form.Item>
|
||
</div>
|
||
{taskCount.map((item, index)=>{
|
||
return <div className='taskApplyBox' key={item}>
|
||
<FlexAJ className='taskApplyTitleBox'>
|
||
<div className='taskApplyTitle font-16'>课题信息(<span>{index+1}</span>/5)</div>
|
||
{index>0 && <Button type="link" onClick={()=>{deleteTaskApply(item)}}><i className='iconfont icon-shanchuicon3 mr5 font-15'></i>删除</Button>}
|
||
</FlexAJ>
|
||
<TaskApply helper={helper} taskKey={item} phonereg={phonereg} emailreg={emailreg} getFieldDecorator={getFieldDecorator} rewardList={rewardList} getFieldValue={getFieldValue} resetFields={resetFields}/>
|
||
</div>
|
||
})}
|
||
{taskCount && taskCount.length<5 && <div>
|
||
<Button type="primary" className='taskApplyBox' style={{width: "100px", height: "36px"}} onClick={addTaskApplyForm}>添加课题</Button>
|
||
</div>}
|
||
<Form.Item className='subInfo introArea'>
|
||
{(isAddRepo || applyInfo) && <Popconfirm
|
||
title={<span>取消将不保存所有修改,请谨慎操作</span>}
|
||
onConfirm={cancelEdit}
|
||
okText="确定"
|
||
cancelText="取消"
|
||
>
|
||
<Button className='mr20' style={{height: '36px', width: '110px'}}>取消</Button>
|
||
</Popconfirm>}
|
||
<Button type="primary" htmlType="submit" className='sub' loading={loading}>提交</Button>
|
||
</Form.Item>
|
||
</Form>}
|
||
</div>
|
||
)
|
||
}
|
||
export default Form.create()(EditRepoApplyInfo); |