增加创客关注功能,注册增加领域,点赞状态切换

This commit is contained in:
何童崇 2022-10-13 16:39:22 +08:00
parent 816d6f609e
commit 769ebc00d3
17 changed files with 1596 additions and 1202 deletions

View File

@ -211,6 +211,12 @@ module.exports = {
{
loader: require.resolve("sass-loader"),
},
{
loader: 'sass-resources-loader',
options: {
resources: ['src/global.scss']
}
}
],
},
{

View File

@ -213,6 +213,12 @@ module.exports = {
{
loader: require.resolve("sass-loader"),
},
{
loader: 'sass-resources-loader',
options: {
resources: ['src/global.scss']
}
}
],
},
{

2370
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -216,6 +216,7 @@
"react-json-view": "^1.21.3",
"reqwest": "^2.0.5",
"resize-observer-polyfill": "^1.5.1",
"sass-resources-loader": "^2.2.5",
"terser-webpack-plugin": "^2.3.5",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.42.1",

5
src/global.scss Normal file
View File

@ -0,0 +1,5 @@
$primary-color: #466aff;
$primary-color-hover: #6684FE;
$primary-color-active: #1A47FF;
$link-color: #466aff;
$link-black-color: #05101a;

View File

@ -617,4 +617,29 @@ export function publishExpertsAndRules(taskId, containerType){
})
}
// 管理页面修改创业
// 关注创客
export function followTask(data) {
return fetch({
url: `/api/tasks/follow`,
method: 'post',
data: data,
});
}
// 取消关注创客
export function unfollowTask(data) {
return fetch({
url: `/api/tasks/unfollow`,
method: 'delete',
data: data,
});
}
// 关注创客列表
export function followTaskList(params) {
return fetch({
url: `/api/tasks/followList`,
method: 'get',
params,
});
}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback, useMemo } from 'react';
import React, { useEffect, useState, useCallback, useMemo, Fragment } from 'react';
import { Form, Modal, Input, Pagination, Radio, Table } from 'antd';
import { Link } from "react-router-dom";
import Nodata from 'forge/Nodata';
@ -6,7 +6,7 @@ import Loading from "src/Loading";
import Upload from 'military/components/Upload';
import ProofModal from '../proofModal';
import { publishModeArr, taskStatusAllArr, myPaperStatusArr } from '../../static';
import { signMethod, uploadAgreeRequire, downAgreement } from "../../api";
import { signMethod, uploadAgreeRequire, downAgreement, unfollowTask } from "../../api";
import { httpUrl } from '../../fetch';
import '../../index.scss';
import './index.scss';
@ -16,7 +16,7 @@ for (const item of taskStatusAllArr) {
statusArr[item.dicItemCode] = item.dicItemName;
}
export default Form.create()((props) => {
const { form, list, curPage, total, changePage, taskCategoryValueArr, loading, publish, showNotification, reloadList, joinTask } = props;
const { form, list, curPage, total, changePage, taskCategoryValueArr, loading, publish, showNotification, reloadList, joinTask,current_user } = props;
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [visibleProofs, setVisibleProofs] = useState(false);
@ -161,6 +161,18 @@ export default Form.create()((props) => {
window.open(httpUrl + '/busiAttachments/download/' + id);
}
function unfollow(id) {
unfollowTask({
userId: current_user.user_id,
watchableId: id,
watchableType: "MakerTask"
}).then(res => {
if (res.message == 'success') {
reloadList();
}
})
}
return (
<React.Fragment>
<ul className="df mt10 needs_condition_content_nav">
@ -181,6 +193,7 @@ export default Form.create()((props) => {
任务编号{item.number}
<i className="ml20 mr5 iconfont icon-shijian color-grey9 font-16"></i>
{item.createdAt}
</p>
<ul className="df">
<li key={1} className="mytask-title with35 edu-txt-left font-16 font-bd" >
@ -254,10 +267,11 @@ export default Form.create()((props) => {
{item.status === 7 && <a className="line_1 color-blue" onClick={() => { setDowloadTaskId(item.id); setVisibleDownload(true); }}>下载协议签订凭证</a>}
</React.Fragment>
}
{item.contactName ? '' : <a className="line_1 color-grey-9" onClick={()=>{unfollow(item.id)}}>取消关注 </a>}
</li>
</ul>
</div>

View File

@ -213,9 +213,9 @@ export default Form.create()((props) => {
<span className="fl"><span className="color-grey9">稿件状态</span>{item.read ? '雇主已浏览' : '雇主未浏览'}</span>
{
item.user.nickname !== "******" && <span className="fr">
{[4, 5].includes(detailStatus) && <a className="mr20" onClick={() => { setReportVisible(true); setCheckedItem(item) }}><i className="iconfont icon-jinggao font-15 mr3"></i>举报</a>}
{[4, 5].includes(detailStatus) && <a className="mr20" onClick={() => { setReportVisible(!reportVisible); setCheckedItem(item) }}><i className="iconfont icon-jinggao font-15 mr3"></i>举报</a>}
<a className="mr20" onClick={() => { commentEdit(item.id) }}><i className="iconfont icon-huifu1 font-15 mr3"></i>{item.comments ? item.comments.length : 0}</a>
<a onClick={() => { thumbUp(item.id) }}><i className="iconfont icon-dianzan11 font-16 mr3"></i>{item.thumbsUp}</a>
<a onClick={() => { thumbUp(item.id) }}><i className={`iconfont ${item.currentUserCanThumbsUp?'icon-morendianzan_icon':'icon-dianzan_icon'} font-16 mr3`}></i>{item.thumbsUp}</a>
</span>
}

View File

@ -66,3 +66,9 @@
}
}
}
.fileComments{
.icon-dianzan_icon{
color: $primary-color;
}
}

View File

@ -0,0 +1,113 @@
import React, { useCallback, useEffect, useState, useMemo } from 'react';
import { Tabs, Input, Table, Pagination, Modal, Button } from 'antd';
import { Link } from "react-router-dom";
import ChooseNav from '../../components/chooseNav';
import ItemListMyTask from '../components/itemListMyTask';
import AgreementModal from '../components/agreementModal';
import ComplainModal from '../components/complainModal';
import { applyStatusAllArr, paperCheckStatusArr, applyStatusArr, publishModeArr, taskStatusAllArr,} from '../static';
import { getJoinTaskList, followTaskList, confirmReceipt } from '../api';
import './index.scss';
const Search = Input.Search;
const publishStatusArr = taskStatusAllArr.slice(3, 9);
const statusArr = [];
for (const item of applyStatusAllArr) {
statusArr[item.dicItemCode] = item.dicItemName;
}
const paperCheckStatus = [];
for (const item of paperCheckStatusArr) {
paperCheckStatus[item.dicItemCode] = item.dicItemName;
}
export default ({ taskCategoryValueArr, showNotification,current_user }) => {
const [paperStatusString, setPaperStatusString] = useState('0,1,2,3,4');
const [taskStatusString, setTaskStatusString] = useState('3,4,5,6,7,8');
const [requirePaper, setRequirePaper] = useState('1');
const [searchInput, setSearchInput] = useState('');
const [curPage, setCurPage] = useState(1);
const [total, setTotal] = useState(0);
const [taskList, setTaskList] = useState([]);
const [loading, setLoading] = useState(false);
const [curPagePaper, setCurPagePaper] = useState(1);
const [totalPaper, setTotalPaper] = useState(0);
const [paperList, setPaperList] = useState([]);
const [checkedItem, setCheckedItem] = useState({});
const [complainVisible, setComplainVisible] = useState(false);
const [agreeVisible, setAgreeVisible] = useState(false);
const [reload, setReload] = useState(0);
useEffect(() => {
const params = {
searchInput,
curPage,
pageSize: 10,
};
setLoading(true);
followTaskList(params).then(res => {
if (res.message=="success") {
setTaskList(res.data.rows);
setTotal(res.data.total);
}
setLoading(false);
});
}, [ reload, searchInput, curPage]);
function confirmReceiptModal(paperId) {
Modal.confirm({
title: '确认收款',
content: '确认已经收到任务报酬',
onOk: () => {
confirmReceipt(paperId).then(res => {
if (res && res.message === "success") {
showNotification("您已确认收款!");
reloadList();
}
})
}
})
}
const reloadList = useCallback(() => {
setReload(Math.random());
}, [])
return (
<div className='follow-task'>
<div className='follow-task-head'>
<div >我关注的任务</div>
<Search
maxLength={20}
style={{ width: "300px" }}
placeholder="请输入任务名称关键字"
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
/>
</div>
<ItemListMyTask
list={taskList}
curPage={curPage}
total={total}
taskCategoryValueArr={taskCategoryValueArr}
changePage={(page) => { setCurPage(page) }}
loading={loading}
joinTask={true}
reloadList={reloadList}
current_user={current_user}
/>
</div>
)
}

View File

@ -3,6 +3,7 @@ import { Tabs, Input, } from 'antd';
import StatusNav from '../../components/statusNav';
import ItemListMyTask from '../components/itemListMyTask';
import JoinTask from './joinTask';
import FollowTask from './followTask';
import { taskStatusAllArr, } from '../static';
import { getTaskCategory, getMyTaskList } from '../api';
import './index.scss';
@ -146,7 +147,7 @@ export default ({ location, history, current_user, showNotification }) => {
<Search
maxLength={20}
style={{ width: "300px" }}
placeholder="请输入任务编号/任务名称关键字"
placeholder="请输入任务名称关键字"
onSearch={(value) => { setSearchInput(value); setCurPage(1) }}
/>
}
@ -211,6 +212,15 @@ export default ({ location, history, current_user, showNotification }) => {
/>
</TabPane>
<TabPane tab="我的关注" key="3">
<FollowTask
taskCategoryValueArr={taskCategoryValueArr}
showNotification={showNotification}
current_user={current_user}
/>
</TabPane>
</Tabs>
</div>

View File

@ -60,3 +60,15 @@
}
}
}
.follow-task{
background: #fff;
}
.follow-task-head{
display: flex;
justify-content: space-between;
padding:1rem 1.5rem;
font-size: 1rem;
border-bottom: 1px solid #e8e8e8;
margin-bottom: 1rem;
}

View File

@ -201,7 +201,7 @@ export default ({ taskCategoryValueArr, showNotification }) => {
<Search
maxLength={20}
style={{ width: "300px" }}
placeholder="请输入任务编号/任务名称关键字"
placeholder="请输入任务名称关键字"
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
/>
}

View File

@ -8,7 +8,7 @@ import Upload from '../../components/Upload';
import StatusNav from '../../components/statusNav';
import ItemListPaper from '../components/itemListPaper';
import ProofModal from '../components/proofModal';
import { getTaskDetail, getTaskCategory, getTaskPaper, makePublic, addPaper, getAgreement, agreement, checkAgreement, checkHavePaper, addExpertReview } from '../api';
import { getTaskDetail, getTaskCategory, getTaskPaper, makePublic, addPaper, getAgreement, agreement, checkAgreement, checkHavePaper, addExpertReview, followTask, unfollowTask } from '../api';
import { taskModeIdArr, applyStatusArr, applyStatusAllArr, agreementContent, paperCheckTextArr } from '../static';
import { httpUrl } from '../fetch';
import './index.scss';
@ -381,6 +381,30 @@ export default Form.create()(
return moment(new Date(makePublicAt).getTime() + makePublicDays * 24 * 3600 * 1000).format('YYYY-MM-DD HH:mm:ss');
}
function follow() {
followTask({
userId: current_user.user_id,
watchableId: id,
watchableType: "MakerTask"
}).then(res => {
if (res.message == 'success') {
setReload(Math.random());
}
})
}
function unfollow() {
unfollowTask({
userId: current_user.user_id,
watchableId: id,
watchableType: "MakerTask"
}).then(res => {
if (res.message == 'success') {
setReload(Math.random());
}
})
}
return (
<div className="centerbox task-detail">
<div className="head-navigation">
@ -398,19 +422,35 @@ export default Form.create()(
<p className="lineh-20 mt10 edu-txt-center">{detailData && detailData.user && (detailData.user.nickname || detailData.user.login)}</p>
</div>
<div className="flex1">
<ul className="clearfix mb20">
<li className="font-18 mr20 font-bd task-hide lineh-20 fl" style={{ maxWidth: "800px" }}>{detailData.name}</li>
<div className="task-title mb10">
<span>
<span className="font-18 mr20 font-bd task-tit-text fl" >{detailData.name}</span>
<span className="task_tag">{taskCategoryValueArr[detailData.categoryId]}</span>
</ul>
<div className="clearfix">
</span>
<span className='detail_tag_btn '>
{
detailData.canFollow ? <span className='detail_tag_btn_name' onClick={follow}>
<i className="iconfont icon-kongxing font-16 mr3"></i>
关注
</span> : <span className='detail_tag_btn_name' onClick={unfollow}>
<i className="iconfont icon-shixing color-orange font-16 mr3"></i>
取消关注
</span>
}
<span className="detail_tag_btn_count">{detailData.followCount}</span>
</span>
</div>
<div className="clearfix flex1">
<ul className="fl">
<li><span className="mr10 color-grey9">悬赏模式</span><span className="color-grey3">{taskModeNameArr[detailData.taskModeId]}</span></li>
<li><span className="mr10 color-grey9">任务编号</span><span className="color-grey3">{detailData.number}</span></li>
<li><span className="mr10 color-grey9">发布时间</span><span className="color-grey3">{detailData.publishedAt || detailData.createdAt}</span></li>
</ul>
<ul className="fr edu-txt-right">
<li className="color-orange font-bd lineh-30"><span className="font-18"></span><span className="font-28">{detailData.bounty}</span></li>
</ul>
<div className="fr edu-txt-right mt10">
<div className="color-orange font-bd lineh-30"><span className="font-18"></span><span className="font-28">{detailData.bounty}</span></div>
</div>
</div>
</div>
</div>

View File

@ -10,19 +10,65 @@
}
}
}
.task-tit-text{
line-height: 1.4;
max-width: 800px;
}
.detail_tag_btn{
height:32px;
line-height: 32px;
border-radius:5px;
border:1px solid #D0D0D0;
display: flex;
align-items: center;
margin-left: 10px;
padding:0px;
background-color:#FAFBFC;
box-shadow: none;
.detail_tag_btn_name{
padding:0px 10px;
text-align: center;
height: 30px;
line-height: 30px;
border-radius:5px 0px 0px 5px;
&:hover
{
background-color: #F3F4F6;
}
span{
color: #333!important;
}
}
.detail_tag_btn_count{
width: 42px;
text-align: center;
background: #fff;
border-radius: 0px 4px 4px 0px;
height:100%;
border-left: 1px solid #D0D0D0;
}
}
}
.head-navigation {
position: absolute;
top: -2.3em;
}
.task-title{
display: flex;
justify-content: space-between;
}
.task_tag {
padding: 0px 12px;
padding: .2rem .75rem;
background: #f1f8ff;
border-radius: 4px;
float: left;
color: #4154f1;
height: 1.25rem;
line-height: 1.25rem;
}

View File

@ -86,13 +86,15 @@
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1vh;
&>span:first-child{
font-size: 1.5em;
font-weight: 600;
color: #000000;
line-height: 1.5;
}
.link_span{
margin-bottom: 1vh;
}
//注册页面的获取验证码输入框
// .ant-input{width: 18rem; }
}
@ -140,6 +142,8 @@
font-size: 0.9em;
}
.message, .ant-form-explain{
position: absolute;
bottom: -1.45em;
color: #D40000;
font-size: 13px;
}
@ -157,14 +161,11 @@
.ant-select-selection__rendered{
line-height: 3em;
}
.ant-form-explain{
margin-top: 0.5vh;
margin-bottom: -10px;
}
//输入框
.ant-form-item{
margin-bottom: 15px;
margin-bottom: 16px;
}
//取消antd表单默认样式
.has-error .ant-input{
@ -249,9 +250,9 @@
.logoimgbox{
text-align: center;
.logoimg{
width: 150px;
width: 100px;
max-width: 30vw;
margin-bottom: 2vh;
margin-bottom: 1vh;
}
}
/*当页面宽度小于786px*/
@ -277,12 +278,11 @@
@media screen and (max-width:375px) {
.login_register_right .right_cont{
font-size: 13px;
padding:5vh 15px
padding:5vh 15px;
height: 100vh;
}
.logoimgbox{
.logoimg{
margin-bottom: 0;
}
display: none;
}
}
@media screen and (max-width:360px) {
@ -290,8 +290,8 @@
font-size: 12px;
padding:5vh 10px
}
.logoimgbox{
display: none;
.login_register_right{
overflow-y: scroll;
}
}

View File

@ -25,6 +25,7 @@ function Register(props) {
//
const inputEl = useRef(null);
//
function handleSubmit() {
validateFields((err, values) => {
@ -34,6 +35,7 @@ function Register(props) {
password: values.register_psd,
company_name: values.company_name,
user_type: values.user_type,
professional_field:values.professional_field,
code: values.captcha
}).then((response) => {
if (response.data && response.data.status === -6) {
@ -62,7 +64,7 @@ function Register(props) {
type: 1
}
}).then(response => {
if (response.data.status === -2) {
if (response&&response.data&&response.data.status === -2) {
setGetCaptchaBut(false);
setMess(response.data.message);
callback('该手机已被注册');
@ -176,7 +178,8 @@ function Register(props) {
clear();
}, [])
const settings=JSON.parse(localStorage.getItem('chromesetting'));
const settings=localStorage.getItem('chromesetting')?JSON.parse(localStorage.getItem('chromesetting')):{};
let professional_field=settings.professional_field||[];
return (
<div className="right_cont Register_content">
@ -281,6 +284,25 @@ function Register(props) {
</Select>)}
</Form.Item>
<Form.Item label={"专业领域"} className="inline_input">
{getFieldDecorator('professional_field', {
rules: [
{
required: true,
message: "请选择专业领域"
},
],
validateTrigger: "onBlur",
validateFirst: true,
})(<Select placeholder="请选择专业领域" >
{
professional_field.map(i=>{
return <Option value={i.value}>{i.name}</Option>
})
}
</Select>)}
</Form.Item>
<Form.Item className="register_last_form">
{getFieldDecorator('agreement', {