forgeplus-react/src/glcc/apply/editInfo.jsx

349 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);