dev_forge
caicai8 5 years ago
commit b32e1901d7

@ -542,6 +542,40 @@ http://localhost:3000/api/projects/3263.json | jq
``` ```
--- ---
#### 删除项目
```
DELETE api/projects/:id
```
*示例*
```
curl -X DELETE http://localhost:3000/api/projects/3263.json | jq
```
注:只有超级管理员和项目拥有者才能删除仓库
*请求参数说明:*
|参数名|必选|类型|说明|
-|-|-|-
|id |是|int |项目id |
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|status |int|返回状态, 0: 表示操作成功 |
|message |string|返回信息说明|
返回值
```
{
"status": 0,
"message": "success"
}
```
---
#### 项目添加成员 #### 项目添加成员
``` ```
POST api/projects/:id/members POST api/projects/:id/members
@ -1343,7 +1377,8 @@ http://localhost:3000/api/18816895620/mirror_demo | jq
|default_branch |string|仓库默认分支| |default_branch |string|仓库默认分支|
|full_name |string|仓库全名(带用户名)| |full_name |string|仓库全名(带用户名)|
|author |object|提交用户| |author |object|提交用户|
|-- login |string|用户名称| |-- login |string|用户login|
|-- name |string|用户姓名|
|-- image_url |string|用户头像| |-- image_url |string|用户头像|
@ -1373,7 +1408,8 @@ http://localhost:3000/api/18816895620/mirror_demo | jq
"mirror": false, "mirror": false,
"private": false, "private": false,
"author": { "author": {
"name": "18816895620", "login": "18816895620",
"name": "美女",
"image_url": "avatars/User/b" "image_url": "avatars/User/b"
} }
} }

