Add upload listType: picture-card

This commit is contained in:
kasinooya 2016-01-15 15:56:06 +08:00
parent 7aad7ba116
commit 4d0e873c88
3 changed files with 198 additions and 65 deletions

View File

@ -59,6 +59,7 @@ const AntUpload = React.createClass({
dragState: 'drop'
};
},
onStart(file) {
if (this.recentUploadStatus === false) return;
@ -85,6 +86,7 @@ const AntUpload = React.createClass({
this.autoUpdateProgress(0, targetItem);
}
},
autoUpdateProgress(percent, file) {
const getPercent = genPercentAdd();
let curPercent = 0;
@ -95,6 +97,7 @@ const AntUpload = React.createClass({
}, file);
}, 200);
},
removeFile(file) {
let fileList = this.state.fileList;
let targetItem = getFileItem(file, fileList);
@ -105,6 +108,7 @@ const AntUpload = React.createClass({
}
return null;
},
onSuccess(response, file) {
this.clearProgressTimer();
// json
@ -129,6 +133,7 @@ const AntUpload = React.createClass({
});
}
},
onProgress(e, file) {
let fileList = this.state.fileList;
let targetItem = getFileItem(file, fileList);
@ -140,6 +145,7 @@ const AntUpload = React.createClass({
fileList: this.state.fileList
});
},
onError(error, response, file) {
this.clearProgressTimer();
let fileList = this.state.fileList;
@ -149,10 +155,12 @@ const AntUpload = React.createClass({
targetItem.status = 'error';
this.handleRemove(targetItem);
},
beforeUpload(file) {
this.recentUploadStatus = this.props.beforeUpload(file);
return this.recentUploadStatus;
},
handleRemove(file) {
let fileList = this.removeFile(file);
if (fileList) {
@ -162,23 +170,26 @@ const AntUpload = React.createClass({
});
}
},
handleManualRemove(file) {
/*eslint-disable */
file.status = 'removed';
/*eslint-enable */
this.handleRemove(file);
},
onChange(info) {
this.setState({
fileList: info.fileList
});
this.props.onChange(info);
},
getDefaultProps() {
return {
type: 'select',
name: '',
multipart: false,
multiple: false,
action: '',
data: {},
accept: '',
@ -189,6 +200,7 @@ const AntUpload = React.createClass({
className: '',
};
},
componentWillReceiveProps(nextProps) {
if ('fileList' in nextProps) {
this.setState({
@ -196,14 +208,17 @@ const AntUpload = React.createClass({
});
}
},
onFileDrop(e) {
this.setState({
dragState: e.type
});
},
clearProgressTimer() {
clearInterval(this.progressTimer);
},
render() {
let type = this.props.type || 'select';
let props = assign({}, this.props, {

View File

@ -29,7 +29,7 @@ export default React.createClass({
this.props.onRemove(file);
},
componentDidUpdate() {
if (this.props.listType !== 'picture') {
if (this.props.listType !== 'picture' && this.props.listType !== 'picture-card') {
return;
}
this.props.items.forEach(file => {
@ -56,15 +56,25 @@ export default React.createClass({
let progress;
let icon = <Icon type="paper-clip" />;
if (this.props.listType === 'picture') {
icon = (file.status === 'uploading' || (!file.thumbUrl && !file.url))
? <Icon className={prefixCls + '-list-item-thumbnail'} type="picture" />
: (
<a className={prefixCls + '-list-item-thumbnail'}
href={file.url}
target="_blank"><img src={file.thumbUrl || file.url} alt={file.name} /></a>
if (this.props.listType === 'picture' || this.props.listType === 'picture-card') {
if (file.status === 'uploading' || (!file.thumbUrl && !file.url)) {
if (this.props.listType === 'picture-card') {
icon = <div className={prefixCls + '-list-item-uploading-text'}>文件上传中</div>
} else {
icon = <Icon className={prefixCls + '-list-item-thumbnail'} type="picture" />;
}
} else {
icon = (<a className={prefixCls + '-list-item-thumbnail'}
href={file.url}
target="_blank"><img src={file.thumbUrl || file.url} alt={file.name} /></a>
);
}
}
if (file.status === 'uploading') {
progress = (
<div className={prefixCls + '-list-item-progress'}>
@ -81,7 +91,14 @@ export default React.createClass({
<div className={prefixCls + '-list-item-info'}>
{icon}
<span className={prefixCls + '-list-item-name'}>{file.name}</span>
<Icon type="cross" onClick={this.handleClose.bind(this, file)} />
{
this.props.listType === 'picture-card' && file.status !== 'uploading'
? (<span>
<a href={file.url} target="_blank"><Icon type="eye-o" /></a>
<Icon type="delete" onClick={this.handleClose.bind(this, file)} />
</span>)
: <Icon type="cross" onClick={this.handleClose.bind(this, file)} />
}
</div>
{ progress }
</div>

View File

@ -1,4 +1,6 @@
@upload-prefix-cls: ant-upload;
@upload-item: ant-upload-list-item;
@imgupload-size: 78px;
.@{upload-prefix-cls} {
@ -132,72 +134,171 @@
}
}
&-picture &-item {
padding: 8px;
border-radius: @border-radius-base;
border: 1px solid @border-color-base;
height: 66px;
position: relative;
&:hover {
&-picture,
&-picture-card {
.@{upload-item} {
padding: 8px;
border-radius: @border-radius-base;
border: 1px solid @border-color-base;
height: 66px;
position: relative;
&:hover {
background: transparent;
}
}
.@{upload-item}-info {
padding: 0;
}
.@{upload-item}:hover .@{upload-item}-info {
background: transparent;
}
.@{upload-item}-uploading {
border-style: dashed;
}
.@{upload-item}-thumbnail {
width: 48px;
height: 48px;
display: inline-block;
overflow: hidden;
vertical-align: middle;
}
.@{upload-item}-thumbnail img {
width: 48px;
height: 48px;
display: block;
}
.@{upload-item}-thumbnail.anticon:before {
line-height: 48px;
font-size: 24px;
color: #999;
}
.@{upload-item}-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 0 0 8px;
line-height: 42px;
transition: all 0.3s ease;
}
.@{upload-item}-uploading .@{upload-item}-name {
line-height: 28px;
}
.@{upload-item}-progress {
padding-left: 56px;
margin-top: 0;
}
.anticon-cross {
position: absolute;
right: 8px;
top: 8px;
line-height: 1;
}
}
&-picture &-item-info {
padding: 0;
}
&-picture &-item:hover &-item-info {
background: transparent;
}
&-picture &-item-uploading {
border-style: dashed;
}
&-picture &-item-thumbnail {
width: 48px;
height: 48px;
&-picture-card {
display: inline-block;
overflow: hidden;
vertical-align: middle;
}
float: left;
height: @imgupload-size + 18;
&-picture &-item-thumbnail img {
width: 48px;
height: 48px;
display: block;
}
.@{upload-item} {
display: inline-block;
width: @imgupload-size + 18;
height: @imgupload-size + 18;
margin-right: 8px;
margin-top: 0;
}
&-picture &-item-thumbnail.anticon:before {
line-height: 48px;
font-size: 24px;
color: #999;
}
.@{upload-item}-info {
height: auto;
&-picture &-item-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0 0 0 8px;
line-height: 42px;
transition: all 0.3s ease;
}
&:before {
content: ' ';
position: absolute;
width: @imgupload-size;
height: @imgupload-size;
background-color: #808080;
transition: all 0.3s ease;
opacity: 0;
}
&-picture &-item-uploading &-item-name {
line-height: 28px;
}
.anticon-eye-o,
.anticon-delete {
position: absolute;
left: 25px;
top: 40px;
transition: all 0.3s ease;
cursor: pointer;
font-size: 16px;
line-height: 1;
color: #fff;
opacity: 0;
-webkit-font-smoothing: antialiased; /*解决safair和chrome被加粗*/
-webkit-text-stroke-width: 0.2px; /*解决chrome锯齿*/
}
&-picture &-item-progress {
padding-left: 56px;
margin-top: 0;
}
.anticon-delete {
left: 56px;
}
&-picture .anticon-cross {
position: absolute;
right: 8px;
top: 8px;
line-height: 1;
&:hover {
&:before {
opacity: .8;
}
.anticon-eye-o,
.anticon-delete {
opacity: 1;
}
}
}
.@{upload-item}-thumbnail {
width: @imgupload-size;
height: @imgupload-size;
}
.@{upload-item}-thumbnail img {
width: @imgupload-size;
height: @imgupload-size;
}
.@{upload-item}-name {
display: none;
}
.@{upload-item}-uploading {
&.@{upload-item} {
background-color: #fbfbfb;
}
.@{upload-item}-info {
&:before,
.anticon-eye-o,
.anticon-delete {
display: none;
}
}
&-text {
margin-top: 18px;
color: #999;
}
}
.@{upload-item}-progress {
padding-left: 0;
}
}
.@{upload-prefix-cls}-success-icon {