forgeplus-react/src/military/task/taskEdit/index.jsx

601 lines
22 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, { forwardRef, useCallback, useEffect, useState } from 'react';
import { Form, Radio, Input, InputNumber, Icon, Button, Modal, Checkbox } from 'antd';
import classNames from 'classnames';
import moment from 'moment';
import ReactWEditor from 'wangeditor-for-react';
import { Link } from "react-router-dom";
import Upload from '../../components/Upload';
import { httpUrl } from '../fetch';
import { getTaskDetail, addTask, updateTask, updatePublishedTask, getTaskCategory, getCompanyInfo } from '../api';
import { formItemLayout, formModalLayout } from '../static';
import { editorConfig } from '../../components/config';
import CodeModal from './codeModal';
import './index.scss';
import { Confirm } from '../../components/ModalFun';
const { info } = Modal;
export default Form.create()(forwardRef(({ current_user, form, showNotification, match, history }, ref) => {
const [taskCategoryArr, setTaskCategoryArr] = useState([]);
const [fileList, setFileList] = useState(null);
const [publishMode, setPublishMode] = useState('0'); //发布方式
const [categoryId, setCategoryId] = useState('7'); //所在领域
const [descriptionHtml, setDescriptionHtml] = useState(''); //详情的富文本
const [enterpriseName, setEnterpriseName] = useState(''); //主体信息
const [displayTime, setDisplayTime] = useState(() => {
return {
collectingTime: getSomeDayAfter(30),
choosingTime: getSomeDayAfter(30 + 15),
makePublicTime: getSomeDayAfter(30 + 15 + 7),
signingTime: getSomeDayAfter(30 + 15 + 7 + 15),
payingTime: getSomeDayAfter(30 + 15 + 7 + 15 + 15)
}
}); //节点时间
const [visible, setVisible] = useState(false);
const [num, setNum] = useState(0) // 倒计时
const [isSend, setIsSend] = useState(false) // 是否发送验证码
const [published, setPublished] = useState(false); //是否已发布
const [status, setStatus] = useState(0); //任务当前状态
const [publishedAt, setPublishedAt] = useState();
const id = match.params.taskId;
const { getFieldDecorator, validateFields, setFieldsValue, getFieldsValue } = form;
// 根据是否传id判断是新增还是修改根据状态判定是否是发布后的修改
useEffect(() => {
if (id) {
getTaskDetail(id).then(data => {
console.log('data');
console.log(data.status);
// 如果发布了, 且用户不是管理员,那么返回之前的页面
if (data.status > 2 && !(current_user && current_user.admin)) {
history.go(-1);
}
if (data.status > 2) {
setPublished(true);
setStatus(data.status);
setPublishedAt(data.publishedAt || data.createdAt)
}else{
// 只有发布之前,才能更新发布人
CompanyInfo();
}
let formValue = {
name: data.name,
contactName: data.contactName,
contactPhone: data.contactPhone,
uploadFileNumbers: data.uploadFileNumbers,
bounty: data.bounty,
taskModeId: data.taskModeId,
collectionMode: data.collectionMode,
publishMode: data.publishMode + '',
description: data.description,
collectingDays: data.collectingDays,
choosingDays: data.choosingDays,
makePublicDays: data.makePublicDays,
signingDays: data.signingDays,
payingDays: data.payingDays,
expertReview: data.expertReview
};
if (data.tasksAttachments && data.tasksAttachments.length) {
for (const item of data.tasksAttachments) {
item.name = item.fileName;
item.size = item.fileSize;
item.uid = "rc-upload" + item.id
}
setFileList(data.tasksAttachments);
}
setFieldsValue(formValue);
setEnterpriseName(data.enterpriseName);
setCategoryId(data.categoryId);
setDescriptionHtml(data.description);
setPublishMode(data.publishMode + '');
let publishedAt = (data.publishedAt || data.createdAt);
let collectingTime = getSomeDayAfter(data.collectingDays, publishedAt);
let choosingTime = getSomeDayAfter(data.collectingDays + data.choosingDays, publishedAt);
let makePublicTime = getSomeDayAfter(data.collectingDays + data.choosingDays + data.makePublicDays, publishedAt);
let signingTime = getSomeDayAfter(data.collectingDays + data.choosingDays + data.makePublicDays + data.signingDays, publishedAt);
let payingTime = getSomeDayAfter(data.collectingDays + data.choosingDays + data.makePublicDays + data.signingDays + data.payingDays, publishedAt);
setDisplayTime({ collectingTime, choosingTime, makePublicTime, signingTime, payingTime });
});
} else {
let formValue = {
contactName: current_user.username || current_user.login,
contactPhone: current_user.contactPhone,
taskModeId: 1,
collectionMode: 1,
publishMode: '0',
collectingDays: 30,
choosingDays: 15,
makePublicDays: 7,
signingDays: 15,
payingDays: 15,
};
setFieldsValue(formValue);
setCategoryId('7');
CompanyInfo();
}
}, [id]);
function CompanyInfo(){
getCompanyInfo().then(res => {
if (res && res.message === 'success') {
setEnterpriseName(res.data.enterpriseName);
setFieldsValue({
contactPhone: res.data.phone,
contactName: res.data.userName,
})
} else {
showNotification(res.message);
}
});
}
useEffect(() => {
getTaskCategory().then(data => {
if (data) {
for (const item of data) {
item.dicItemCode = item.id;
item.dicItemName = item.name;
}
setTaskCategoryArr(data);
}
});
}, []);
/** 倒计时显示*/
useEffect(() => {
let timer = 0;
if (isSend && num !== 0) {
timer = setInterval(() => {
setNum(n => {
if (n === 1) {
setIsSend(false)
clearInterval(timer)
}
return n - 1;
});
}, 1000);
}
return () => {
// 组件销毁时,清除定时器
clearInterval(timer)
};
}, [isSend]);
// 计算发布以后多久
function getSomeDayAfter(nDay, publishedAt) {
return publishedAt ? moment(new Date(publishedAt).setDate((publishedAt ? new Date(publishedAt) : new Date()).getDate() + nDay)).format('YYYY-MM-DD HH:mm') :
moment(new Date().setDate(new Date().getDate() + nDay)).format('YYYY-MM-DD HH:mm');
}
// 上传附件后得到的文件数组
function UploadFunc(fileList) {
setFileList(fileList);
let files = [];
for (const item of fileList) {
if (item) {
let itemId = (item.response && item.response.data && item.response.data.id) || item.id;
itemId && files.push(itemId);
}
}
setFieldsValue({
uploadFileNumbers: files.join()
});
}
const helper = useCallback(
(label, name, rules, widget, initialValue, rightComponent) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
{rightComponent}
</Form.Item>
), []);
const helperNoLabel = useCallback(
(title, name, rules, widget, displayTime) => {
let active = (status == 3 && title == '成果提交') || (status == 4 && title == '成果评选') || (status == 5 && title == '结果公示') || (status == 6 && title == '任务协议签订');
return (
<div className="timing_task" key={name}>
<div className="mbt10 color-grey-9 lineh-35"><span className={`inline-span ${active ? 'active' : ''}`}>{title}</span></div>
<Form.Item className="no-label">
{getFieldDecorator(name, { rules, validateFirst: true, })(widget)}
</Form.Item>
<span className="days-word color-grey-9 "></span>
{publishMode == '0' && <p className="display-time">{displayTime}</p>}
</div>
)
}, [publishMode, status]);
// 新增或者修改后的处理函数
const publishDeal = useCallback((status, publishMode, res) => {
if (res && res.data) {
if (!status) {
history.push("/task/myTask?published=false");
showNotification("任务保存成功!");
} else if (current_user.admin && status>2) {
history.push(`/task/taskDetail/${id}`);
showNotification("任务修改成功!");
} else if (current_user.admin) {
history.push("/task");
showNotification("任务发布成功!");
} else {
info({
title: '提示',
content: <div>
<h4>发布申请已提交请等待管理员的审核</h4>
<p>我们将在1-2个工作日内完成审核</p>
</div>,
onOk() {
history.push("/task/myTask?published=false");
},
});
}
} else {
showNotification(res.message);
}
}, []);
// 发布/保存
function saveItem(status) {
validateFields((error, values) => {
if (!error) {
let params = {
...values,
status,
enterpriseName: enterpriseName,
categoryId,
};
params.expertReview=Boolean(params.expertReview);
let dateSum = params.collectingDays + params.choosingDays + params.makePublicDays + params.signingDays + params.payingDays;
if (dateSum > 180) {
showNotification("任务天数总和不得超过180天");
return;
}
if (status > 2) {
updatePublishedTask({
id: id,
bounty: values.bounty,
choosingDays: values.choosingDays,
collectingDays: values.collectingDays,
currentUserId: current_user.user_id,
description: values.description,
makePublicDays: values.makePublicDays,
name: values.name,
payingDays: values.payingDays,
signingDays: values.signingDays,
uploadFileNumbers:values.uploadFileNumbers
}).then(res => {
publishDeal(status, publishMode, res);
});
} else if (id) {
// 编辑
params.id = id;
updateTask(params).then(res => {
publishDeal(status, publishMode, res);
});
} else {
// 新增
addTask(params).then(res => {
publishDeal(status, publishMode, res);
});
}
}
})
}
function changeDate(v, field) {
if (typeof v !== 'number' || v < 0) {
return;
}
let values = getFieldsValue();
values[field] = v;
let collectingTime = getSomeDayAfter(values.collectingDays, publishedAt);
let choosingTime = getSomeDayAfter(values.collectingDays + values.choosingDays, publishedAt);
let makePublicTime = getSomeDayAfter(values.collectingDays + values.choosingDays + values.makePublicDays, publishedAt);
let signingTime = getSomeDayAfter(values.collectingDays + values.choosingDays + values.makePublicDays + values.signingDays, publishedAt);
let payingTime = getSomeDayAfter(values.collectingDays + values.choosingDays + values.makePublicDays + values.signingDays + values.payingDays, publishedAt);
setDisplayTime({ collectingTime, choosingTime, makePublicTime, signingTime, payingTime });
}
function changeContactPhone(e) {
console.log(e);
setFieldsValue({
contactPhone: e
})
}
function editPublished() {
Confirm({
title: '提醒',
content: <div>
<p>确认更改该创客任务内容</p>
</div>,
onOk: () => {
saveItem(status)
},
onCancel:()=>{
history.push(`/task/taskDetail/${id}`);
}
});
}
return (
<div className="centerbox">
<div className="head-navigation">
<Link to="/task">创客空间 &gt;</Link>
<Link to="/task">任务大厅 &gt;</Link>
<span >需求提报 </span>
</div>
<p className="font-18 font-bd mb15">任务提交</p>
<div className="edu-back-white mb30">
<div className="padding30 bor-bottom-greyE">
<p className="partTitle">联系方式<span className="color-red font-14">*必填</span></p>
<Form {...formItemLayout}>
<Form.Item label='主体信息:'>
{enterpriseName}
</Form.Item>
{helper(
"联系人:",
"contactName",
[{ required: true, message: "请输入联系人" }],
<Input
disabled={published}
className="contact-input"
placeholder="请输入联系人"
/>
)}
{helper(
"联系电话:",
"contactPhone",
[{ required: true, message: "请输入联系电话" }],
<Input
className="contact-input"
placeholder="请输入联系电话"
disabled
/>, '', <Icon className="editPhone" type="edit" onClick={() => { setVisible(true) }} />
)}
</Form>
</div>
<div className="padding30 bor-bottom-greyE">
<p className="partTitle">任务内容<span className="color-red font-14">*必填</span></p>
<div className="pl15 task-edit-content">
<p className="color-grey3 mb20">选择任务所在领域</p>
<div className="mb20 clearfix areaDiv" >
{
taskCategoryArr.map(item => {
return <button
className={classNames({ "choose-button": true, "active": item.dicItemCode == categoryId })}
key={item.dicItemCode}
onClick={() => { setCategoryId(item.dicItemCode) }}
>{item.dicItemName}</button>
})
}
</div>
{helper(
"",
"name",
[{ required: true, message: "请用一句话概括您要做什么比如开源项目网站开发最大限制200个字符" },
{ max: 200, message: '长度不能超过200个字符' }],
<Input
placeholder="请用一句话概括您要做什么比如开源项目网站开发最大限制200个字符"
/>
)}
<Form.Item >
{(!id || (id && descriptionHtml)) && <ReactWEditor
defaultValue={descriptionHtml}
config={{
...editorConfig,
placeholder: "把您的任务内容补充详细一些吧,越清晰具体,任务完成质量越高哟~",
}}
onChange={(html) => { setFieldsValue({ description: html }) }}
/>}
{/* 用一个隐藏的input实现上必填校验 */}
{getFieldDecorator('description', {
rules: [{ required: true, message: "把您的任务内容补充详细一些吧,越清晰具体,任务完成质量越高哟~" }],
validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
<p className="color-grey3 mb10 mt20">
<span className="color-orange mr2 ">*</span>
任务发布之后将会公开展示在交易中心不要把与项目客户相关等隐私信息以及QQ号微信号电话号码等联系方式填写在任务中
</p>
<Form.Item >
{getFieldDecorator('expertReview', {
validateFirst: true,
defaultValue:false,
valuePropName:"checked"
})(<Checkbox className="color-grey-3" disabled={published}>是否增加专家评审流程添加后可联系管理员发布此专家评审任务</Checkbox>)}
</Form.Item>
<Form.Item >
<Upload
className="commentStyle"
load={UploadFunc}
size={150}
showNotification={showNotification}
actionUrl={httpUrl}
fileList={fileList}
/>
{getFieldDecorator('uploadFileNumbers', {
validateFirst: true
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
</div>
</div>
<div className="padding30 ">
<p className="partTitle">选择任务周期价格和发布模式<span className="color-red font-14">*必填</span></p>
<Form className="gray-form" {...formItemLayout}>
{helper(
"赏金:",
"bounty",
[{ required: true, message: "您打算支付多少赏金呢" }],
<InputNumber
min={1}
max={99999999}
className="number-input"
placeholder="您打算支付多少赏金呢"
formatter={value => `${value}¥`}
/>
)}
{helper(
"悬赏模式:",
"taskModeId",
[{ required: true, message: "请选择悬赏模式" }],
<Radio.Group disabled={published}>
<Radio value={1}>单人悬赏只设置一个中标者</Radio>
<Radio value={2}>多人悬赏设置多分中标分享赏金</Radio>
<Radio value={3}>计件悬赏合格一稿支付一稿稿件数量2</Radio>
</Radio.Group>
)}
{helper(
"征集方式:",
"collectionMode",
[{ required: true, message: "请选择征集方式" }],
<Radio.Group disabled={published}>
<Radio value={1}>创意征集应征者以开放讨论的形式参与</Radio>
<Radio value={0}>物化成果征集应征者以各自提交成果物的形式参与</Radio>
</Radio.Group>
)}
{helper(
"发布方式:",
"publishMode",
[{ required: true, message: "请选择发布方式" }],
<Radio.Group disabled={published} onChange={(e) => { setPublishMode(e.target.value) }}>
<Radio value={'0'}>自主提交方式由发布方自行支付赏金一键自助发布</Radio>
<Radio value={'1'}>统筹任务由平台支付赏金需经过平台遴选方能发布</Radio>
</Radio.Group>
)}
<div className="task-setting-days">
<div className="timing_task">
<div className="mbt10 color-grey-9 lineh-35"><span className="inline-span active">需求提报</span></div>
<div className="color-grey-9 ">自主提交立即发布</div>
<div className="color-grey-9 ">统筹任务遴选后发布</div>
</div>
{helperNoLabel(
"成果提交",
"collectingDays",
[{ required: true, message: "请输入天数" }],
<InputNumber
className="date-input"
onChange={(v) => { changeDate(v, 'collectingDays') }}
min={1}
max={180}
disabled={status > 2}
/>,
displayTime.collectingTime
)}
{/* <div className="color-grey-9 format-time-days-1 format-time-day-show">2021-06-16 07:10</div> */}
{/* <div className="days-error"><span className="color-red none">成果提交时间不能为空</span></div> */}
{helperNoLabel(
"成果评选",
"choosingDays",
[{ required: true, message: "请输入天数" }],
<InputNumber
className="date-input"
onChange={(v) => { changeDate(v, 'choosingDays') }}
min={1}
max={180}
disabled={status > 3}
/>,
displayTime.choosingTime
)}
{helperNoLabel(
"结果公示",
"makePublicDays",
[{ required: true, message: "请输入天数" }],
<InputNumber
className="date-input"
onChange={(v) => { changeDate(v, 'makePublicDays') }}
min={1}
max={180}
disabled={status > 4}
/>,
displayTime.makePublicTime
)}
{helperNoLabel(
"任务协议签订",
"signingDays",
[{ required: true, message: "请输入天数" }],
<InputNumber
className="date-input"
onChange={(v) => { changeDate(v, 'signingDays') }}
min={1}
max={180}
/>,
displayTime.signingTime
)}
{helperNoLabel(
"支付",
"payingDays",
[{ required: true, message: "请输入天数" }],
<InputNumber
className="date-input"
onChange={(v) => { changeDate(v, 'payingDays') }}
min={1}
max={180}
/>,
displayTime.payingTime
)}
<div className="timing_task">
<div className="mbt10 color-grey-9 lineh-35"><span className="inline-span">任务完成</span></div>
<div className="color-grey-9 ">支付确认后任务完成</div>
</div>
</div>
<p className="color-grey3 mb10 ml40 mt20">
<span className="color-orange mr2 ">*</span>
任务天数总和不得超过180天
</p>
</Form>
</div>
</div>
{
published ? <Button className="mr20" type={"primary"} onClick={editPublished}>确认修改</Button> : <div>
<Button className="mr20" type={"primary"} onClick={() => { saveItem(1) }}>发布</Button>
<Button className="mr20" type={"primary"} onClick={() => { saveItem(0) }}>保存</Button>
<Button onClick={() => { history.go(-1) }}>取消</Button>
</div>
}
<CodeModal visible={visible} setVisible={setVisible} changeContactPhone={changeContactPhone} />
</div>
)
})
)