UNPKG

magiccube-vue3

Version:

vue3-js版组件库

179 lines (171 loc) 5.68 kB
/** * TODO * 基本功能已实现,遗留问题: * 1 多个图片时,删除报错(*) * 2 何时需要清空上传的value值 * 3 onProgress函数 * 4 less 文件,default.min.css 如何生成(*) */ import '../../style/upload.less' import { computed, ref } from 'vue' import $post from '../import/ajax' const McUpload = { name: 'McUpload', props: { // 必传 modelValue: [String, Array], url: String, // 上传的文件地址 // 非必传 width: { type: [String, Number], default: 240 }, height: { type: [String, Number], default: 152 }, multi: { type: Boolean, default: false }, headers: { type: Object, default: () => { } }, params: { type: Object, default: () => { } }, max: { // 最多展示几个 type: [Number, String], default: 1 }, disabled: Boolean, customResponse: Function, }, emits: ['update:modelValue', 'preview', 'change'], setup(props, { emit, slots }) { const model = computed({ get() { return props.modelValue && typeof props.modelValue === 'string' ? [props.modelValue] : (props.modelValue || []) }, set(value) { emit('update:modelValue', value) } }) /** * TODO * uploadInput.value.value = '' 可以清空上传的文件值 */ const uploadInput = ref(null) /** * 预览图片 */ const handleRemove = (url) => { const ary = model.value const i = ary.indexOf(url) if (i > -1) ary.splice(i, 1) model.value = ary } const handlePreview = (url) => emit('preview', url) const getSize = (size) => { if(!size) return '' let _s = size if(typeof size === 'number'){ _s = size.toString() } return _s.indexOf('%') > -1? _s : _s + 'px' } const previewNode = (url) => ( <div class="mc-upload-preview" style={{ width: getSize(props.width), height: getSize(props.height) || getSize(props.width), cursor: props.disabled? 'default' : 'pointer' }} onClick={() => handlePreview(url)}> <img src={url} /> { props.disabled? '' : <div class="mc-upload-preview__close" onClick={() => handleRemove(url)}></div> } </div> ) /** * 上传图片 */ const handleChange = (e) => { if(props.disabled) return false loading.value = true const file = props.multi ? e.target.files : e.target.files[0] const options = { headers: props.headers, action: props.url, multi: props.multi, file, extraParams: props.params, onSuccess: res => { loading.value = false // 自定义处理请求返回值(主要用于第三方上传后的处理) if(props.customResponse){ props.customResponse(res) return } if (res.code === 200) { const url = res.data && res.data.url ? res.data.url : '' handleSuccess({ url, res, file }) } else { throw new Error('上传失败') } }, onError: err => { loading.value = false throw new Error('上传失败') } } $post(options) } const handleSuccess = ({ url, res, file }) => { const max = Number(props.max) model.value = max > 1 ? [...model.value, url] : url emit('change', { url, res, file }) } const loading = ref(false) const actionNode = () => ( <div v-loading={loading.value} class="mc-upload-action" style={{ width: getSize(props.width), height: getSize(props.height) || getSize(props.width) }}> { slots.placeholder? slots.placeholder() : <span class="mc-upload-action__arrow"></span> } <input class="mc-upload-action__inner" ref={uploadInput} type="file" accept="image/*" onChange={handleChange} disabled={props.disabled} multiple={props.multi} /> </div> ) return () => ( <div class="mc-upload"> <div class="mc-upload__wrap"> { model.value?.length ? model.value.map(url => previewNode(url)) : '' } { model.value.length < Number(props.max) ? actionNode() : '' } </div> </div> ) } } McUpload.install = (app) => { app.component(McUpload.name, McUpload) } export { McUpload, McUpload as default }