Skip to content

Commit e9899ac

Browse files
committed
add vc-upload
1 parent 2bea54c commit e9899ac

File tree

8 files changed

+699
-0
lines changed

8 files changed

+699
-0
lines changed

components/vc-upload/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import upload from './src'
2+
3+
export default upload
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import PropTypes from '../../_util/vue-types'
2+
import BaseMixin from '../../_util/BaseMixin'
3+
import classNames from 'classnames'
4+
import defaultRequest from './request'
5+
import getUid from './uid'
6+
import attrAccept from './attr-accept'
7+
8+
const upLoadPropTypes = {
9+
component: PropTypes.string,
10+
// style: PropTypes.object,
11+
prefixCls: PropTypes.string,
12+
// className: PropTypes.string,
13+
multiple: PropTypes.bool,
14+
disabled: PropTypes.bool,
15+
accept: PropTypes.string,
16+
// children: PropTypes.any,
17+
// onStart: PropTypes.func,
18+
data: PropTypes.oneOfType([
19+
PropTypes.object,
20+
PropTypes.func,
21+
]),
22+
headers: PropTypes.object,
23+
beforeUpload: PropTypes.func,
24+
customRequest: PropTypes.func,
25+
// onProgress: PropTypes.func,
26+
withCredentials: PropTypes.bool,
27+
}
28+
29+
const AjaxUploader = {
30+
mixins: [BaseMixin],
31+
props: upLoadPropTypes,
32+
data () {
33+
this.reqs = {}
34+
return {
35+
uid: getUid(),
36+
}
37+
},
38+
methods: {
39+
onChange (e) {
40+
const files = e.target.files
41+
this.uploadFiles(files)
42+
this.reset()
43+
},
44+
onClick () {
45+
const el = this.$refs.fileInputRef
46+
if (!el) {
47+
return
48+
}
49+
el.click()
50+
},
51+
onKeyDown (e) {
52+
if (e.key === 'Enter') {
53+
this.onClick()
54+
}
55+
},
56+
onFileDrop (e) {
57+
if (e.type === 'dragover') {
58+
e.preventDefault()
59+
return
60+
}
61+
const files = Array.prototype.slice.call(e.dataTransfer.files).filter(
62+
file => attrAccept(file, this.accept)
63+
)
64+
this.uploadFiles(files)
65+
66+
e.preventDefault()
67+
},
68+
uploadFiles (files) {
69+
const postFiles = Array.prototype.slice.call(files)
70+
postFiles.forEach((file) => {
71+
file.uid = getUid()
72+
this.upload(file, postFiles)
73+
})
74+
},
75+
upload (file, fileList) {
76+
if (!this.beforeUpload) {
77+
// always async in case use react state to keep fileList
78+
return setTimeout(() => this.post(file), 0)
79+
}
80+
81+
const before = this.beforeUpload(file, fileList)
82+
if (before && before.then) {
83+
before.then((processedFile) => {
84+
const processedFileType = Object.prototype.toString.call(processedFile)
85+
if (processedFileType === '[object File]' || processedFileType === '[object Blob]') {
86+
this.post(processedFile)
87+
} else {
88+
this.post(file)
89+
}
90+
}).catch(e => {
91+
console && console.log(e); // eslint-disable-line
92+
})
93+
} else if (before !== false) {
94+
setTimeout(() => this.post(file), 0)
95+
}
96+
},
97+
post (file) {
98+
if (!this._isMounted) {
99+
return
100+
}
101+
let { data } = this.$props
102+
if (typeof data === 'function') {
103+
data = data(file)
104+
}
105+
const { uid } = file
106+
const request = this.customRequest || defaultRequest
107+
this.reqs[uid] = request({
108+
action: this.action,
109+
filename: this.name,
110+
file,
111+
data,
112+
headers: this.headers,
113+
withCredentials: this.withCredentials,
114+
onProgress: e => {
115+
this.$emit('progress', e, file)
116+
},
117+
onSuccess: (ret, xhr) => {
118+
delete this.reqs[uid]
119+
this.$emit('success', ret, file, xhr)
120+
},
121+
onError: (err, ret) => {
122+
delete this.reqs[uid]
123+
this.$emit('error', err, ret, file)
124+
},
125+
})
126+
this.$emit('start', file)
127+
},
128+
reset () {
129+
this.setState({
130+
uid: getUid(),
131+
})
132+
},
133+
abort (file) {
134+
const { reqs } = this
135+
if (file) {
136+
let uid = file
137+
if (file && file.uid) {
138+
uid = file.uid
139+
}
140+
if (reqs[uid]) {
141+
reqs[uid].abort()
142+
delete reqs[uid]
143+
}
144+
} else {
145+
Object.keys(reqs).forEach((uid) => {
146+
if (reqs[uid]) {
147+
reqs[uid].abort()
148+
}
149+
150+
delete reqs[uid]
151+
})
152+
}
153+
},
154+
},
155+
mounted () {
156+
this.$nextTick(() => {
157+
this._isMounted = true
158+
})
159+
},
160+
beforeDestroy () {
161+
this._isMounted = false
162+
this.abort()
163+
},
164+
render () {
165+
const {
166+
component: Tag, prefixCls, disabled, multiple, accept,
167+
} = this.$props
168+
const cls = classNames({
169+
[prefixCls]: true,
170+
[`${prefixCls}-disabled`]: disabled,
171+
})
172+
const events = disabled ? {} : {
173+
onClick: this.onClick,
174+
onKeydown: this.onKeyDown,
175+
onDrop: this.onFileDrop,
176+
onDragover: this.onFileDrop,
177+
tabIndex: '0',
178+
}
179+
return (
180+
<Tag
181+
{...events}
182+
class={cls}
183+
role='button'
184+
>
185+
<input
186+
type='file'
187+
ref='fileInputRef'
188+
key={this.uid}
189+
style={{ display: 'none' }}
190+
accept={accept}
191+
multiple={multiple}
192+
onChange={this.onChange}
193+
/>
194+
{this.$slots.default}
195+
</Tag>
196+
)
197+
},
198+
}
199+
200+
export default AjaxUploader

0 commit comments

Comments
 (0)