forked from Gitlink/forgeplus-react
issue评论+里程碑
This commit is contained in:
parent
91cc185cb4
commit
af6ad43bfe
|
@ -11299,7 +11299,7 @@
|
|||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import React from 'react';
|
||||
import { Input } from 'antd';
|
||||
|
||||
|
||||
function Add(){
|
||||
return(
|
||||
<div className="addcomments">
|
||||
<img src={`https://testforgeplus.trustie.net/images/avatars/User/36480?t=1672730523`} alt="" />
|
||||
<div style={{flex:1}}>
|
||||
<Input placeholder="添加评论" style={{width:"100%",height:"36px"}}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Add;
|
|
@ -0,0 +1,127 @@
|
|||
import React from 'react';
|
||||
import { Input, Button, message } from 'antd';
|
||||
import { getImageUrl, timeAgo } from 'educoder';
|
||||
import MDEditor from "../../../../modules/tpm/challengesnew/tpm-md-editor";
|
||||
import Upload from "../../../../forge/Upload/Index";
|
||||
import UploadImg from "../../../../forge/Images/upload.png";
|
||||
import './list.scss';
|
||||
import '../../../../forge/Order/order.scss';
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
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 [content, setContent] = useState(props.content);
|
||||
const [quillFlag, setQuillFlag] = useState(false);
|
||||
// 确认评论按钮loading效果
|
||||
const [journalSpin, setJournalSpin] = useState(false);
|
||||
const [atWhoLoginList, setAtWhoLoginList] = useState(undefined);
|
||||
const [fileList, setFileList] = useState(undefined);
|
||||
const [attachmentClean, setAttachmentClean] = useState(true);
|
||||
|
||||
// 评论点击函数
|
||||
function addJournals(){
|
||||
setJournalSpin(true);
|
||||
if(updateId){
|
||||
// 修改评论
|
||||
axios.patch(`/v1/${owner}/${projectsId}/issues/${index}/journals/${updateId}`,{
|
||||
notes: content,
|
||||
attachment_ids: fileList,
|
||||
receivers_login:atWhoLoginList
|
||||
}).then(res=>{
|
||||
if(res && res.data){
|
||||
// 刷新评论列表
|
||||
reloadComment();
|
||||
message.success('评论成功');
|
||||
cancelMd();
|
||||
setContent(undefined);
|
||||
}
|
||||
setJournalSpin(false);
|
||||
})
|
||||
}else{
|
||||
// 新建评论
|
||||
const params = {
|
||||
parent_id: parentId,
|
||||
reply_id: replyId,
|
||||
notes: content,
|
||||
attachment_ids: fileList,
|
||||
receivers_login:atWhoLoginList
|
||||
}
|
||||
axios.post(`/v1/${owner}/${projectsId}/issues/${index}/journals`, params).then(res=>{
|
||||
if(res && res.data){
|
||||
// 刷新评论列表
|
||||
reloadComment();
|
||||
message.success('评论成功');
|
||||
cancelMd();
|
||||
setContent(undefined);
|
||||
}
|
||||
setJournalSpin(false);
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
return(
|
||||
<div className="grid-item-top pb10">
|
||||
<Link
|
||||
to={`/${current_user && current_user.login}`}
|
||||
className="show-user-link mr10"
|
||||
>
|
||||
<img
|
||||
className="radius"
|
||||
src={getImageUrl(
|
||||
`/${current_user && current_user.image_url}`
|
||||
)}
|
||||
alt=""
|
||||
width="30"
|
||||
height="30"
|
||||
/>
|
||||
</Link>
|
||||
<div style={{position:"relative"}}>
|
||||
<MDEditor
|
||||
placeholder={"添加评论..."}
|
||||
height={300}
|
||||
mdID={"orderdetail-add-descriptions" + replyId}
|
||||
initValue={content}
|
||||
onChange={(value)=>{setQuillFlag(false);setContent(value);}}
|
||||
isCanAtme = {true}
|
||||
changeAtWhoLoginList = {(loginList)=>{setAtWhoLoginList(loginList); setAttachmentClean(true)}}
|
||||
owner = {owner}
|
||||
projectsId = {projectsId}
|
||||
></MDEditor>
|
||||
<p className="quillFlag">
|
||||
{quillFlag && <span>请输入评论内容</span>}
|
||||
</p>
|
||||
<Upload
|
||||
className="commentStyle"
|
||||
isComplete={attachmentClean}
|
||||
load={(fileList)=>{setFileList(fileList)}}
|
||||
icon={
|
||||
<img
|
||||
src={UploadImg}
|
||||
width="58"
|
||||
alt=""
|
||||
style={{ marginBottom: 15 }}
|
||||
/>
|
||||
}
|
||||
size={100}
|
||||
showNotification={showNotification}
|
||||
defaultFileList={props.defaultFileList}
|
||||
/>
|
||||
<p className="clearfix mt20">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={addJournals}
|
||||
loading={journalSpin}
|
||||
className="mr15"
|
||||
>
|
||||
评论
|
||||
</Button>
|
||||
<Button onClick={()=>{cancelMd()}}>取消</Button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default EditComment;
|
|
@ -0,0 +1,209 @@
|
|||
import { Button, Popconfirm, Radio, Input, message } from 'antd';
|
||||
import axios from 'axios';
|
||||
import React, { Fragment } from 'react';
|
||||
import { getImageUrl, timeAgo } from 'educoder';
|
||||
import { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
import RenderHtml from '../../../../components/render-html';
|
||||
import Attachment from '../../../Upload/attachment';
|
||||
import EditComment from './editComment';
|
||||
import './list.scss';
|
||||
import Nodata from '../../../Nodata';
|
||||
|
||||
function IssueCommentList(props){
|
||||
const{history: {location}, reload, reloadComment, current_user, showNotification, current_user:{login, admin, image_url}, isManager, showLoginDialog} = props;
|
||||
const {owner, projectsId, index} = props.match.params;
|
||||
const [category, setCategory] = useState('all');
|
||||
const [journals, setJournals] = useState(undefined);
|
||||
// 是否展示新建/编辑评论部分
|
||||
const [showEdit, setShowEdit] = useState(false);
|
||||
const [parentId, setParentId] = useState(undefined);
|
||||
const [replyId, setReplyId] = useState(undefined);
|
||||
// 修改评论id
|
||||
const [updateId, setUpdateId] = useState(undefined);
|
||||
// 操作日志展开效果
|
||||
const [open, setOpen] = useState(undefined);
|
||||
// 操作记录 icon
|
||||
const journalsIcon ={
|
||||
'issue': 'icon-chuangjianqianbao',
|
||||
'branch_name': 'icon-fenzhi3',
|
||||
'assigner': 'icon-chengyuan2',
|
||||
'status_id': 'icon-xiugaibaobiaomoban',
|
||||
'fixed_version_id': 'icon-lichengbeiicon2',
|
||||
'due_date': 'icon-riqi',
|
||||
'issue_tag': 'icon-biaoji2',
|
||||
'description': 'icon-xiugaibaobiaomoban',
|
||||
'subject': 'icon-xiugaibaobiaomoban',
|
||||
'start_date': 'icon-riqi'
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
axios.get(`/v1/${owner}/${projectsId}/issues/${index}/journals`,{params:{
|
||||
category
|
||||
}}).then(res=>{
|
||||
if(res && res.data){
|
||||
const {journals} = res.data;
|
||||
if(category === 'all'){
|
||||
const array = [];
|
||||
let start = undefined;
|
||||
let isJournalCount = 0;
|
||||
journals.map((item, index)=>{
|
||||
!isJournalCount && (start = index)
|
||||
item.is_journal_detail && (isJournalCount++)
|
||||
if(isJournalCount >= 10 && (!item.is_journal_detail || journals.length-1 === index)){
|
||||
array.push({start, count: isJournalCount});
|
||||
isJournalCount = 0;
|
||||
}
|
||||
})
|
||||
array.map((item, i)=>{
|
||||
journals[item.start].numCount = item.count;
|
||||
for (let index = 0; index < item.count; index++) {
|
||||
journals[item.start+index].start = journals[item.start].id;
|
||||
journals[item.start+index].closeAndSpan = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log('journals', journals);
|
||||
setJournals(journals);
|
||||
}
|
||||
})
|
||||
}, [reload, category])
|
||||
|
||||
function commentCtx(v){
|
||||
return <RenderHtml className="break_word_comments imageLayerParent" value={v} url={location}/>;
|
||||
};
|
||||
|
||||
// 删除评论内容
|
||||
function deleteComment(id){
|
||||
axios.delete(`/v1/${owner}/${projectsId}/issues/${index}/journals/${id}`).then(res=>{
|
||||
if(res && res.data && !res.data.status){
|
||||
reloadComment();
|
||||
message.success('删除成功');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// markdown 取消操作
|
||||
function cancelMd(){
|
||||
setShowEdit(false);
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="commentListBox">
|
||||
{/* 添加评论 */}
|
||||
<div className="pt20 pb30">
|
||||
{login ? showEdit === 1 ? <EditComment {...props} cancelMd={cancelMd}/> : <div className="addcomments">
|
||||
<img src={getImageUrl(image_url)} alt="" />
|
||||
<div style={{flex:1}} onClick={()=>{setShowEdit(1)}}>
|
||||
<Input placeholder="添加评论" style={{width:"100%",height:"36px"}}/>
|
||||
</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 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='logContent font-15'>
|
||||
<div>
|
||||
<span className='iconBackBox mr10'><i className={`iconfont font-12 ${journalsIcon[item.operate_category]}`}></i></span>
|
||||
<img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr5'/>
|
||||
<span>{item.user.name} </span>
|
||||
<span className='task-hide' dangerouslySetInnerHTML={{__html:item.operate_content}} style={{maxWidth: '650px'}}></span>
|
||||
<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 ? '关闭' : '展开'}全部操作日志</a>}
|
||||
</div>
|
||||
<div className='operationLogBottomBor'></div>
|
||||
</div> : '' : <div key={item.id} className='commentContentBox'>
|
||||
{/* 评论 */}
|
||||
{/* 判断是否是编辑状态 */}
|
||||
{(showEdit === 2 && updateId === item.id) ? <div className='mt15'><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>
|
||||
<img src={getImageUrl(item.user.image_url)} alt="" className='commentUserImg mr8'/>
|
||||
<span>{item.user.name}</span>
|
||||
<span className='ml15 timeAgo'>{timeAgo(item.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者 */}
|
||||
{(admin || isManager || login === item.user.login) && <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>}
|
||||
<Button type='link' className='color-grey-89' onClick={()=>{setParentId(item.id); setReplyId(item.id); setShowEdit(3)}}><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button>
|
||||
</div>}
|
||||
</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>}
|
||||
</div>
|
||||
</div>}
|
||||
{showEdit === 3 && replyId === item.id && <div className='contentHtml'><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'><EditComment {...props} cancelMd={cancelMd} updateId={updateId} reloadComment={reloadComment} content={i.notes} defaultFileList={i.attachments}/></div> : <div>
|
||||
<div className='flexCenter'>
|
||||
<div>
|
||||
<img src={getImageUrl(i.user.image_url)} alt="" className='commentUserImg mr8'/>
|
||||
<span>{i.user.name}</span>
|
||||
<span className='ml5 timeAgo mr3'>回复</span>
|
||||
<span>{i.reply_user.name}</span>
|
||||
<span className='ml15 timeAgo'>{timeAgo(i.created_at)}</span>
|
||||
</div>
|
||||
{login && <div>
|
||||
{/* 平台管理员/仓库管理员/发布评论者/回复评论者 */}
|
||||
{(admin || isManager || login === i.user.login || login === i.reply_user.login) && <Popconfirm
|
||||
placement="bottom"
|
||||
title={"确定要删除当前回复吗?"}
|
||||
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 === 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>}
|
||||
<Button type='link' className='color-grey-89' onClick={()=>{setParentId(item.id);setReplyId(i.id); setShowEdit(5)}}><i className='iconfont icon-a-xiaoxi1 font-13 mr8'></i>回复</Button>
|
||||
</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'><EditComment {...props} cancelMd={cancelMd} parentId={parentId} replyId={replyId} reloadComment={reloadComment}/></div>}
|
||||
</div>})}
|
||||
<div className='issueCommentBottomBor'></div></div>}))}
|
||||
</div>
|
||||
{/* 无数据 */}
|
||||
{journals && !journals.length && <Nodata _html="暂无数据"/>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default IssueCommentList;
|
|
@ -0,0 +1,92 @@
|
|||
.typeActionBox{
|
||||
padding: 17px 20px 10px;
|
||||
background-color:#fafcff;
|
||||
border:1px solid rgba(42, 97, 255, 0.23);
|
||||
border-radius:4px;
|
||||
.typeActionRadio{
|
||||
color: #333;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 35px;
|
||||
}
|
||||
}
|
||||
.commentUserImg{
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.commentsBox{
|
||||
.iconBackBox{
|
||||
display: inline-block;
|
||||
width:24px;
|
||||
height:24px;
|
||||
border-radius: 50%;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
background-color:#f2f3f5;
|
||||
}
|
||||
.logContent{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.operationLogTopBor, .operationLogBottomBor{
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background-color:#eeeeee;
|
||||
margin-left: 12px;
|
||||
}
|
||||
.operationLogTopBor{
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
.operationLogBottomBor{
|
||||
margin-top: -4px;
|
||||
}
|
||||
.timeAgo{
|
||||
color:#acb0bf;
|
||||
}
|
||||
.operationLog:last-child .operationLogBottomBor, .operationLog:first-child .operationLogTopBor{
|
||||
display: none;
|
||||
}
|
||||
.commentContent, .commentContentBox+.operationLog{
|
||||
border-top: 1px solid #eeeeee;
|
||||
}
|
||||
.commentContentBox:first-of-type .commentContent{
|
||||
border-top: none;
|
||||
}
|
||||
.flexCenter{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.contentHtml, .commentReply{
|
||||
margin-left: 34px;
|
||||
}
|
||||
.commentReply{
|
||||
padding: 15px 0;
|
||||
border-top: 1px solid #eeeeee;
|
||||
}
|
||||
}
|
||||
.primaryColor, .primaryColor:link{
|
||||
color: $primary-color;
|
||||
}
|
||||
.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);
|
||||
border-radius:4px;
|
||||
color: rgba(84, 87, 103, 1);
|
||||
.loginBtn{
|
||||
color: $primary-color;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import { Link } from 'react-router-dom';
|
|||
import { Box , LongWidth } from '../../Component/layout';
|
||||
import RenderHtml from "../../../components/render-html";
|
||||
import EditMenus from '../Component/editMenus';
|
||||
import Add from '../Component/comments/add';
|
||||
import NewPanel from '../Component/newPanel';
|
||||
import Attachments from "../../Upload/attachment";
|
||||
import AddTagsBox from '../Component/addTagsBox';
|
||||
|
@ -14,6 +13,7 @@ import Date from '../Component/date';
|
|||
import moment from 'moment';
|
||||
import Copy from '../Component/copy';
|
||||
import axios from 'axios';
|
||||
import CommentList from '../Component/comments/list';
|
||||
|
||||
function Details(props){
|
||||
const [ details , setDetails ] = useState(undefined);
|
||||
|
@ -48,6 +48,7 @@ function Details(props){
|
|||
|
||||
const [ start_date, setStartDate ] = useState("");
|
||||
const [ due_date, setDueDate ] = useState("");
|
||||
const [ commentReload, setCommentReload] = useState(undefined);
|
||||
const pathname = props.history.location.pathname;
|
||||
|
||||
useEffect(()=>{
|
||||
|
@ -228,6 +229,8 @@ function Details(props){
|
|||
}).then(result=>{
|
||||
if(result){
|
||||
Init();
|
||||
// 更新操作日志
|
||||
setCommentReload(Math.random());
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
@ -259,13 +262,14 @@ function Details(props){
|
|||
}).then(result=>{
|
||||
if(result){
|
||||
props.showNotification("疑修更新成功!");
|
||||
// 刷新操作记录
|
||||
setCommentReload(Math.random());
|
||||
Init();
|
||||
setEdit(false);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}else{
|
||||
// 调用新建保存接口
|
||||
console.log(branchId,statusId,prioritiesId,millstoneId,tagId, charegeId);
|
||||
const url = `/v1/${owner}/${projectsId}/issues`;
|
||||
axios.post(url,{
|
||||
...params,
|
||||
|
@ -368,10 +372,7 @@ function Details(props){
|
|||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{/* <div className="pt20 pb30">
|
||||
<Add />
|
||||
</div> */}
|
||||
<CommentList {...props} reload = {commentReload} reloadComment = {()=>{setCommentReload(Math.random())}}/>
|
||||
</LongWidth>
|
||||
<div className="shortwidth mt25">
|
||||
<EditMenus name="负责人" names={names && names.assigner_name} imgFlag onChange={(ids,name)=>{saveForeach(ids);let copyname = { ...names,assigner_name:name};setNames(copyname);setCharegeId(ids);}} list={chargeList} value={charegeId} searchFlag searchFunc={(value)=>{setCharge(value)}} double={5} editFlag={details && !details.user_permission}/>
|
||||
|
|
|
@ -9,6 +9,8 @@ import axios from 'axios';
|
|||
import moment from 'moment';
|
||||
|
||||
function New(props){
|
||||
// 里程碑id
|
||||
const milepostId = props.match.params.milepostId;
|
||||
const [ visible , setVisible ] = useState(false);
|
||||
|
||||
|
||||
|
|
|
@ -40,6 +40,13 @@ function Index(props){
|
|||
<Detail {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
{/* 里程碑创建issue */}
|
||||
<Route
|
||||
path="/:owner/:projectsId/issues/:milepostId/new"
|
||||
render={(p) => (
|
||||
<New {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/:owner/:projectsId/issues/new"
|
||||
render={(p) => (
|
||||
|
|
|
@ -89,7 +89,7 @@ const UpdateMerge = Loadable({
|
|||
})
|
||||
|
||||
const MilepostDetail = Loadable({
|
||||
loader: () => import('../Order/MilepostDetail'),
|
||||
loader: () => import('../Order/MilepostDetail.jsx'),
|
||||
loading: Loading,
|
||||
})
|
||||
const WatchUsers = Loadable({
|
||||
|
@ -767,7 +767,7 @@ class Detail extends Component {
|
|||
}
|
||||
></Route>
|
||||
{/*里程碑详情*/}
|
||||
<Route path="/:owner/:projectsId/milestones/:meilid"
|
||||
<Route path="/:owner/:projectsId/milestones/:mileId"
|
||||
render={
|
||||
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Dropdown, Icon, Menu, Pagination, Typography, Popconfirm, Spin } from 'antd';
|
||||
import { Dropdown, Icon, Menu, Pagination, Typography, Popconfirm, Spin, Button } from 'antd';
|
||||
import NoneData from '../Nodata';
|
||||
import axios from 'axios';
|
||||
import './order.scss';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
import './milepost.scss';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
|
@ -13,16 +12,12 @@ class Milepost extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
data: undefined,
|
||||
limit: 15,
|
||||
limit: 10,
|
||||
page: 1,
|
||||
order_type: undefined,
|
||||
//新建标签区域是否显示 none 隐藏 block 显示
|
||||
display: 'none',
|
||||
// 里程碑 开启/关闭 状态
|
||||
status: 'open',
|
||||
openselect: 1,
|
||||
closeselect: undefined,
|
||||
order_name: undefined,
|
||||
|
||||
spinings: true
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +26,7 @@ class Milepost extends Component {
|
|||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
this.getList(1, this.state.status, 'desc');
|
||||
this.getList(1, this.state.limit, this.state.status);
|
||||
this.updateDocumentTitle();
|
||||
}
|
||||
|
||||
|
@ -44,13 +39,12 @@ class Milepost extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
getList = (page, status, order_type, order_name) => {
|
||||
getList = (page, limit, category, sort_by, sort_direction) => {
|
||||
const { projectsId ,owner } = this.props.match.params;
|
||||
const { limit } = this.state;
|
||||
const url = `/${owner}/${projectsId}/milestones.json`;
|
||||
const url = `/v1/${owner}/${projectsId}/milestones.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
page, limit, status, order_type, order_name
|
||||
page, limit: limit, category, sort_by, sort_direction
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
|
@ -65,45 +59,24 @@ class Milepost extends Component {
|
|||
}
|
||||
|
||||
opneMilelist = (type) => {
|
||||
const { order_name } = this.state;
|
||||
if (type) {
|
||||
const { current_user } = this.props;
|
||||
if (type === 1) {
|
||||
this.setState({
|
||||
status: 'open',
|
||||
openselect: current_user.user_id,
|
||||
closeselect: undefined,
|
||||
|
||||
})
|
||||
this.getList(1, 'open', 'desc', order_name);
|
||||
} else {
|
||||
this.setState({
|
||||
status: 'closed',
|
||||
openselect: undefined,
|
||||
closeselect: current_user.user_id
|
||||
})
|
||||
this.getList(1, 'closed', 'desc', order_name);
|
||||
}
|
||||
this.setState({
|
||||
status: type === 1 ? 'open' : 'closed'
|
||||
})
|
||||
this.getList(1, this.state.limit, type === 1 ? 'open' : 'closed');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updatestatusemile = (status, arr) => {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/milestones/${arr.id}/update_status.json`;
|
||||
const { current_user } = this.props;
|
||||
axios.post(url, {
|
||||
project_id: projectsId,
|
||||
id: arr.id,
|
||||
status: status
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
status: status,
|
||||
closeselect: status === "closed" ? current_user.user_id : undefined,
|
||||
openselect: status === "closed" ? undefined : current_user.user_id
|
||||
})
|
||||
this.getList(1, status, 'desc');
|
||||
this.getList(1, this.state.limit, this.state.status);
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
}
|
||||
|
@ -122,7 +95,7 @@ class Milepost extends Component {
|
|||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.getList(1, this.state.status, 'desc');
|
||||
this.getList(1, this.state.limit, this.state.status);
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
}
|
||||
|
@ -136,8 +109,7 @@ class Milepost extends Component {
|
|||
this.setState({
|
||||
page
|
||||
})
|
||||
const { status } = this.state;
|
||||
this.getList( page , status );
|
||||
this.getList(page, this.state.limit, this.state.status);
|
||||
}
|
||||
|
||||
// 排序
|
||||
|
@ -146,29 +118,24 @@ class Milepost extends Component {
|
|||
order_name: e.key,
|
||||
order_type: e.item.props.value
|
||||
})
|
||||
this.getList(1, this.state.status, e.item.props.value, e.key);
|
||||
this.getList(1, this.state.limit, this.state.status, e.key, e.item.props.value);
|
||||
}
|
||||
|
||||
|
||||
//控制新建标签页是否显示
|
||||
newshow = () => {
|
||||
// 分页组件
|
||||
onShowSizeChange = (current, pageSize) =>{
|
||||
this.setState({
|
||||
display: 'block'
|
||||
});
|
||||
|
||||
};
|
||||
newclose = () => {
|
||||
this.setState({
|
||||
display: 'none'
|
||||
});
|
||||
};
|
||||
|
||||
page: 1,
|
||||
limit: pageSize
|
||||
})
|
||||
this.getList(1, pageSize, this.state.status);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data, limit, page, openselect, closeselect, spinings } = this.state;
|
||||
const { data, limit, page, spinings, status } = this.state;
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { isManager, isDeveloper} = this.props;
|
||||
const menu = (
|
||||
<Menu className="orderCondition" onClick={this.arrayList}>
|
||||
<Menu className="orderCondition milepostSort" onClick={this.arrayList}>
|
||||
<Menu.Item key={'effective_date'} value="desc">到期日从后到先</Menu.Item>
|
||||
<Menu.Item key={'effective_date'} value="asc">到期日从先到后</Menu.Item>
|
||||
<Menu.Item key={'percent'} value="asc">完成度从低到高</Menu.Item>
|
||||
|
@ -181,100 +148,66 @@ class Milepost extends Component {
|
|||
|
||||
return (
|
||||
<Spin spinning={spinings}>
|
||||
<div className="main mt20" style={{minHeight:"400px"}}>
|
||||
<div style={{ display: this.state.display }}>
|
||||
<div className="tagdiv" >
|
||||
<span>里程碑{data && data.issue_tags_count}已创建</span>
|
||||
</div>
|
||||
<div className="main milepostBox">
|
||||
{/* 创建里程碑按钮 */}
|
||||
<div className='createMilepost mb25'>
|
||||
{(isManager || isDeveloper) && <Button type='primary' onClick={() => {this.props.history.push(`/${owner}/${projectsId}/milestones/new`)}} className='createMilepostBtn'>+ 创建里程碑</Button>}
|
||||
</div>
|
||||
<div className="topWrapper" style={{borderBottom:"1px solid #eee"}}>
|
||||
<div className="topWrapper_type_infos">
|
||||
<li className={openselect ? "active" : ""} onClick={() => this.opneMilelist(1)}>{data && data.open_count}个开启中</li>
|
||||
<li className={closeselect ? "active" : ""} onClick={() => this.opneMilelist(2)}>{data && data.closed_count}个已关闭</li>
|
||||
</div>
|
||||
<div className="topWrapper_select">
|
||||
<ul className="topWrapper_select mb-0">
|
||||
<li>
|
||||
<Dropdown className="topWrapperSelect" overlay={menu} trigger={['click']} placement="bottomCenter">
|
||||
<span>排序<Icon type="caret-down" className="ml5" /></span>
|
||||
</Dropdown>
|
||||
</li>
|
||||
</ul>
|
||||
{
|
||||
data && data.user_admin_or_member ?
|
||||
<CheckProfile {...this.props} className="topWrapper_btn" sureFunc={() => {this.props.history.push(`/${owner}/${projectsId}/milestones/new`)}}>新的里程碑</CheckProfile>
|
||||
: ''
|
||||
}
|
||||
{/* 里程碑列表表头 */}
|
||||
<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>
|
||||
<Dropdown className="topWrapperSelect" overlay={menu} trigger={['click']} placement="bottomCenter">
|
||||
<span className='pointBox'>排序<Icon type="caret-down" className="ml5"/></span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
{
|
||||
data && data.versions && data.versions.length > 0
|
||||
&&
|
||||
<div className="tagList">
|
||||
{
|
||||
data.versions.map((item, key) => {
|
||||
return (
|
||||
<div style={{ display: 'block' }} key={key}>
|
||||
<div className="milepostdiv">
|
||||
<div className="milepostwidth">
|
||||
<div className="grid-item width100">
|
||||
<i className="iconfont icon-lubiaosignpost3 font-12 mr3"></i>
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${item.id}`} className="font-16">{item.name}</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="milepostdiv" style={{ marginTop: 5 }}>
|
||||
<div className="milepostrighe">
|
||||
<div className="grid-item mr10">
|
||||
<i className="iconfont icon-rili font-14 mr5"></i>
|
||||
<span className={item.effective_date ? "color-red" : "color-grey-c"}>{item.effective_date || "暂无截止时间"}</span>
|
||||
</div>
|
||||
<div className="grid-item mr10 color-grey-9">
|
||||
<i className="iconfont icon-issue font-14 mr5"></i>
|
||||
<span>{item.open_issues_count}个开启</span>
|
||||
</div>
|
||||
<div className="grid-item mr10 color-grey-9">
|
||||
<i className="iconfont icon-shanchudiao font-14 mr5"></i>
|
||||
<span>{item.close_issues_count}个关闭</span>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
data && data.user_admin_or_member ?
|
||||
<div className="milepostleft">
|
||||
<div className="grid-item ml15 color-grey-9">
|
||||
<i className="iconfont icon-bianji3 font-14 mr5"></i>
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${item.id}/edit`} className="color-grey-9">编辑</Link>
|
||||
</div>
|
||||
<div className="grid-item ml15 color-grey-9">
|
||||
<i className={item.status === "closed" ? "iconfont icon-gouxuan font-14 mr5":"iconfont icon-yiguanbi1 font-14 mr5"}></i>
|
||||
<a onClick={() => this.updatestatusemile(item.status === "closed" ? "open" : "closed", item)} className="color-grey-9">{this.state.status === "closed" ? "开启" : "关闭"}</a>
|
||||
</div>
|
||||
<div className="grid-item ml15 color-grey-9">
|
||||
<i className="iconfont icon-lajitong font-14 mr5" ></i>
|
||||
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
|
||||
<a className="color-grey-9">删除</a>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
<div className="milepostdiv" style={{ marginTop: 5 }}>
|
||||
<div className="textwidth">
|
||||
<Text type="secondary" ellipsis={{ rows: 30, expandable: false, onExpand: Function }} >{item.description}</Text>
|
||||
</div>
|
||||
</div>
|
||||
{/* 里程碑列表展示 */}
|
||||
{data && data.milestones && data.milestones.length === 0 && <div className="milestonesNoDate"><NoneData _html="暂无里程碑"></NoneData></div>}
|
||||
{data && data.milestones && data.milestones.length > 0 && <div className='milepostList'>
|
||||
{data.milestones.map((item, key)=>{
|
||||
return <div className='flexSpaceBetween milepostItemBox'>
|
||||
<div>
|
||||
<div className="flexSpaceBetween">
|
||||
<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>
|
||||
<Text type="secondary" ellipsis={{ rows: 30, expandable: false, onExpand: Function }} className='color-grey-89 task-hide milepostInfo'>{item.description}</Text>
|
||||
</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>
|
||||
</div>
|
||||
<div className="mr10 effectiveDate">
|
||||
<span>{item.opened_issues_count || 0}个开启</span>
|
||||
<span className='color-grey-89'> | </span>
|
||||
<span>{item.close_issues_count || 0}个关闭</span>
|
||||
</div>
|
||||
{
|
||||
(isManager || isDeveloper) && <div className="flexSpaceBetween">
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${item.id}/edit`} className="primaryColor"><i className="iconfont icon-a-bianji12 font-14 mr5 primaryColor"></i>编辑</Link>
|
||||
<div className="grid-item ml15">
|
||||
<i className={`effectiveDate iconfont font-14 mr5 ${item.status === "closed" ? "icon-gouxuan":"icon-shanchu8"}`}></i>
|
||||
<a onClick={() => this.updatestatusemile(item.status === "closed" ? "open" : "closed", item)} className="effectiveDate">{item.status === "closed" ? "开启" : "关闭"}</a>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<div className="grid-item ml15">
|
||||
<i className="iconfont icon-fuzhi-shanchu font-14 mr5 colorRed" ></i>
|
||||
<Popconfirm placement="bottom" title={'是否删除里程碑?'} okText="是" cancelText="否" onConfirm={() => this.closemile(item)}>
|
||||
<a className="colorRed">删除</a>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{ data && data.versions && data.versions.length === 0 && <NoneData _html="暂无里程碑"></NoneData> }
|
||||
})}
|
||||
</div>}
|
||||
{
|
||||
data && data.versions_count > limit ?
|
||||
<div className="mt30 mb50 edu-txt-center">
|
||||
<Pagination simple current={page} total={data && data.versions_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||
data && data.total_count > limit ?
|
||||
<div className="mt30 mb50 edu-txt-right">
|
||||
<Pagination current={page} total={data && data.total_count} pageSize={limit} onChange={this.ChangePage} showQuickJumper showSizeChanger onShowSizeChange={this.onShowSizeChange}></Pagination>
|
||||
</div> : ""
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
import React , { useRef , useState , useEffect } from 'react';
|
||||
import { Dropdown , Menu , Icon , Input , Checkbox , Pagination, Button , Tooltip ,Spin } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import issueEmp from '../Issues/Img/issue-big.png';
|
||||
import AllMenus from './component/allMenus';
|
||||
import Datas from '../Issues/Component/datas';
|
||||
import axios from 'axios';
|
||||
import { FlexAJ } from '../Component/layout';
|
||||
import './milepost.scss';
|
||||
import './order.scss';
|
||||
import '../Issues/index.scss';
|
||||
const { Search } = Input;
|
||||
|
||||
function MilepostDetail(props){
|
||||
const [ milepost, setMilepost] = useState(undefined);
|
||||
const [ issueList , setIssueList ] = useState(undefined);
|
||||
const [ closedCount , setClosedCount ] = useState(0);
|
||||
const [ openedCount , setOpenedCount ] = useState(0);
|
||||
|
||||
const[ aboutMe , setAboutMe ] = useState("aboutme");
|
||||
const[ value , setValue ] = useState("");
|
||||
const[ keyword , setKeyword ] = useState(undefined);
|
||||
|
||||
const [ category , setCategory] = useState("all");
|
||||
|
||||
const [ allValue , setAllValue ] = useState([]);
|
||||
const [ allIds , setAllIds ] = useState([]);
|
||||
const [ checkAll , setCheckAll ] = useState(false);
|
||||
|
||||
const [ updateIds , setUpdateIds ] = useState([]);
|
||||
const [ limit, setLimit] = useState(10);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ total , setTotal ] = useState(undefined);
|
||||
|
||||
const menuRef = useRef(null);
|
||||
const { projectsId, mileId , owner } = props.match.params;
|
||||
const {current_user, projectDetail, showLoginDialog, history} = props;
|
||||
const permission = props && props.projectDetail && props.projectDetail.permission;
|
||||
|
||||
useEffect(()=>{
|
||||
Init();
|
||||
},[aboutMe, keyword, category, page, limit])
|
||||
|
||||
useEffect(()=>{
|
||||
updateDocumentTitle()
|
||||
}, [projectDetail, milepost])
|
||||
|
||||
// 更新网页标题
|
||||
function updateDocumentTitle(){
|
||||
if(projectDetail && milepost){
|
||||
const { author, name} = projectDetail;
|
||||
document.title = `${milepost.name}-里程碑-${author.name}/${name}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取issue列表数据
|
||||
function Init(params){
|
||||
const url = `/v1/${owner}/${projectsId}/milestones/${mileId}.json`;
|
||||
axios.get(url,{
|
||||
params:{
|
||||
page,
|
||||
limit,
|
||||
category,
|
||||
// participant_category:aboutMe,
|
||||
// keyword,category,
|
||||
...params
|
||||
// sort_direction:(params && params.sort_by) ? ((params.sort_by === 1 || params.sort_by === 3) ? "desc" : "asc") :undefined,
|
||||
// sort_by:(params && params.sort_by) ? ((params.sort_by === 1 || params.sort_by === 2) ? "created_on" : "updated_on") : undefined
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
const {milestone, issues, total_issues_count, closed_issues_count, opened_issues_count} = result.data;
|
||||
setMilepost(milestone);
|
||||
setIssueList(issues);
|
||||
setTotal(total_issues_count);
|
||||
setClosedCount(closed_issues_count);
|
||||
setOpenedCount(opened_issues_count);
|
||||
const ids = issues.length>0 ? issues.map(i=>{return i.id}) : [];
|
||||
setAllIds(ids);
|
||||
}
|
||||
}).then(error=>{console.log("error:",error)})
|
||||
}
|
||||
|
||||
// 第一个下拉搜索
|
||||
const menu = (
|
||||
<Menu selectedKeys={[`${aboutMe}`]} onClick={chooseAboutMe}>
|
||||
<Menu.Item key={"all"}>全部</Menu.Item>
|
||||
<Menu.Item key={"aboutme"}><Tooltip title="指我创建的、我负责的和@我的疑修">与我相关</Tooltip></Menu.Item>
|
||||
<Menu.Item key={"assignedme"}>我负责的</Menu.Item>
|
||||
<Menu.Item key={"authoredme"}>我创建的</Menu.Item>
|
||||
<Menu.Item key={"atme"}>@我的</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
function chooseAboutMe(e){
|
||||
setCategory("all");
|
||||
setAboutMe(e.key);
|
||||
}
|
||||
|
||||
//清除筛选条件
|
||||
function clearCondition(){
|
||||
setKeyword(undefined);
|
||||
setAboutMe("aboutme");
|
||||
Init();
|
||||
// 清除下拉选项
|
||||
menuRef.current && menuRef.current.clearChoose();
|
||||
|
||||
}
|
||||
|
||||
// 全选所有issue
|
||||
function chooseAll(e){
|
||||
setCheckAll(e.target.checked);
|
||||
if(e.target.checked){
|
||||
setAllValue(allIds);
|
||||
}else{
|
||||
setAllValue([]);
|
||||
}
|
||||
}
|
||||
|
||||
// 选择列表里的issue
|
||||
function checkIssues(value){
|
||||
setAllValue(value);
|
||||
if(value.length === allIds.length){
|
||||
setCheckAll(true);
|
||||
}else{
|
||||
setCheckAll(false);
|
||||
}
|
||||
}
|
||||
|
||||
// 取消
|
||||
function cancelUpdate(){
|
||||
setAllValue([]);
|
||||
setCheckAll(false);
|
||||
// 清除下拉选项
|
||||
menuRef.current && menuRef.current.clearChoose();
|
||||
}
|
||||
// 确认修改 allValue updateIds
|
||||
function sureUpdate(){
|
||||
const url = `/v1/${owner}/${projectsId}/issues/batch_update`;
|
||||
axios.patch(url,{
|
||||
assigner_ids: [updateIds && updateIds.assigner_id],
|
||||
ids: allValue,
|
||||
issue_tag_ids: [updateIds && updateIds.issue_tag_ids],
|
||||
milestone_id: updateIds && updateIds.milestone_id,
|
||||
priority_id: updateIds && updateIds.issue_priorities_id,
|
||||
status_id: updateIds && updateIds.status_id
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
Init();
|
||||
cancelUpdate();
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
// 切换页码
|
||||
function changepage(page){
|
||||
setPage(page);
|
||||
}
|
||||
|
||||
function chooseFunc(ids){
|
||||
if(allValue && allValue.length>0){
|
||||
// 将ids保存下来以便修改
|
||||
setUpdateIds(ids);
|
||||
}else{
|
||||
Init(ids);
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="main milepostDetail">
|
||||
{milepost && <FlexAJ>
|
||||
<div>
|
||||
<p className="font-17 font-bd color-black" style={{width: '900px'}}>{milepost.name}</p>
|
||||
<p className="mt7">
|
||||
<span className="mr20">
|
||||
<i className="iconfont icon-a-31shijian font-14 mr5 color-grey-89"></i>
|
||||
<span className="color-grey-89">{milepost.effective_date || '暂无截止时间'}</span>
|
||||
</span>
|
||||
{(milepost.percent || milepost.percent===0) ? <span style={{color: '#1aaf42'}}> {milepost.percent > 0 ? milepost.percent.toFixed(2):milepost.percent}%完成 </span> :"" }
|
||||
</p>
|
||||
</div>
|
||||
<div className="milepostdiv">
|
||||
{
|
||||
(current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${mileId}/edit`} className="grayButton" style={{ marginRight: 15 }}><i className="iconfont icon-lichengbeiicon1 font-12 mr5"></i>编辑里程碑</Link>
|
||||
:""
|
||||
}
|
||||
{
|
||||
current_user && current_user.login ?
|
||||
<Button type='primary' onClick={() => {history.push(`/${owner}/${projectsId}/issues/${mileId}/new`)}} className='createMilepostBtn' style={{width: '83px'}}>+ 创建疑修</Button>
|
||||
:<Button type='primary' onClick={showLoginDialog} className='createMilepostBtn' style={{width: '83px'}}>+ 创建疑修</Button>
|
||||
}
|
||||
</div>
|
||||
</FlexAJ>}
|
||||
<div className="lists mt25">
|
||||
<div className="listheader">
|
||||
<div style={{display:"flex"}}>
|
||||
<Checkbox value="all" style={{marginRight: "16px"}} checked={checkAll} onChange={chooseAll}></Checkbox>
|
||||
{
|
||||
allValue && allValue.length>0 ?
|
||||
<span>选择{allValue.length}个issue</span>
|
||||
:
|
||||
<ul className="statusul">
|
||||
<li className={category === "all" ?"active":""} onClick={()=>setCategory("all")}>全部<span>{total}</span></li>
|
||||
<li className={category === "opened" ?"active":""} onClick={()=>setCategory("opened")}>开启中<span>{openedCount}</span></li>
|
||||
<li className={category === "closed" ?"active":""} onClick={()=>setCategory("closed")}>已关闭<span>{closedCount}</span></li>
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
<div className="menusul">
|
||||
<AllMenus
|
||||
ref={menuRef}
|
||||
update={allValue && allValue.length>0}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
chooseFunc={chooseFunc}
|
||||
/>
|
||||
{
|
||||
allValue && allValue.length>0 ?
|
||||
<div>
|
||||
<Button type="primary" ghost onClick={sureUpdate}>确定</Button>
|
||||
<Button ghost className="ml10 mr10" onClick={cancelUpdate}>取消</Button>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
total === 0 &&
|
||||
<div className="listempty">
|
||||
<img src={issueEmp} alt="" width="68px" />
|
||||
<p className="font-22 mt5 mb10">欢迎使用疑修(Issue)</p>
|
||||
<p className="font-15">疑修用于记录与跟踪待办事项、项目bug、功能需求等。在使用之前,请您先<a className="color-blue">创建一个疑修</a></p>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
total > 0 &&
|
||||
<React.Fragment>
|
||||
<Checkbox.Group name="issues" onChange={checkIssues} value={allValue} style={{ width: "100%" }}>
|
||||
<div className="listdatas">
|
||||
{issueList.map((item,key)=>{
|
||||
return(
|
||||
<Datas
|
||||
key={key}
|
||||
checkbox={ <Checkbox value={item.id} key={item.id} style={{marginRight: "16px"}}></Checkbox> }
|
||||
item={item}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</Checkbox.Group>
|
||||
{
|
||||
total > 10 &&
|
||||
<div className="pt25 pb30" style={{textAlign:"right"}}>
|
||||
<Pagination total={total} current={page} onChange={changepage} showSizeChanger showQuickJumper onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}}/>
|
||||
</div>
|
||||
}
|
||||
</React.Fragment>
|
||||
}
|
||||
{total === undefined && <div style={{height:344,display:"flex",alignItems:"center",justifyContent:"center"}}><Spin /></div> }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default MilepostDetail;
|
|
@ -1,14 +1,15 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Dropdown, Menu, Icon, Pagination, Spin } from 'antd';
|
||||
import { Dropdown, Menu, Icon, Pagination, Spin, Button, Checkbox } from 'antd';
|
||||
import './order.scss';
|
||||
import { FlexAJ } from '../Component/layout';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
|
||||
import AllMenus from "../Issues/Component/allMenus";
|
||||
import NoneData from '../Nodata';
|
||||
import OrderItem from './OrderItem';
|
||||
|
||||
import axios from 'axios';
|
||||
import './milepost.scss';
|
||||
|
||||
/**
|
||||
* issue_chosen:下拉的筛选列表,
|
||||
|
@ -22,6 +23,7 @@ import axios from 'axios';
|
|||
* search_count:列表总条数
|
||||
* issue_type:搜索条件
|
||||
* status_type: issue的关闭和开启,1表示开启中的,2表示关闭的
|
||||
* category: issue状态: 全部、开启、关闭
|
||||
*/
|
||||
class MilepostDetail extends Component {
|
||||
constructor(props) {
|
||||
|
@ -47,7 +49,11 @@ class MilepostDetail extends Component {
|
|||
status_ids: "状态",
|
||||
done_ratios: '完成度',
|
||||
paix: '排序',
|
||||
issueFlag:true
|
||||
issueFlag:true,
|
||||
checkAll: false,
|
||||
allValue: [],
|
||||
allIds: [],
|
||||
category: 'all'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +61,6 @@ class MilepostDetail extends Component {
|
|||
this.getSelectList();
|
||||
const { page } = this.state;
|
||||
this.getIssueList(page);
|
||||
//
|
||||
}
|
||||
|
||||
componentDidUpdate=(prevProps)=>{
|
||||
|
@ -122,7 +127,7 @@ class MilepostDetail extends Component {
|
|||
const { projectsId, meilid , owner } = this.props.match.params;
|
||||
const { limit , order_name , order_type , issue_tag_id , author_id , assigned_to_id , tracker_id , status_id , done_ratio , status_type } = this.state;
|
||||
|
||||
const url = `/${owner}/${projectsId}/milestones/${meilid}.json`;
|
||||
const url = `/v1/${owner}/${projectsId}/milestones/${meilid}.json`;
|
||||
let params = update ? {
|
||||
page, limit , order_name:value , order_type:updateValue , issue_tag_id ,
|
||||
author_id , assigned_to_id , tracker_id , status_id , done_ratio,
|
||||
|
@ -138,7 +143,7 @@ class MilepostDetail extends Component {
|
|||
}).then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
data: result.data,
|
||||
data: result.data.milestone,
|
||||
issues: result.data.issues,
|
||||
search_count: params.status_type ==="1" ? result.data.open_issues_count : result.data.close_issues_count,
|
||||
isSpin: false
|
||||
|
@ -211,7 +216,7 @@ class MilepostDetail extends Component {
|
|||
this.getIssueList(page);
|
||||
}
|
||||
|
||||
openorder = (type) => {
|
||||
category = (type) => {
|
||||
this.setState({
|
||||
status_type: type,
|
||||
issue_tag_id : undefined,
|
||||
|
@ -233,9 +238,18 @@ class MilepostDetail extends Component {
|
|||
|
||||
}
|
||||
|
||||
// 全选所有issue
|
||||
chooseAll = (e) =>{
|
||||
const {allIds} = this.state;
|
||||
this.setState({
|
||||
checkAll: e.target.checked,
|
||||
allValue: e.target.checked ? allIds : []
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const { issue_chosen, issues, limit, page, search_count, data, isSpin , status_type , issueFlag } = this.state;
|
||||
const { issue_chosen, issues, limit, page, search_count, data, isSpin , status_type , issueFlag, checkAll, allValue, category } = this.state;
|
||||
const { projectsId, meilid ,owner} = this.props.match.params;
|
||||
const { current_user , showLoginDialog , projectDetail } = this.props;
|
||||
const menu = (
|
||||
|
@ -247,42 +261,74 @@ class MilepostDetail extends Component {
|
|||
</Menu>
|
||||
)
|
||||
return (
|
||||
<div className="main" style={{padding:"0px"}}>
|
||||
<div className="miledetail">
|
||||
<p className="font-20">{data && data.name}</p>
|
||||
<FlexAJ>
|
||||
<span className="mt7">
|
||||
<span className="mr10">
|
||||
<i className="iconfont icon-rili font-14 mr5">
|
||||
<div className="main milepostDetail">
|
||||
<FlexAJ>
|
||||
<div>
|
||||
<p className="font-17 font-bd color-black" style={{width: '900px'}}>{data && data.name}</p>
|
||||
<p className="mt7">
|
||||
<span className="mr20">
|
||||
<i className="iconfont icon-a-31shijian font-14 mr5 color-grey-89">
|
||||
</i>
|
||||
{
|
||||
data && data.effective_date ?
|
||||
<span >{data && data.effective_date}</span>
|
||||
<span className="color-grey-89">{data && data.effective_date}</span>
|
||||
:
|
||||
<span >暂无截止时间</span>
|
||||
<span className="color-grey-89">暂无截止时间</span>
|
||||
}
|
||||
</span>
|
||||
{data && (data.percent || data.percent===0) ? <span className="font-weight-bold"> {data.percent > 0 ? data.percent.toFixed(2):data.percent}%完成 </span> :"" }
|
||||
</span>
|
||||
<div className="milepostdiv">
|
||||
{data && (data.percent || data.percent===0) ? <span style={{color: '#1aaf42'}}> {data.percent > 0 ? data.percent.toFixed(2):data.percent}%完成 </span> :"" }
|
||||
</p>
|
||||
</div>
|
||||
<div className="milepostdiv">
|
||||
{
|
||||
(current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${meilid}/edit`} className="grayButton" style={{ marginRight: 15 }}><i className="iconfont icon-lichengbeiicon1 font-12 mr5"></i>编辑里程碑</Link>
|
||||
:""
|
||||
}
|
||||
{
|
||||
issueFlag ? (current_user && current_user.login ?
|
||||
<Button type='primary' onClick={() => {this.props.history.push(`/${owner}/${projectsId}/issues/${meilid}/new`)}} className='createMilepostBtn' style={{width: '83px'}}>+ 创建疑修</Button>
|
||||
:<Button type='primary' onClick={showLoginDialog} className='createMilepostBtn' style={{width: '83px'}}>+ 创建疑修</Button>)
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</FlexAJ>
|
||||
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="listheader">
|
||||
<div style={{display:"flex"}}>
|
||||
<Checkbox value="all" style={{marginRight: "16px"}} checked={checkAll} onChange={this.chooseAll}></Checkbox>
|
||||
{
|
||||
(current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
|
||||
<Link to={`/${owner}/${projectsId}/milestones/${meilid}/edit`} className="topWrapper_btn" style={{ marginRight: 15 }} >编辑里程碑</Link>
|
||||
:""
|
||||
}
|
||||
{
|
||||
issueFlag ? (current_user && current_user.login ?
|
||||
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push(`/${owner}/${projectsId}/issues/${meilid}/new`)}} className="topWrapper_btn">创建疑修</CheckProfile>
|
||||
allValue && allValue.length>0 ?
|
||||
<span>选择{allValue.length}个issue</span>
|
||||
:
|
||||
<a className="topWrapper_btn" onClick={showLoginDialog}>创建疑修</a>
|
||||
):""
|
||||
<ul className="statusul">
|
||||
<li className={category === "all" ?"active":""} onClick={() => this.category("all")}>全部<span>{total}</span></li>
|
||||
<li className={category === "opened" ?"active":""} onClick={() => this.category("opened")}>开启中<span>{openedCount}</span></li>
|
||||
<li className={category === "closed" ?"active":""} onClick={() => this.category("closed")}>已关闭<span>{closedCount}</span></li>
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
</FlexAJ>
|
||||
</div>
|
||||
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="pl20 pr20">
|
||||
<div className="menusul">
|
||||
<AllMenus
|
||||
ref={menuRef}
|
||||
update={allValue && allValue.length>0}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
chooseFunc={chooseFunc}
|
||||
/>
|
||||
{
|
||||
allValue && allValue.length>0 ?
|
||||
<div>
|
||||
<Button type="primary" ghost onClick={sureUpdate}>确定</Button>
|
||||
<Button type="danger" ghost className="ml10" onClick={()=>setVisible(true)}>删除</Button>
|
||||
<Button ghost className="ml10 mr10" onClick={cancelUpdate}>取消</Button>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="pl20 pr20">
|
||||
<div className="f-wrap-between pt15 pb15 bor-bottom-greyE">
|
||||
<ul className="topWrapper_type_infos">
|
||||
<li className={status_type==="1" ? "active" : ""} onClick={() => this.openorder("1")}>{data && data.open_issues_count}个开启中</li>
|
||||
|
@ -352,7 +398,7 @@ class MilepostDetail extends Component {
|
|||
<Pagination simple current={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||
</div>:""
|
||||
}
|
||||
</div>
|
||||
</div> */}
|
||||
</Spin>
|
||||
</div>
|
||||
)
|
|
@ -0,0 +1,140 @@
|
|||
import React,{ useState , useEffect , forwardRef ,useImperativeHandle , useRef } from 'react';
|
||||
import Menus from '../../Issues/Component/menus';
|
||||
import axios from 'axios';
|
||||
|
||||
const array =[
|
||||
{id:1,name:"最新创建"},
|
||||
{id:2,name:"最早创建"},
|
||||
{id:3,name:"最新更新"},
|
||||
{id:4,name:"最早更新"}
|
||||
]
|
||||
|
||||
function AllMenus({owner,projectsId,chooseFunc,update},ref){
|
||||
// 列表右侧所有筛选项的值
|
||||
const [ authorList , setAuthorList ] = useState(undefined);
|
||||
const [ author , setAuthor ] = useState(undefined);
|
||||
const [ tagList , setTagList ] = useState(undefined);
|
||||
const [ tag , setTag ] = useState(undefined);
|
||||
const [ chargeList , setChargeList ] = useState(undefined);
|
||||
const [ charge , setCharge ] = useState(undefined);
|
||||
const [ millstone , setMillstone ] = useState(undefined);
|
||||
const [ millstoneList , setMillstoneList ] = useState(undefined);
|
||||
const [ ids , setIds ] = useState({author_id:undefined,issue_priorities_id:undefined,issue_tag_ids:undefined,milestone_id:undefined,sort_by:undefined,status_id:undefined,assigner_id:undefined});
|
||||
const [ names , setNames ] = useState({author_name:undefined,issue_priorities_name:undefined,issue_tag_name:undefined,milestone_name:undefined,sortby_name:undefined,status_name:undefined,assigner_name:undefined});
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
clearChoose: () => {
|
||||
// 父组件按钮:清除筛选条件,将Ids\names里的字段全部改为undefined
|
||||
setIds({author_id:undefined,issue_tag_ids:undefined,issue_priorities_id:undefined,milestone_id:undefined,sort_by:undefined,status_id:undefined,assigner_id:undefined});
|
||||
setNames({author_name:undefined,issue_tag_name:undefined,issue_priorities_name:undefined,milestone_name:undefined,sortby_name:undefined,status_name:undefined,assigner_name:undefined});
|
||||
}
|
||||
}))
|
||||
// 获取发布人列表
|
||||
useEffect(()=>{
|
||||
getSendPerson();
|
||||
},[author])
|
||||
|
||||
function getSendPerson(){
|
||||
const url = `/v1/${owner}/${projectsId}/issue_authors`;
|
||||
axios.get(url,{params:{keyword:author,only_name:true}}).then(result=>{
|
||||
if(result && result.data){
|
||||
setAuthorList(result.data.authors);
|
||||
}
|
||||
})
|
||||
}
|
||||
// 获取标记列表
|
||||
useEffect(()=>{
|
||||
getSign();
|
||||
},[tag])
|
||||
function getSign(){
|
||||
const url = `/v1/${owner}/${projectsId}/issue_tags`;
|
||||
axios.get(url,{params:{keyword:tag,only_name:true}}).then(result=>{
|
||||
if(result && result.data){
|
||||
setTagList(result.data.issue_tags);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 获取负责人列表
|
||||
useEffect(()=>{
|
||||
getCharge();
|
||||
},[charge])
|
||||
|
||||
function getCharge(){
|
||||
const url = `/v1/${owner}/${projectsId}/issue_assigners`;
|
||||
axios.get(url,{params:{keyword:charge,only_name:true}}).then(result=>{
|
||||
if(result && result.data){
|
||||
setChargeList(result.data.assigners);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function choose(id,name){
|
||||
let copy = {...ids,author_id:id.join(",")};
|
||||
let copyname = { ...names,author_name:name}
|
||||
setIds(copy);setNames(copyname);
|
||||
chooseFunc(copy);
|
||||
}
|
||||
|
||||
// 获取里程碑列表
|
||||
useEffect(()=>{
|
||||
getMillstone();
|
||||
},[millstone])
|
||||
|
||||
function getMillstone(){
|
||||
const url = `/v1/${owner}/${projectsId}/milestones`;
|
||||
axios.get(url,{params:{keyword:millstone,only_name:true}}).then(result=>{
|
||||
if(result && result.data){
|
||||
setMillstoneList(result.data.milestones);
|
||||
}
|
||||
})
|
||||
}
|
||||
return(
|
||||
<ul className="dropboxul">
|
||||
{ !update && <Menus
|
||||
update={update}
|
||||
ids={ids && ids.author_id}
|
||||
names={names && names.author_name}
|
||||
name={"发布人" } size={"large"} imgControl
|
||||
lists={authorList} searchFunc={(value)=>setAuthor(value)}
|
||||
chooseFunc={(id,name)=>choose(id,name,'author_name')}
|
||||
/>
|
||||
}
|
||||
<Menus
|
||||
update={update}
|
||||
ids={ids && ids.issue_tag_ids}
|
||||
name={"标记"} size={"large"}
|
||||
double
|
||||
names={names && names.issue_tag_name}
|
||||
lists={tagList} searchFunc={(value)=>setTag(value)}
|
||||
chooseFunc={(id,name)=>{let copy = {...ids,issue_tag_ids:id.join(",")};let copyname = { ...names,issue_tag_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
|
||||
/>
|
||||
<Menus
|
||||
update={update}
|
||||
ids={ids && ids.assigner_id}
|
||||
name={"负责人"} size={"large"} imgControl
|
||||
names={names && names.assigner_name}
|
||||
lists={chargeList} searchFunc={(value)=>setCharge(value)}
|
||||
chooseFunc={(id,name)=>{let copy = {...ids,assigner_id:id.join(",")};let copyname = { ...names,assigner_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
|
||||
/>
|
||||
{ !update && <Menus
|
||||
ids={ids && ids.sort_by}
|
||||
name={"排序"} size={"small"}
|
||||
lists={array}
|
||||
names={names && names.sortby_name}
|
||||
chooseFunc={(id,name)=>{let copy = {...ids,sort_by:id.join(",")};let copyname = { ...names,sortby_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
|
||||
/>
|
||||
}
|
||||
{update && <Menus
|
||||
update={update}
|
||||
ids={ids && ids.milestone_id}
|
||||
name={"里程碑"} size={"large"}
|
||||
names={names && names.milestone_name}
|
||||
lists={millstoneList} searchFunc={(value)=>setMillstone(value)}
|
||||
chooseFunc={(id,name)=>{let copy = {...ids,milestone_id:id.join(",")};let copyname = { ...names,milestone_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
|
||||
/>}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
export default forwardRef(AllMenus);
|
|
@ -0,0 +1,90 @@
|
|||
.milepostBox{
|
||||
border: none;
|
||||
padding: 0;
|
||||
.createMilepost{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.flexSpaceBetween{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.milepostHead{
|
||||
background-color:#fafcff;
|
||||
border:1px solid rgba(42, 97, 255, 0.23);
|
||||
color:#898d9d;
|
||||
padding: 15px 15px 15px 20px;
|
||||
border-radius:4px 4px 0px 0px;
|
||||
.postStatus.active{
|
||||
font-weight:700;
|
||||
color:#333333;
|
||||
}
|
||||
.statusCount{
|
||||
background-color:rgba(70, 106, 255, 0.09);
|
||||
border-radius:10px;
|
||||
margin-left: 5px;
|
||||
padding: 4px 7px;
|
||||
color:#666666;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
.pointBox{
|
||||
cursor: pointer;
|
||||
}
|
||||
.milepostSort{
|
||||
box-shadow:0px 0px 10px rgba(24, 54, 181, 0.17);
|
||||
}
|
||||
.milepostList{
|
||||
border-left: 1px solid #d0d0d0;
|
||||
border-right: 1px solid #d0d0d0;
|
||||
.milepostItemBox{
|
||||
border-bottom: 1px solid #d0d0d0;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
.milepostInfo{
|
||||
display: inline-block;
|
||||
width: 500px;
|
||||
}
|
||||
.actionMileBox{
|
||||
width: 550px;
|
||||
}
|
||||
}
|
||||
.createMilepostBtn{
|
||||
width: 96px;
|
||||
padding: 0;
|
||||
}
|
||||
.primaryColor, .primaryColor:link, .flexSpaceBetween .primaryColor{
|
||||
color: $primary-color;
|
||||
}
|
||||
.effectiveDate, .flexSpaceBetween .effectiveDate{
|
||||
color:#40424a;
|
||||
}
|
||||
.color-grey-89{
|
||||
color: #898d9d;
|
||||
}
|
||||
.colorRed, .colorRed:hover{
|
||||
color:#f30000;
|
||||
}
|
||||
.milestonesNoDate{
|
||||
border:1px solid#d0d0d0;
|
||||
border-top: none;
|
||||
}
|
||||
// 浅灰色按钮
|
||||
.grayButton{
|
||||
width:108px;
|
||||
height:32px;
|
||||
text-align: center;
|
||||
background-color:#fafbfc;
|
||||
border:1px solid #d0d0d0;
|
||||
border-radius:4px;
|
||||
&:hover{
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
}
|
||||
|
||||
// 里程碑详情页面
|
||||
.milepostDetail{
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
|
@ -29,14 +29,6 @@
|
|||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.miledetail {
|
||||
padding:15px 20px;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.topWrapper_nav {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,19 @@ class Index extends Component {
|
|||
}
|
||||
}
|
||||
componentDidMount=()=>{
|
||||
const {defaultFileList} = this.props;
|
||||
if(defaultFileList){
|
||||
const files = [];
|
||||
defaultFileList.map(i=>{
|
||||
files.push({
|
||||
uid: i.id,
|
||||
name: i.title,
|
||||
status: 'done',
|
||||
url: i.url
|
||||
})
|
||||
})
|
||||
this.setState({fileList: files})
|
||||
}
|
||||
this.checkInitFile();
|
||||
}
|
||||
componentDidUpdate=(prevProps)=>{
|
||||
|
|
Loading…
Reference in New Issue