Merge pull request 'issue改版2稿+用户反馈问题' (#514) from durian/forgeplus-react:gitlink_server_issue into gitlink_server_issue

This commit is contained in:
caishi 2023-03-07 09:28:54 +08:00
commit fd1e2fa668
8 changed files with 273 additions and 166 deletions

View File

@ -12,7 +12,7 @@ import axios from 'axios';
function EditComment(props){
const {owner, projectsId, index} = props.match.params;
const {current_user, current_user:{login}, showLoginDialog, showNotification, reloadComment, cancelMd, parentId, replyId, updateId} = props;
const {current_user, current_user:{login}, showLoginDialog, showNotification, reloadComment, cancelMd, parentId, replyId, updateId, showUserImg=true} = props;
const [content, setContent] = useState(props.content);
const [quillFlag, setQuillFlag] = useState(false);
// loading
@ -80,6 +80,7 @@ function EditComment(props){
alt=""
width="30"
height="30"
style={{display: showUserImg ? '' : 'none'}}
/>
</Link>
<div style={{position:"relative"}}>

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { Button, Popconfirm, Radio, Input, message, Tooltip } from 'antd';
import { Button, Popconfirm, Radio, Input, message, Tooltip, Spin } from 'antd';
import axios from 'axios';
import { getImageUrl, timeAgo } from 'educoder';
import RenderHtml from '../../../../components/render-html';
@ -13,7 +13,7 @@ import { Link } from 'react-router-dom';
function IssueCommentList(props){
const{history, history: {location}, reload, reloadComment, showNotification, current_user:{login, admin, image_url, user_id}, isManager, showLoginDialog, issueInfo:{author}} = props;
const {owner, projectsId, index} = props.match.params;
const [category, setCategory] = useState('all');
const [category, setCategory] = useState('comment');
const [journals, setJournals] = useState(undefined);
// /markdown1 2 3 4 5
const [showEdit, setShowEdit] = useState(false);
@ -23,6 +23,10 @@ function IssueCommentList(props){
const [updateId, setUpdateId] = useState(undefined);
//
const [open, setOpen] = useState(undefined);
// css 线
const [spin, setSpin] = useState(false);
// issue
const [journalsCount, setJournalsCount] = useState(undefined);
// icon
const journalsIcon ={
'issue': 'icon-chuangjianqianbao',
@ -40,11 +44,12 @@ function IssueCommentList(props){
}
useEffect(()=>{
setSpin(true);
axios.get(`/v1/${owner}/${projectsId}/issues/${index}/journals`,{params:{
category
}}).then(res=>{
if(res && res.data){
const {journals} = res.data;
const {journals, total_comment_journals_count} = res.data;
if(category === 'all'){
const array = [];
let start = undefined;
@ -69,13 +74,15 @@ function IssueCommentList(props){
}
})
}
setJournalsCount(total_comment_journals_count);
setJournals(journals);
setSpin(false)
}
})
}, [reload, category])
function commentCtx(v){
return <RenderHtml className="break_word_comments imageLayerParent" value={v} url={location}/>;
return <RenderHtml className="break_word_comments imageLayerParent commentRenderHtml" value={v} url={location}/>;
};
//
@ -95,121 +102,126 @@ function IssueCommentList(props){
return(
<div className="commentListBox">
{/* 全部 / 评论 / 操作日志 */}
<div className='typeActionBox mt30 mb20'>
<Radio.Group onChange={(e)=>{setSpin(true);setCategory(e.target.value)}} value={category}>
<Radio value={'comment'} className='typeActionRadio font-14'>评论<span className='journalsCount font-13 ml5'>{journalsCount}</span></Radio>
<Radio value={'operate'} className='typeActionRadio font-14'>操作日志</Radio>
<Radio value={'all'} className='typeActionRadio font-14'>全部</Radio>
</Radio.Group>
</div>
{/* 添加评论 */}
<div className="pt20 pb30">
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addcomments">
{category !== 'operate' && <div className="pt5 pb25">
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addComments">
<img src={getImageUrl(image_url)} alt="" />
<div style={{flex:1}}>
<CheckProfile {...props} sureFunc={()=>{setShowEdit(1)}}>
<Input placeholder="添加评论" style={{width:"100%",height:"36px"}}/>
<Input className='addCommentBox' placeholder="添加评论"/>
</CheckProfile>
</div>
</div> : <div className='unLoginComment font-15 pl20'>
{/* 未登录用户 */}
<a className='mr5 loginBtn' onClick={()=>{showLoginDialog()}}>登录</a>并参与评论与回复
</div>}
</div>
{/* 全部 / 评论 / 操作日志 */}
<div className='typeActionBox mb20'>
<Radio.Group onChange={(e)=>{setCategory(e.target.value)}} value={category}>
<Radio value={'all'} className='typeActionRadio font-16'>全部</Radio>
<Radio value={'comment'} className='typeActionRadio font-16'>评论</Radio>
<Radio value={'operate'} className='typeActionRadio font-16'>操作日志</Radio>
</Radio.Group>
</div>
</div>}
{/* 评论/操作日志 展示列表 */}
<div className='commentsBox'>
{journals && (journals.length > 0 && journals.map(item=>{return item.is_journal_detail ? (!item.closeAndSpan || item.id === item.start || open === item.start) ? <div key={item.id} className='operationLog'>
{/* 操作日志 */}
<div className='operationLogTopBor'></div>
<div className='flexCenter font-15'>
<div className='flexCenter'>
<span className='iconBackBox mr10'><i className={`iconfont font-12 ${journalsIcon[item.operate_category]}`}></i></span>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr5'/></Link>
<Link to={`/${item.user.login}`}>{item.user.name}&nbsp;</Link>
<Tooltip title={<div><span>{item.user.name} </span><span dangerouslySetInnerHTML={{__html:item.operate_content}}></span></div>}><span className='task-hide' dangerouslySetInnerHTML={{__html:item.operate_content}} style={{maxWidth: '450px'}}></span></Tooltip>
<span className='ml15 timeAgo'>{timeAgo(item.created_at)}</span>
</div>
{(item.closeAndSpan && item.id === item.start) && <a className='primaryColor' onClick={()=>{setOpen(open === item.id ? undefined : item.id)}}>{open === item.id ? `点击收起操作日志` : `已折叠${item.numCount}条, 点击查看`}</a>}
</div>
<div className='operationLogBottomBor'></div>
</div> : '' : <div key={item.id} className='commentContentBox'>
{/* 评论 */}
{/* 判断是否是编辑状态 */}
{(showEdit === 2 && updateId === item.id) ? <div className='mt15 mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={item.notes} defaultFileList={item.attachments}/></div> : <div>
<div className='issueCommentTopBor'></div>
<div className='commentContent'>
<div className='flexCenter mt15 font-15'>
<div>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr8'/></Link>
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
<span className='ml15 timeAgo'>{timeAgo(item.created_at)}</span>
<Spin spinning={spin}>
<div className={`issueCommentsBox ${category === 'comment' && !spin && 'justComment'}`}>
{journals && (journals.length > 0 && journals.map(item=>{return item.is_journal_detail ? (!item.closeAndSpan || item.id === item.start || open === item.start) ? <div key={item.id} className='operationLog'>
{/* 操作日志 */}
<div className='operationCommentBor'></div>
<div className='flexCenter font-13' style={{flex: 1}}>
<div className='flexCenter opBox'>
<span className='iconBackBox mr10'><i className={`iconfont font-12 ${journalsIcon[item.operate_category]}`}></i></span>
<div className='task-hide' style={{flex: '1'}}>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr5'/></Link>
<Link to={`/${item.user.login}`}>{item.user.name}&nbsp;</Link>
{(item.user.name.length + item.operate_content.length) > 62 ? <Tooltip title={<div><span>{item.user.name} </span><span dangerouslySetInnerHTML={{__html:item.operate_content}}></span></div>}><span dangerouslySetInnerHTML={{__html:item.operate_content}}></span></Tooltip> : <span dangerouslySetInnerHTML={{__html:item.operate_content}}></span>}
</div>
{login && <div>
{/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
{(admin || isManager || login === item.user.login || user_id === author.id) && <Popconfirm
placement="bottom"
title={`确定要删除此条评论吗?${item.children_journals.length > 0 ? '子评论也将被一起删除。' : ''}`}
okText="是"
cancelText="否"
onConfirm={() => deleteComment(item.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-fuzhi-shanchu font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅评论者可修改 */}
{login === item.user.login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(item.id); setShowEdit(2)}}><i className='iconfont icon-a-bianji12 font-13 mr8'></i>修改</Button>}
<CheckProfile {...props} sureFunc={()=>{setParentId(item.id); setReplyId(item.id); setShowEdit(3)}}><Button type='link' className='color-grey-89'><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button></CheckProfile>
</div>}
<span className='ml15 timeAgo font-12'>{timeAgo(item.created_at)}</span>
</div>
<div className='contentHtml mb15 mt5'>{commentCtx(item.notes)}</div>
{item && item.attachments && item.attachments.length > 0 && <div className='attachmentBox'><Attachment
attachments={item.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
{(item.closeAndSpan && item.id === item.start) && <a className='primaryColor' onClick={()=>{setOpen(open === item.id ? undefined : item.id)}}>{open === item.id ? `点击收起操作日志` : `已折叠${item.numCount}条, 点击查看`}<i className={`iconfont ${open === item.id ? `icon-sanjiaoxing-up` : 'icon-sanjiaoxing-down'} font-15`}></i></a>}
</div>
</div>}
{showEdit === 3 && replyId === item.id && <div className='contentHtml mr20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
{/* 评论回复部分 */}
{item.children_journals.map(i =>{return <div className='commentReply' key={i.id}>
{(showEdit === 4 && updateId === i.id) ? <div className='mt15 mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={i.notes} defaultFileList={i.attachments}/></div> : <div>
<div className='flexCenter'>
<div>
<Link to={`/${i.user.login}`}><img src={getImageUrl(i.user.image_url)} alt="" className='commentUserImg mr8'/></Link>
<Link to={`/${i.user.login}`}>{i.user.name}</Link>
<span className='ml5 timeAgo mr3'>回复</span>
<span>{i.reply_user.name}</span>
<span className='ml15 timeAgo'>{timeAgo(i.created_at)}</span>
</div> : '' : <div key={item.id} className='commentContentBox pb30'>
{/* 评论 */}
<div className='commentOperationBor'></div>
<Link to={`/${item.user.login}`}><img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr15'/></Link>
<div className='commentContentRight'>
{/* 判断是否是编辑状态 */}
{(showEdit === 2 && updateId === item.id) ? <div className='mt15 mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={item.notes} defaultFileList={item.attachments} showUserImg={false}/></div> : <div>
<div className='commentContent'>
<div className='flexCenter font-14'>
<div>
<Link to={`/${item.user.login}`}>{item.user.name}</Link>
<span className='ml15 timeAgo font-15'>{timeAgo(item.created_at)}</span>
</div>
{login && <div>
{/* 平台管理员/仓库管理员/发布评论者/issue创建者 */}
{(admin || isManager || login === item.user.login || user_id === author.id) && <Popconfirm
placement="bottom"
title={`确定要删除此条评论吗?${item.children_journals.length > 0 ? '子评论也将被一起删除。' : ''}`}
okText="是"
cancelText="否"
onConfirm={() => deleteComment(item.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-fuzhi-shanchu font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅评论者可修改 */}
{login === item.user.login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(item.id); setShowEdit(2)}}><i className='iconfont icon-a-bianji12 font-13 mr8'></i>修改</Button>}
<CheckProfile {...props} sureFunc={()=>{setParentId(item.id); setReplyId(item.id); setShowEdit(3)}}><Button type='link' className='color-grey-89'><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button></CheckProfile>
</div>}
</div>
<div className='contentHtml mb5'>{commentCtx(item.notes)}</div>
{item && item.attachments && item.attachments.length > 0 && <div className='attachmentBox mb5'><Attachment
attachments={item.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
</div>
{login && <div>
{/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
{(admin || isManager || login === i.user.login || login === i.reply_user.login || user_id === author.id) && <Popconfirm
placement="bottom"
title={"确定要删除当前回复吗?"}
okText="是"
cancelText="否"
onConfirm={() => deleteComment(i.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-fuzhi-shanchu font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅回复评论者可修改 */}
{login === i.user.login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(i.id); setShowEdit(4)}}><i className='iconfont icon-a-bianji12 font-13 mr8'></i>修改</Button>}
<CheckProfile {...props} sureFunc={()=>{setParentId(item.id);setReplyId(i.id); setShowEdit(5)}}>
<Button type='link' className='color-grey-89'><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button>
</CheckProfile>
</div>}
{showEdit === 3 && replyId === item.id && <div className='contentHtml mr20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
{/* 评论回复部分 */}
{item.children_journals.map(i =>{return <div className='commentReply' key={i.id}>
{(showEdit === 4 && updateId === i.id) ? <div className='mr20'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={i.notes} defaultFileList={i.attachments}/></div> : <div>
<div className='flexCenter'>
<div>
<Link to={`/${i.user.login}`}><img src={getImageUrl(i.user.image_url)} alt="" className='commentUserImg mr8'/></Link>
<Link to={`/${i.user.login}`}>{i.user.name}</Link>
<span className='ml5 timeAgo mr3'>回复</span>
<span>{i.reply_user.name}</span>
<span className='ml15 timeAgo font-15'>{timeAgo(i.created_at)}</span>
</div>
{login && <div>
{/* 平台管理员/仓库管理员/发布评论者/回复评论者/issue创建者 */}
{(admin || isManager || login === i.user.login || login === i.reply_user.login || user_id === author.id) && <Popconfirm
placement="bottom"
title={"确定要删除当前回复吗?"}
okText="是"
cancelText="否"
onConfirm={() => deleteComment(i.id)}
>
<Button type='link' className='color-grey-89'><i className='iconfont icon-fuzhi-shanchu font-14 mr8'></i>删除</Button>
</Popconfirm>}
{/* 仅回复评论者可修改 */}
{login === i.user.login && <Button type='link' className='color-grey-89' onClick={()=>{setUpdateId(i.id); setShowEdit(4)}}><i className='iconfont icon-a-bianji12 font-13 mr8'></i>修改</Button>}
<CheckProfile {...props} sureFunc={()=>{setParentId(item.id);setReplyId(i.id); setShowEdit(5)}}>
<Button type='link' className='color-grey-89'><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button>
</CheckProfile>
</div>}
</div>
<div className='contentHtml mt5 mb10'>{commentCtx(i.notes)}</div>
{i && i.attachments && i.attachments.length > 0 && <div className='attachmentBox'><Attachment
attachments={i.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
</div>}
</div>
<div className='contentHtml mt5'>{commentCtx(i.notes)}</div>
{i && i.attachments && i.attachments.length > 0 && <div className='ml30'><Attachment
attachments={i.attachments}
showNotification={showNotification}
canDelete={false}
/></div>}
</div>}
{showEdit === 5 && replyId === i.id && <div className='contentHtml mt20 mr20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
</div>})}
<div className='issueCommentBottomBor'></div></div>}))}
</div>
{showEdit === 5 && replyId === i.id && <div className='contentHtml mr20'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
</div>})}
</div>
</div>}))}
</div>
</Spin>
{/* 无数据 */}
{journals && !journals.length && <Nodata _html="暂无数据"/>}
</div>

View File

@ -1,13 +1,22 @@
.typeActionBox{
padding: 17px 20px 10px;
background-color:#fafcff;
border:1px solid rgba(42, 97, 255, 0.23);
padding: 10px 20px 4px;
background-color:rgba(241, 243, 252, 0.55);
border-radius:4px;
.typeActionRadio{
color: #333;
display: inline-flex;
align-items: center;
margin-right: 35px;
margin-right: 25px;
&.ant-radio-wrapper-checked{
color: $primary-color;
}
}
.journalsCount{
color:#5e6685;
background-color:rgba(70, 106, 255, 0.09);
border-radius:10px;
display: inline-block;
padding: 0px 6px;
}
}
.commentUserImg{
@ -16,7 +25,7 @@
border-radius: 50%;
object-fit: cover;
}
.commentsBox{
.issueCommentsBox{
.iconBackBox{
display: inline-block;
width:24px;
@ -26,43 +35,115 @@
text-align: center;
background-color:#f2f3f5;
}
.operationLogTopBor, .operationLogBottomBor{
width: 1px;
height: 20px;
background-color:#eeeeee;
margin-left: 12px;
.operationLog, .commentContentBox{
position: relative;
min-height: 62px;
display: flex;
>.flexCenter, >a{
z-index: 2;
}
&::before, &::after{
content: '';
width: 1px;
height: 50%;
position: absolute;
background: #eee;
left: 12px;
z-index: 1;
}
&::after{
background: #eee;
top: 50%;
}
}
.operationLogTopBor{
margin-bottom: -3px;
.commentContentBox+.operationLog .operationCommentBor, .operationLog+.commentContentBox .commentOperationBor{
border-top: 1px solid #eee;
width: 98.5%;
position: absolute;
left: 12px;
}
.operationLogBottomBor{
margin-top: -4px;
.operationLog+.commentContentBox{
&>a, &>.commentContentRight{
margin-top: 25px;
}
}
.timeAgo{
color:#acb0bf;
}
.operationLog:last-child .operationLogBottomBor, .operationLog:first-child .operationLogTopBor{
.operationLog:last-child::after, .operationLog:first-child::before, .commentContentBox:last-child::after, &.justComment .commentContentBox::before, &.justComment .commentContentBox::after{
display: none;
}
.commentContent, .commentContentBox+.operationLog{
border-top: 1px solid #eeeeee;
.operationLog:first-child, .commentContentBox+.operationLog{
margin-top: -15px;
}
.commentContentBox:first-of-type .commentContent{
border-top: none;
.commentContentBox:last-child::before{
height: 35%;
}
.flexCenter{
display: flex;
align-items: center;
justify-content: space-between;
}
.contentHtml, .commentReply{
margin-left: 34px;
.commentRenderHtml.markdown-body p{
font-size: 13px !important;
}
.commentReply{
padding: 15px 0 15px 20px;
padding: 15px 0 0 20px;
background-color: rgba(238, 240, 246, 0.41);
&+.commentReply{
border-top: 1px dashed #eeeeee;
&>div{
padding-bottom: 5px;
}
&+.commentReply>div{
margin-top: -15px;
padding-top: 15px;
border-top: 1px dashed #eee;
}
}
.opBox{
justify-content: flex-start;
// flex: 1;
// width: 100%;
}
.commentContentBox{
display: flex;
}
.commentContentRight{
flex: 1;
background-color:#fafafc;
border:1px solid rgba(42, 97, 255, 0.23);
border-radius:6px;
position: relative;
top: -6px;
padding: 10px 15px 16px;
&::before{
content: '';
display: block;
position: absolute;
top: 13px;
left: -14px;
width: 0;
height: 0;
overflow: hidden;
font-size: 0;
line-height: 0;
border: 7px;
border-style: solid;
border-color: transparent rgba(42, 97, 255, 0.23) transparent transparent;
}
&::after{
content: '';
display: block;
width: 0;
height: 0;
overflow: hidden;
font-size: 0;
line-height: 0;
border: 6px;
border-style: solid;
border-color: transparent #fafafc transparent transparent;
position: absolute;
top: 14px;
left: -11px;
}
}
}
@ -71,14 +152,12 @@
}
.attachmentBox{
margin-top: -8px;
margin-left: 27px;
}
.color-grey-89{
color: #898d9d;
}
// 添加评论样式
.unLoginComment{
width:871px;
height:58px;
line-height: 58px;
background-color:rgba(241, 243, 252, 0.55);
@ -92,4 +171,22 @@
color: red;
margin-top: -10px;
margin-bottom: 5px !important;
}
.addComments{
display: flex;
align-items: center;
background-color:rgba(241, 243, 252, 0.55);
border-radius:4px;
padding:7px 10px;
&>img{
height: 26px;
width: 26px;
border-radius: 50%;
margin-right: 13px;
}
}
.addCommentBox{
width: 100%;
height: 30px;
border: none;
}

View File

@ -661,20 +661,7 @@
}
}
// 评论相关
.addcomments{
display: flex;
align-items: flex-start;
background-color:rgba(241, 243, 252, 0.55);
border-radius:4px;
padding:11px 20px;
&>img{
height: 36px;
width: 36px;
border-radius: 50%;
margin-right: 13px;
}
}
.overlaydrop{
&.large{
width: 260px;

View File

@ -263,16 +263,10 @@ function Index(props) {
//
function addBranchBtn(){
setAddBranch(true);
const url = `/v1/${owner}/${projectsId}/branches.json`;
Axios.get(url,{
params:{
page: 1,
limit: total
}
}).then(result=>{
const url = `/v1/${owner}/${projectsId}/branches/all.json`;
Axios.get(url).then(result=>{
if(result){
const {branches} = result.data;
setBranchList(branches);
setBranchList(result.data);
}
}).catch(error=>{console.log('error', error);})
}
@ -393,7 +387,7 @@ function Index(props) {
<Input placeholder='请输入分支名称' className='createBranchInput' onChange={checkNewBranchName} maxLength={100}/>
<div className='newBranchError mt5'>{newBranchError}</div>
<div className='font-15 createBranchLabel mt20'>分支起点</div>
<Select showSearch style={{width: '340px'}} className='createBranchInput' defaultValue={list[0] && list[0].name} onChange={(value)=>{setNewFormBranchName(value)}} getPopupContainer={triggerNode => triggerNode.parentNode}>
<Select showSearch style={{width: '340px'}} className='createBranchInput' placeholder="请选择分支起点" onChange={(value)=>{setNewFormBranchName(value)}} getPopupContainer={triggerNode => triggerNode.parentNode}>
{branchList && branchList.map((item, index)=>{
return <Select.Option value={item.name} key={index}>{item.name}</Select.Option>
})}

View File

@ -15,7 +15,9 @@ class Milepost extends Component {
// 里程碑 开启/关闭 状态
status: 'open',
order_name: undefined,
spinings: true
spinings: true,
// tooltip显隐
visible: false
}
}
componentDidUpdate(){
@ -129,8 +131,16 @@ class Milepost extends Component {
this.getList(1, pageSize, this.state.status, this.state.order_name, this.state.order_type);
}
// tooltip判断是否显示
// onVisibleChange = (visible, value) => {
// console.log('visible, value', visible, value);
// this.setState({
// visible: value.length >24 ? visible : false
// })
// }
render() {
const { data, limit, page, spinings, status, order_name, order_type } = this.state;
const { data, limit, page, spinings, status, order_name, order_type, visible } = this.state;
const { projectsId , owner } = this.props.match.params;
const { isManager, isDeveloper} = this.props;
const menu = (
@ -168,18 +178,21 @@ class Milepost extends Component {
<Spin spinning={spinings}>
<div className="main milepostBox">
{/* 创建里程碑按钮 */}
<div className='createMilepost mb25'>
{/* <div className='createMilepost mb25'>
{(isManager || isDeveloper) && <Button type='primary' onClick={() => {this.props.history.push(`/${owner}/${projectsId}/milestones/new`)}} className='createMilepostBtn'>+ 创建里程碑</Button>}
</div>
</div> */}
{/* 里程碑列表表头 */}
<div className='milepostHead flexSpaceBetween'>
<div>
<span className={`pointBox font-15 postStatus ${status === "closed" ? "" : "active"}`} onClick={() => this.opneMilelist(1)}>开启中<span className='statusCount font-13'>{data && data.opening_milestone_count}</span></span>
<span className={`pointBox ml35 font-15 postStatus ${status === "closed" ? "active" : ""}`} onClick={() => this.opneMilelist(2)}>已关闭<span className='statusCount font-13'>{data && data.closed_milestone_count}</span></span>
</div>
<div>
{(isManager || isDeveloper) && <Button type='primary' onClick={() => {this.props.history.push(`/${owner}/${projectsId}/milestones/new`)}} className='createMilepostBtn mr20'>+ 创建里程碑</Button>}
<Dropdown className="topWrapperSelect" overlay={menu} trigger={['click']} placement="bottomCenter">
<span className='pointBox'>{order_name ? sortByMile[order_name][order_type] : '排序'}<Icon type="caret-down" className="ml5"/></span>
</Dropdown>
</div>
</div>
{/* 里程碑列表展示 */}
{data && data.milestones && data.milestones.length === 0 && <div className="milestonesNoDate"><img src={emp} alt=""/></div>}
@ -191,12 +204,12 @@ class Milepost extends Component {
<i className="iconfont icon-lichengbeiicon1 font-12 mr10 primaryColor"></i>
<Link to={`/${owner}/${projectsId}/milestones/${item.id}`} className="font-16 task-hide milepostInfo">{item.name}</Link>
</div>
<Tooltip title={item.description} placement={'topLeft'} overlayStyle={{width: '600px'}}><span className='color-grey-89 task-hide milepostInfo'>{item.description}</span></Tooltip>
{item.description && item.description.length > 44 ? <Tooltip title={item.description} placement={'topLeft'} overlayStyle={{width: '600px'}}><span className='color-grey-89 task-hide milepostInfo'>{item.description}</span></Tooltip> : <span className='color-grey-89 milepostInfo'>{item.description}</span>}
</div>
<div className="flexSpaceBetween actionMileBox">
<div className="grid-item effectiveDate">
<i className={`iconfont icon-a-31shijian font-15 mr10 ${item.effective_date ? "effectiveDate" : "color-grey-89"}`}></i>
<span className={item.effective_date ? "" : "color-grey-89"}>{item.effective_date || "暂无截止时间"}</span>
<span className={`${item.effective_date ? "" : "color-grey-89"} ${item.effective_date && status !== 'closed' && new Date().getTime()-new Date(`${item.effective_date} 24:0`).getTime() > 0 ? 'outTime' : ''}`}>{item.effective_date || "暂无截止时间"}</span>
</div>
<div className="mr10 effectiveDate">
<span>{item.opened_issues_count || 0}个开启</span>

View File

@ -52,10 +52,13 @@
}
.milepostInfo{
display: inline-block;
width: 500px;
width: 640px;
}
.actionMileBox{
width: 550px;
.outTime{
color: red;
}
}
}
.createMilepostBtn{

View File

@ -20,7 +20,7 @@ export default Form.create()(
function checkPsd(rule, value, callback){
const map = passMap;
if(value){
current_user && Axios.post(`/v1/${current_user.login}/check_password.json`,{
current_user && value.length > 8 && Axios.post(`/v1/${current_user.login}/check_password.json`,{
password: value
}).then(res=>{
if(res && !res.data.status){
@ -50,7 +50,7 @@ export default Form.create()(
callback("请先输入登录密码");
}
if(value){
current_user && value && value.length > 4 && Axios.post(`/v1/${current_user.login}/check_phone_verify_code.json`,{
current_user && value && value.length > 5 && Axios.post(`/v1/${current_user.login}/check_phone_verify_code.json`,{
code_type: 4,
phone: phoneValue,
code: value
@ -192,7 +192,7 @@ export default Form.create()(
{required:true,message:"请输入登录密码"},
{validator:(rule, value, callback)=>checkPsd(rule, value, callback)}
],
validateTrigger:"onBlur",
validateTrigger:"onChange",
})(
<Input.Password placeholder="请输入登录密码" autoComplete={"new-password"} style={{width:"400px"}}/>
)}
@ -203,7 +203,7 @@ export default Form.create()(
{required:true,message:"请输入新手机号码"},
{validator:(rule, value, callback)=>checkPhone(rule, value, callback)}
],
validateTrigger:"onBlur",
validateTrigger:"onChange",
})(
<Input placeholder="请输入新手机号码" style={{width:"400px"}} autoComplete={"off"}/>
)}
@ -215,7 +215,7 @@ export default Form.create()(
{required:true,message:"请输入短信验证码"},
{validator:(rule, value, callback)=>checkCode(rule, value, callback)}
],
validateTrigger:"onBlur",
validateTrigger:"onChange",
})(
<Input placeholder="请输入短信验证码" style={{width:"400px"}}/>
)}