@ -4,10 +4,10 @@ import {Link} from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import Nav from './Nav'; import Nav from './Nav';
import UploadComponent from '../Upload/Index'; import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import{ Modal,Col,Form,Input,Tooltip,Select } from 'antd' import{ Modal,Col,Form,Input,Tooltip,Select } from 'antd'
import NoneData from '../../modules/courses/coursesPublic/NoneData'; import NoneData from '../../modules/courses/coursesPublic/NoneData';
import Attachments from '../Upload/attachment'
const TextArea = Input.TextArea; const TextArea = Input.TextArea;
const Option = Select.Option; const Option = Select.Option;
@ -35,6 +35,8 @@ class CopyDetail extends Component{
priority_id:0, priority_id:0,
done_ratio:0, done_ratio:0,
textcount:"", textcount:"",
fileList:undefined,
get_attachments: undefined
} }
} }
@ -65,7 +67,13 @@ class CopyDetail extends Component{
status_id:result.data.status_id, status_id:result.data.status_id,
priority_id:result.data.priority_id, priority_id:result.data.priority_id,
done_ratio:result.data.done_ratio, done_ratio:result.data.done_ratio,
textcount:result.data.description textcount:result.data.description,
branch_name: result.data.branch_name,
get_attachments: result.data.attachments,
fileList:undefined,
issue_tag_ids: result.data.issue_tags && result.data.issue_tags[0].id,
fixed_version_id: result.data.fixed_version_id,
assigned_to_id: result.data.assigned_to_id
}) })
this.getjournalslist(); this.getjournalslist();
@ -133,6 +141,7 @@ class CopyDetail extends Component{
} }
handleSubmit=()=>{ handleSubmit=()=>{
const { fileList } = this.state;
this.props.form.validateFieldsAndScroll((err, values) => { this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){ if(!err){
const { projectsId,orderId} = this.props.match.params; const { projectsId,orderId} = this.props.match.params;
@ -145,10 +154,11 @@ class CopyDetail extends Component{
} }
axios.put(url,{ axios.put(url,{
project_id:projectsId, project_id:projectsId,
subject:subject, subject:subject,
id: orderId, id: orderId,
description:this.state.textcount, description:this.state.textcount,
attachment_ids:fileList,
...values ...values
}).then(result=>{ }).then(result=>{
if(result){ if(result){
@ -166,176 +176,192 @@ class CopyDetail extends Component{
render(){ render(){
const { projectsId,orderId } = this.props.match.params; const { projectsId,orderId } = this.props.match.params;
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const { issue_tag_ids , fixed_version_id , branch_name , status_id , tracker_id , issue_type ,assigned_to_id , priority_id , done_ratio, const { issue_tag_ids , fixed_version_id , branch_name , status_id , tracker_id , issue_type ,assigned_to_id , priority_id , done_ratio,
issue_chosen , branches } = this.state; issue_chosen , branches, subject, textcount,get_attachments } = this.state;
return( return(
<div className="main"> <div className="main">
<div className="topWrapper"> <div className="topWrapper">
<Nav {...this.props} {...this.state}/> <Nav {...this.props} {...this.state}/>
</div> </div>
<div> <div>
<Form> <Form>
<div className="f-wrap-between mt20" style={{alignItems:"flex-start"}}> <div className="f-wrap-between mt20" style={{alignItems: "flex-start"}}>
<div className="list-right df divwidth" > <div className="list-right df">
<ul className="ul_width"> <Link to={``}><img className="user_img"
<li> src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/></Link>
<div className="df"> <div className="new_context">
<div style={{width:40}}>标题</div> <Form.Item>
<Input value={this.state.subject} style={{marginLeft:25}} size={10} onChange={this.changmodelname}></Input> {getFieldDecorator('subject', {
</div> rules: [{
</li> required: true, message: '请填写工单标题'
<li style={{marginTop:15}}> }],
<div className="df" > initialValue: subject
<Link to={``}><img class="user_img" onClick={this.imgshow} src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/> </Link> })(
<div className="new_context"> <Input placeholder="标题" onChange={this.changmodelname}/>
<TextArea defaultValue={this.state.textcount} style={{height:"200px"}} value={this.state.textcount} onChange={this.changmodelcount}/> )}
<UploadComponent load={this.UploadFunc}></UploadComponent> </Form.Item>
<Form.Item>
<div className="topWrapper"> {getFieldDecorator('description', {
<div className="detail_p"> </div> rules: [],
<a className="topWrapper_btn fr" type="submit" style={{marginLeft:5}} onClick={()=>this.deleteorder(orderId)}>关闭</a> initialValue: textcount
<a className="topWrapper_btn fr" type="submit" style={{marginLeft:5}} onClick={this.handleSubmit}>保存</a> })(
<TextArea placeholder="请输入工单的描述..." style={{height: "300px"}} onChange={this.changmodelcount}/>
)}
</Form.Item>
<UploadComponent load={this.UploadFunc}
showNotification={this.props.showNotification}></UploadComponent>
{
get_attachments ?
<Attachments attachments={get_attachments} showNotification={this.props.showNotification}
canDelete={true}/>
:
""
}
<p className="clearfix mt15 text-right">
<a className="topWrapper_btn fr" type="submit" style={{marginLeft: 5}}
onClick={this.handleSubmit}>保存</a>
<Link to={`/projects/${projectsId}/orders/${orderId}/detail`}
className="a_btn cancel_btn fr">取消</Link>
</p>
</div> </div>
</div> </div>
</div> <div className="list-left" style={{paddingRight: "0px", paddingLeft: "15px", paddingTop: "10px"}}>
</li> <div className="list-l-panel">
</ul> <Form.Item
</div> label="分支"
<div className="list-left DetailRight"> >
<div className="list-l-panel"> {getFieldDecorator('branch_name', {
<Form.Item initialValue: branch_name,
label="分支" rules: [],
> })(
{getFieldDecorator('branch_name', { <Select>
initialValue:0, <Option value={''}>分支未指定</Option>
rules: [], {
})( branches && branches.length > 0 && branches.map((item, key) => {
<Select value={branch_name} > return (
<Option value={0}>分支未指定</Option> <Option value={item}>{item}</Option>
{ )
branches && branches.length >0 && branches.map((item,key)=>{ })
return( }
<Option value={item}>{item}</Option> </Select>
) )}
}) </Form.Item>
} <Form.Item
</Select> label="标签"
)} >
</Form.Item> {getFieldDecorator('issue_tag_ids', {
<Form.Item initialValue: issue_tag_ids ? [issue_tag_ids] : "",
label="标签" rules: [],
> })(
{getFieldDecorator('issue_tag_ids', { <Select>
initialValue:0, <Option value={''}>未选择标签</Option>
rules: [], {this.renderSelect(issue_chosen && issue_chosen.issue_tag)}
})( </Select>
<Select value={issue_tag_ids}> )}
<Option value={0}>未选择标签</Option> </Form.Item>
{ this.renderSelect(issue_chosen && issue_chosen.issue_tag) } <Form.Item
</Select> label="里程碑"
)} >
</Form.Item> {getFieldDecorator('fixed_version_id', {
<Form.Item initialValue: fixed_version_id ? fixed_version_id : "",
label="里程碑" rules: [],
> })(
{getFieldDecorator('fixed_version_id', { <Select>
initialValue:0, <Option value={''}>未选择里程碑</Option>
rules: [], {this.renderSelect(issue_chosen && issue_chosen.issue_version)}
})( </Select>
<Select value={fixed_version_id}> )}
<Option value={0}>未选择里程碑</Option> </Form.Item>
{ this.renderSelect(issue_chosen && issue_chosen.issue_version) } <Form.Item
</Select> label="状态"
)} >
</Form.Item> {getFieldDecorator('status_id', {
<Form.Item initialValue: status_id,
label="状态" rules: [{
> required: true, message: '请选择完成状态'
{getFieldDecorator('status_id', { }],
initialValue:status_id, })(
rules: [{ <Select>
required: true, message: '请选择完成状态' {this.renderSelect(issue_chosen && issue_chosen.issue_status)}
}], </Select>
})( )}
<Select > </Form.Item>
{ this.renderSelect(issue_chosen && issue_chosen.issue_status) } <Form.Item
</Select> label="分类"
)} >
</Form.Item> {getFieldDecorator('tracker_id', {
<Form.Item initialValue: tracker_id,
label="分类" rules: [{
> required: true, message: '请选择分类'
{getFieldDecorator('tracker_id', { }],
initialValue:tracker_id, })(
rules: [{ <Select>
required: true, message: '请选择分类' {this.renderSelect(issue_chosen && issue_chosen.tracker)}
}], </Select>
})( )}
<Select value={tracker_id}> </Form.Item>
{ this.renderSelect(issue_chosen && issue_chosen.tracker) } <Form.Item
</Select> label="指派成员"
)} >
</Form.Item> {getFieldDecorator('assigned_to_id', {
<Form.Item initialValue: assigned_to_id ? assigned_to_id : "",
label="指派成员" rules: [{}],
> })(
{getFieldDecorator('assigned_to_id', { <Select value={assigned_to_id}>
initialValue:assigned_to_id, <Option value={''}>未指派成员</Option>
rules: [{ {this.renderSelect(issue_chosen && issue_chosen.assign_user)}
}], </Select>
})( )}
<Select value={assigned_to_id}> </Form.Item>
<Option value={""}>未指派成员</Option> <Form.Item
{ this.renderSelect(issue_chosen && issue_chosen.assign_user) } label="优先度"
</Select> >
)} {getFieldDecorator('priority_id', {
</Form.Item>
<Form.Item
label="优先度"
>
{getFieldDecorator('priority_id', {
initialValue:priority_id, initialValue: priority_id,
rules: [{ rules: [{
required: true, message: '请选择优先度' required: true, message: '请选择优先度'
}], }],
})( })(
<Select> <Select>
{ this.renderSelect(issue_chosen && issue_chosen.priority) } {this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select> </Select>
)} )}
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label="完成度" label="完成度"
> >
{getFieldDecorator('done_ratio', { {getFieldDecorator('done_ratio', {
initialValue:done_ratio, initialValue: done_ratio,
rules: [{ rules: [{
required: true, message: '请选择完成度' required: true, message: '请选择完成度'
}], }],
})( })(
<Select value={done_ratio}> <Select value={done_ratio}>
{ this.renderSelect(issue_chosen && issue_chosen.done_ratio) } {this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select> </Select>
)} )}
</Form.Item> </Form.Item>
</div> </div>
</div> </div>
</div>
</Form>
</div> </div>
</Form> <Modal
onCancel={this.handleCancel}
visible={this.state.isShow}
width="400px"
footer={
[]
}
bodyStyle={{textAlign: 'center'}}
>
<img className="list_img"
src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg"
alt=""/>
</Modal>
</div> </div>
<Modal
onCancel={this.handleCancel}
visible={this.state.isShow}
width="400px"
footer={
[]
}
bodyStyle={{textAlign:'center'}}
>
<img class="list_img" src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/>
</Modal>
</div>
) )
} }
} }

@ -5,7 +5,7 @@ import axios from 'axios';
import Nav from './Nav'; import Nav from './Nav';
import UploadComponent from '../Upload/Index'; import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import{ Modal,Col,Form,Input,Tooltip,Popconfirm } from 'antd' import {Modal, Col, Form, Input, Tooltip, Popconfirm, Pagination , Spin} from 'antd'
import NoneData from '../../modules/courses/coursesPublic/NoneData'; import NoneData from '../../modules/courses/coursesPublic/NoneData';
import Attachments from '../Upload/attachment' import Attachments from '../Upload/attachment'
@ -26,7 +26,12 @@ class Detail extends Component{
titledisplay:'none', titledisplay:'none',
countvalue:'', countvalue:'',
//是否需要编辑 //是否需要编辑
isedit:'block' isedit:undefined,
fileList:undefined,
limit:10,
page:1,
search_count:undefined,
isSpin:false,
} }
} }
@ -72,12 +77,15 @@ class Detail extends Component{
if(!err){ if(!err){
const { data } = this.state; const { data } = this.state;
const url = `/issues/${data.id}/journals.json`; const url = `/issues/${data.id}/journals.json`;
const { fileList } = this.state;
axios.post(url,{ axios.post(url,{
...values, ...values,
issue_id:data.id, issue_id:data.id,
attachment_ids:fileList
}).then(result=>{ }).then(result=>{
if(result){ if(result){
this.getjournalslist(); this.getjournalslist();
this.props.showNotification("评论成功!");
} }
}).catch(error=>{ }).catch(error=>{
console.log(error); console.log(error);
@ -86,18 +94,20 @@ class Detail extends Component{
}) })
} }
//获取评论信息 //获取评论信息
getjournalslist=()=>{ getjournalslist=(page, limit)=>{
const { data } = this.state; const { data} = this.state;
const url = `/issues/${data.id}/journals.json`; const url = `/issues/${data.id}/journals.json`;
let id=data.id; let id=data.id;
axios.get(url,{ axios.get(url,{
params:{ params:{
id id,page,limit
} }
}).then(result=>{ }).then(result=>{
if(result){ if(result){
this.setState({ this.setState({
journalsdata:result.data journalsdata:result.data,
search_count:result.data.journals_count,
isSpin:false
}) })
} }
}).catch(error=>{ }).catch(error=>{
@ -105,7 +115,7 @@ class Detail extends Component{
}) })
} }
//删除评论信息 //删除工单信息
deletedetail=(id)=>{ deletedetail=(id)=>{
const { projectsId , orderId} = this.props.match.params; const { projectsId , orderId} = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}.json`; const url = `/projects/${projectsId}/issues/${orderId}.json`;
@ -141,6 +151,7 @@ class Detail extends Component{
//修改评论 //修改评论
updatedetail=(id)=>{ updatedetail=(id)=>{
const {page, limit } = this.state;
const {orderId} = this.props.match.params; const {orderId} = this.props.match.params;
const url = `/issues/${orderId}/journals/${id}.json`; const url = `/issues/${orderId}/journals/${id}.json`;
axios.put(url,{ axios.put(url,{
@ -149,19 +160,26 @@ class Detail extends Component{
content:this.state.countvalue content:this.state.countvalue
}).then(result=>{ }).then(result=>{
if(result){ if(result){
this.setState({ // this.setState({
isedit:'block' // journalsdata: 'block'
}) // })
this.getjournalslist(); this.getjournalslist(page, limit);
} }
}).catch(error=>{ }).catch(error=>{
console.log(error); console.log(error);
}) })
} }
// 获取上传后的文件id数组
UploadFunc=(fileList)=>{
this.setState({
fileList
})
}
//删除工单 //删除评论
deleteorder=(id)=>{ deleteorder=(id)=>{
const { orderId} = this.props.match.params; const { orderId} = this.props.match.params;
const { page, limit } = this.state;
const url = `/issues/${orderId}/journals/${id}.json`; const url = `/issues/${orderId}/journals/${id}.json`;
axios.delete(url,{ data: { axios.delete(url,{ data: {
issue_id: orderId, issue_id: orderId,
@ -169,7 +187,7 @@ class Detail extends Component{
} }
}).then((result)=>{ }).then((result)=>{
if(result){ if(result){
this.getjournalslist() this.getjournalslist(page,limit)
} }
}).catch((error)=>{ }).catch((error)=>{
console.log(error); console.log(error);
@ -188,6 +206,39 @@ class Detail extends Component{
}) })
} }
renderJournalList=(list)=>{
if(list && list.length >0){
return(
list.map((item,key)=>{
return(
<div key={key+1} className="journal-list-item">
<span className="font-weight-bold mr3">
{item.detail}
</span>
<span className="mr5 color-grey-9">
{item.old_value.length > 0 ? "更新为" : "新增"}
</span>
<span>
{item.value && item.value.length > 0 ?
item.detail === "标签" ? <span className="issue-tag-show" style={{background: item.value[0].color}}>{item.value[0].name}</span> : item.value
:
"无"
}
</span>
</div>
)
})
)
}else{
return(
<div>
<span>没有评论~</span>
</div>
)
}
}
//复制 //复制
copydetail=()=>{ copydetail=()=>{
const {projectsId,orderId} = this.props.match.params; const {projectsId,orderId} = this.props.match.params;
@ -204,11 +255,31 @@ class Detail extends Component{
}) })
} }
// 翻页
ChangePage=(page)=>{
this.setState({
page,
isSpin:true
})
const {limit} = this.state;
this.getjournalslist(page,limit);
}
render(){ render(){
const { projectsId,orderId} = this.props.match.params; const { projectsId,orderId} = this.props.match.params;
const { data,journalsdata } = this.state; const { data,journalsdata, page, limit, search_count, isSpin, isedit } = this.state;
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
const { current_user } = this.props; const { current_user } = this.props;
const Paginations = (
<React.Fragment>
{
search_count > limit ?
<div className="pt30 mb50 edu-txt-center btp1">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
}
</React.Fragment>
)
const renderList =()=>{ const renderList =()=>{
if(journalsdata && journalsdata.issue_journals && journalsdata.issue_journals.length>0 ){ if(journalsdata && journalsdata.issue_journals && journalsdata.issue_journals.length>0 ){
return( return(
@ -217,38 +288,47 @@ class Detail extends Component{
return( return(
<li> <li>
<div className="df"> <div className="df">
<Link to={``}><img class="user_img" src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/></Link> <Link to={``}><img class="user_img" src={getImageUrl(`images/${item.user_picture && item.user_picture}`)} alt=""/></Link>
<div className="detail_context" > <div className="detail_context" >
<div className="topWrapper_detali"> <div className="topWrapper_detali">
<p className="detail_p"> <p className="ml6 detail_p lineH40">
{item.user_name} {item.user_name}
<span className="color-grey-9">评论于</span> <span className="color-grey-9 ml3 mr3">评论于</span>
<Tooltip title={item.format_time} placement="bottom"> <Tooltip title={item.format_time} placement="bottom">
<span>{item.created_at}</span> <span>{item.created_at}</span>
</Tooltip> </Tooltip>
</p> </p>
<div className="detail_right"> <div className="detail_right" style={{display: current_user && (current_user.admin || current_user.login === item.user_login) ? "block" : "none"}}>
<span onClick={()=>this.editdetail(item.content,'none')} className="detail_edit_action">编辑</span> <span onClick={()=>this.editdetail(item.content,item.id)} className="detail_edit_action">编辑</span>
<Popconfirm placement="bottom" title={'确定要删除当前评论吗'} okText="是" cancelText="否" onConfirm={()=>this.deletedetail(item.id)}> <Popconfirm placement="bottom" title={'确定要删除当前评论吗'} okText="是" cancelText="否" onConfirm={()=>this.deleteorder(item.id)}>
<span className="detail_edit_action">删除</span> <span className="detail_edit_action">删除</span>
</Popconfirm> </Popconfirm>
{/*<i className="iconfont icon-weibiaoti1 font-18 mr3" onClick={()=>this.editdetail(item.content,'none')}></i> */} </div>
{/*<div style={{width:20}}></div>*/}
{/*<Popconfirm placement="bottom" title={'确定要删除当前评论吗'} okText="是" cancelText="否" onConfirm={()=>this.deletedetail(item.id)}>*/}
{/*<i className="iconfont icon-yiguanbi1 font-18 mr3"></i> */}
{/*</Popconfirm>*/}
</div>
</div> </div>
<div className="detail_ptitlecount"> <div className="detail_ptitlecount">
<p style={{display:this.state.isedit}} >{item.content}</p> <div style={{display: (isedit && isedit === item.id) ? "none" : "block"}} >
<div style={{display:this.state.isedit==='none'?'block':'none'}}> {
<TextArea style={{height:"200px"}} value={this.state.countvalue} onChange={this.changmodelname}/> item.content ?
<p className="clearfix mt15"> <div>{item.content}</div>
<a className="topWrapper_btn fr" type="submit" onClick={()=>this.updatedetail(item.id)}>保存</a> :
<a className="Closeor_btn fr" type="submit" onClick={()=>this.editdetail(item.content,'block')}>取消</a> <div>
</p> {this.renderJournalList(item.journal_details)}
</div> </div>
}
{
item && item.attachments.length > 0 ?
<Attachments attachments={item.attachments} showNotification={this.props.showNotification} canDelete={current_user && (current_user.admin || current_user.login === item.user_login)}/>
:
""
}
</div>
<div style={{display: (isedit && isedit === item.id) ? "block" : "none"}}>
<TextArea style={{height:"200px"}} value={this.state.countvalue} onChange={this.changmodelname}/>
<p className="clearfix mt15">
<a className="topWrapper_btn fr" type="submit" onClick={()=>this.updatedetail(item.id)}>保存</a>
<a className="a_btn cancel_btn fr" type="submit" onClick={()=>this.editdetail(item.content,undefined)}>取消</a>
</p>
</div>
</div> </div>
<div style={{display: this.state.display}}> <div style={{display: this.state.display}}>
<div className="div_line" ></div> <div className="div_line" ></div>
@ -257,7 +337,7 @@ class Detail extends Component{
dataSource={valuse} dataSource={valuse}
renderItem={obj => ( renderItem={obj => (
<List.Item> <List.Item>
<img class="list_img" onClick={this.imgshow} src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/> <img class="list_img" onClick={this.imgshow} src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/>
</List.Item> </List.Item>
)} )}
/> */} /> */}
@ -318,36 +398,40 @@ class Detail extends Component{
: :
"" ""
} }
{/*{renderAttachments()}*/}
</div> </div>
</div> </div>
</div> </div>
<div className="f-wrap-between mt5" style={{alignItems:"flex-start"}}> <div className="f-wrap-between mt5" style={{alignItems:"flex-start"}}>
<div className="df item-list-right" > <div className="item-list-right" >
<ul className="ul_width"> <Spin spinning={isSpin}>
{renderList()} <ul className="ul_width">
<li> {renderList()}
<div className="df"> </ul>
<Link to={``}><img class="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/></Link> </Spin>
<div className="new_context">
{ Paginations }
<div className="df">
<Link to={``}><img className="user_img"
src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/></Link>
<div className="new_context">
<Form.Item> <Form.Item>
{getFieldDecorator('content', { {getFieldDecorator('content', {
rules: [{ rules: [{
required: true, message: '请输入内容' required: true, message: '请输入内容'
}], }],
})( })(
<TextArea placeholder="添加评论..." style={{height:"200px"}}/> <TextArea placeholder="添加评论..." style={{height: "200px"}}/>
)} )}
</Form.Item> </Form.Item>
<UploadComponent load={this.UploadFunc}></UploadComponent> <UploadComponent load={this.UploadFunc}></UploadComponent>
<p className="clearfix mt15"> <p className="clearfix mt15">
<a className="topWrapper_btn fr" type="submit" onClick={this.addjournals}>评论</a> <a className="topWrapper_btn fr" type="submit" onClick={this.addjournals}>评论</a>
<a className="Closeor_btn fr" type="submit" onClick={()=>this.closedetail(data&&data.issue_status==="关闭"?2:5)}>{data&&data.issue_status==="关闭"?"开启工单":"关闭工单"}</a> <a className="Closeor_btn fr" type="submit"
onClick={() => this.closedetail(data && data.issue_status === "关闭" ? 2 : 5)}>{data && data.issue_status === "关闭" ? "开启工单" : "关闭工单"}</a>
</p> </p>
</div> </div>
</div> </div>
</li>
</ul>
</div> </div>
<div className="list-left DetailRight mt10"> <div className="list-left DetailRight mt10">
<p> <p>

@ -8,6 +8,7 @@ import { getImageUrl } from 'educoder';
import{ Modal,Col,Form,Input,Tooltip,Select } from 'antd' import{ Modal,Col,Form,Input,Tooltip,Select } from 'antd'
import NoneData from '../../modules/courses/coursesPublic/NoneData'; import NoneData from '../../modules/courses/coursesPublic/NoneData';
import Attachments from '../Upload/attachment'
const TextArea = Input.TextArea; const TextArea = Input.TextArea;
const Option = Select.Option; const Option = Select.Option;
@ -35,7 +36,8 @@ class UpdateDetail extends Component{
priority_id:0, priority_id:0,
done_ratio:0, done_ratio:0,
textcount:"", textcount:"",
fileList:undefined fileList:undefined,
get_attachments: undefined
} }
} }
@ -66,7 +68,13 @@ class UpdateDetail extends Component{
status_id:result.data.status_id, status_id:result.data.status_id,
priority_id:result.data.priority_id, priority_id:result.data.priority_id,
done_ratio:result.data.done_ratio, done_ratio:result.data.done_ratio,
textcount:result.data.description textcount:result.data.description,
branch_name: result.data.branch_name,
get_attachments: result.data.attachments,
fileList:undefined,
issue_tag_ids: result.data.issue_tags && result.data.issue_tags[0].id,
fixed_version_id: result.data.fixed_version_id,
assigned_to_id: result.data.assigned_to_id
}) })
// this.getjournalslist(); // this.getjournalslist();
} }
@ -128,11 +136,15 @@ class UpdateDetail extends Component{
const { projectsId,orderId} = this.props.match.params; const { projectsId,orderId} = this.props.match.params;
const { subject } = this.state; const { subject } = this.state;
const url = `/projects/${projectsId}/issues/${orderId}.json`; const url = `/projects/${projectsId}/issues/${orderId}.json`;
if(values.issue_tag_ids===0){ if(values.issue_tag_ids===0){
values.issue_tag_ids = "" values.issue_tag_ids = ""
}else{ }else{
values.issue_tag_ids = [values.issue_tag_ids] values.issue_tag_ids = [values.issue_tag_ids]
} }
if(values.assigned_to_id===0){
values.assigned_to_id = ""
}
axios.put(url,{ axios.put(url,{
project_id:projectsId, project_id:projectsId,
subject:subject, subject:subject,
@ -158,7 +170,7 @@ class UpdateDetail extends Component{
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
const { current_user } = this.props; const { current_user } = this.props;
const { issue_tag_ids , fixed_version_id , branch_name , status_id , tracker_id , issue_type ,assigned_to_id , priority_id , done_ratio, const { issue_tag_ids , fixed_version_id , branch_name , status_id , tracker_id , issue_type ,assigned_to_id , priority_id , done_ratio,
issue_chosen , branches, subject, textcount } = this.state; issue_chosen , branches, subject, textcount,get_attachments } = this.state;
return( return(
<div className="main"> <div className="main">
<div className="topWrapper"> <div className="topWrapper">
@ -189,23 +201,29 @@ class UpdateDetail extends Component{
)} )}
</Form.Item> </Form.Item>
<UploadComponent load={this.UploadFunc} showNotification={this.props.showNotification}></UploadComponent> <UploadComponent load={this.UploadFunc} showNotification={this.props.showNotification}></UploadComponent>
{
get_attachments ?
<Attachments attachments={get_attachments} showNotification={this.props.showNotification} canDelete={true}/>
:
""
}
<p className="clearfix mt15 text-right"> <p className="clearfix mt15 text-right">
<a className="topWrapper_btn fr" type="submit" style={{marginLeft:5}} onClick={this.handleSubmit}>保存</a> <a className="topWrapper_btn fr" type="submit" style={{marginLeft:5}} onClick={this.handleSubmit}>保存</a>
<Link to={`/projects/${projectsId}/orders/${orderId}/detail`} className="a_btn cancel_btn fr">取消</Link> <Link to={`/projects/${projectsId}/orders/${orderId}/detail`} className="a_btn cancel_btn fr">取消</Link>
</p> </p>
</div> </div>
</div> </div>
<div className="list-left DetailRight"> <div className="list-left" style={{paddingRight:"0px",paddingLeft:"15px",paddingTop:"10px"}}>
<div className="list-l-panel"> <div className="list-l-panel">
<Form.Item <Form.Item
label="分支" label="分支"
> >
{getFieldDecorator('branch_name', { {getFieldDecorator('branch_name', {
initialValue:0, initialValue: branch_name,
rules: [], rules: [],
})( })(
<Select value={branch_name} > <Select>
<Option value={0}>分支未指定</Option> <Option value={''}>分支未指定</Option>
{ {
branches && branches.length >0 && branches.map((item,key)=>{ branches && branches.length >0 && branches.map((item,key)=>{
return( return(
@ -220,11 +238,11 @@ class UpdateDetail extends Component{
label="标签" label="标签"
> >
{getFieldDecorator('issue_tag_ids', { {getFieldDecorator('issue_tag_ids', {
initialValue:0, initialValue: issue_tag_ids ? [issue_tag_ids] : '',
rules: [], rules: [],
})( })(
<Select value={issue_tag_ids}> <Select>
<Option value={0}>未选择标签</Option> <Option value={''}>未选择标签</Option>
{ this.renderSelect(issue_chosen && issue_chosen.issue_tag) } { this.renderSelect(issue_chosen && issue_chosen.issue_tag) }
</Select> </Select>
)} )}
@ -233,11 +251,11 @@ class UpdateDetail extends Component{
label="里程碑" label="里程碑"
> >
{getFieldDecorator('fixed_version_id', { {getFieldDecorator('fixed_version_id', {
initialValue:0, initialValue: fixed_version_id ? fixed_version_id : "",
rules: [], rules: [],
})( })(
<Select value={fixed_version_id}> <Select>
<Option value={0}>未选择里程碑</Option> <Option value={''}>未选择里程碑</Option>
{ this.renderSelect(issue_chosen && issue_chosen.issue_version) } { this.renderSelect(issue_chosen && issue_chosen.issue_version) }
</Select> </Select>
)} )}
@ -265,7 +283,7 @@ class UpdateDetail extends Component{
required: true, message: '请选择分类' required: true, message: '请选择分类'
}], }],
})( })(
<Select value={tracker_id}> <Select>
{ this.renderSelect(issue_chosen && issue_chosen.tracker) } { this.renderSelect(issue_chosen && issue_chosen.tracker) }
</Select> </Select>
)} )}
@ -274,12 +292,10 @@ class UpdateDetail extends Component{
label="指派成员" label="指派成员"
> >
{getFieldDecorator('assigned_to_id', { {getFieldDecorator('assigned_to_id', {
initialValue:assigned_to_id, initialValue: assigned_to_id ? assigned_to_id : "",
rules: [{
}],
})( })(
<Select value={assigned_to_id}> <Select>
<Option value={""}>未指派成员</Option> <Option value={''}>未指派成员</Option>
{ this.renderSelect(issue_chosen && issue_chosen.assign_user) } { this.renderSelect(issue_chosen && issue_chosen.assign_user) }
</Select> </Select>
)} )}

@ -12,7 +12,7 @@
} }
.detail_p{ .detail_p{
display: flex; display: flex;
padding:10px; /*padding:10px;*/
/*width: 80%;*/ /*width: 80%;*/
/*padding-left: 15px;*/ /*padding-left: 15px;*/
/*margin: auto;*/ /*margin: auto;*/
@ -270,6 +270,7 @@
display: flex; display: flex;
/*height: 35px;*/ /*height: 35px;*/
background-color: #eee; background-color: #eee;
align-items: center;
} }
.towwrapper_img_detali{ .towwrapper_img_detali{
display: flex; display: flex;
@ -293,8 +294,9 @@
flex: 1; flex: 1;
border: 1px solid #f4f4f4; border: 1px solid #f4f4f4;
margin-left: 15px; margin-left: 15px;
padding-top: 0px; padding: 10px;
padding-left: 0px; /*padding-top: 0px;*/
/*padding-left: 0px;*/
/*margin-right: 15px;*/ /*margin-right: 15px;*/
position: relative; position: relative;
background: #FFFFFF; background: #FFFFFF;
@ -461,9 +463,15 @@ a.issue-type-button.active:hover{background: #f4f4f4; color: #4CACFF;}
} }
.ml10{margin-left: 10px;} .ml10{margin-left: 10px;}
.lineH32{line-height: 32px;} .lineH32{line-height: 32px;}
.lineH40{line-height: 40px;}
.item-list-right{width: 74%; padding: 10px 15px 10px 0} .item-list-right{width: 74%; padding: 10px 15px 10px 0}
.detail_edit_action{padding:10px; color: #999; cursor: pointer; line-height: 40px;} .detail_edit_action{padding:10px; color: #999; cursor: pointer; line-height: 40px;}
.attachmentsList{ .attachmentsList{
padding: 10px; margin-left:4px;
} }
.paper-clip-color{color:#29bd8b !important} .paper-clip-color{color:#29bd8b !important}
.attachment-list-delete{display: none;}
.attachment-list-div:hover{background-color: #e6f7ff;}
.attachment-list-div:hover .attachment-list-delete{display: block !important;}
.attachment-list-a{color: rgba(0, 0, 0, 0.65) !important;}
.btp1{border-top: 1px solid #f4f4f4;}

@ -17,21 +17,23 @@ class Attachment extends Component{
} }
getDetail=()=>{ getDetail=()=>{
this.setState({ // this.setState({
attachments: this.props.attachments, // attachments: this.props.attachments,
canDelete: this.props.canDelete // canDelete: this.props.canDelete
}) // })
} }
deleteAttachment = (id) => { deleteAttachment = (id) => {
console.log("delte_state",id)
const url = `/attachments/${id}.json` const url = `/attachments/${id}.json`
axios.delete(url, { axios.delete(url, {
}).then((response) => { }).then((response) => {
if (response.data) { if (response.data) {
if (response.data.status === 0) { if (response.data.status === 0) {
this.setState({ this.setState({
Deleted: [...this.state.Deleted, id] Deleted: this.state.Deleted.concat(id)
}); });
this.props.showNotification("附件删除成功")
}else{ }else{
this.props.showNotification(response.data.message) this.props.showNotification(response.data.message)
} }
@ -43,7 +45,8 @@ class Attachment extends Component{
} }
render(){ render(){
const { attachments, canDelete, Deleted } = this.state; const { Deleted } = this.state;
const { attachments, canDelete } = this.props;
return( return(
<div> <div>
{ {
@ -52,16 +55,16 @@ class Attachment extends Component{
{ {
attachments.map((item,key)=>{ attachments.map((item,key)=>{
return( return(
<div style={{display: (Deleted.length > 0 && Deleted.indexOf(item.id)) ? "none" : "block"}}> <div key= {key} style={{display: (Deleted.length > 0 && Deleted.indexOf(item.id)) ? "none" : "block"}} className="mt10 attachment-list-div" >
<Link to={`${item.url}`}> <Link to={`${item.url}`} className="attachment-list-a">
<i className="iconfont icon-fujian mr10 paper-clip-color font-14"></i> <i className="iconfont icon-fujian mr8 paper-clip-color font-12"></i>
<span>{item.title}</span> <span>{item.title}</span>
<span className="color-grey-9 ml20">{item.filesize}</span> <span className="ml20">{item.filesize}</span>
</Link> </Link>
{ {
canDelete ? canDelete ?
<Popconfirm placement="bottom" title={'您确定要删除附件吗'} okText="是" cancelText="否" onConfirm={()=>this.deleteAttachment(item.id)}> <Popconfirm placement="bottom" title={'您确定要删除附件吗'} okText="是" cancelText="否" onConfirm={()=>this.deleteAttachment(item.id)}>
<span className="color-grey-9 fr" ><i className="iconfont icon-lajitong mr10 color-grey-9 font-14"></i></span> <span className="attachment-list-delete fr" ><i className="iconfont icon-lajitong mr10 color-grey-9 font-14"></i></span>
</Popconfirm> </Popconfirm>
: :
"" ""

Loading…
Cancel
Save