日照项目的居民端小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
13 KiB

import baseComponent from '../helpers/baseComponent'
import classNames from '../helpers/classNames'
baseComponent({
properties: {
prefixCls: {
type: String,
value: 'wux-upload',
},
max: {
type: Number,
value: -1,
observer: 'updated',
},
count: {
type: Number,
value: 9,
observer: 'updated',
},
defaultFileType: {
type: String,
value: 'image',
},
compressed: {
type: Boolean,
value: true,
},
maxDuration: {
type: Number,
value: 60,
},
camera: {
type: String,
value: 'back',
},
sizeType: {
type: Array,
value: ['original', 'compressed'],
},
sourceType: {
type: Array,
value: ['album', 'camera'],
},
url: {
type: String,
value: '',
},
name: {
type: String,
value: 'file',
},
header: {
type: Object,
value: {},
},
formData: {
type: Object,
value: {},
},
uploaded: {
type: Boolean,
value: true,
},
disabled: {
type: Boolean,
value: false,
},
progress: {
type: Boolean,
value: false,
},
listType: {
type: String,
value: 'text',
},
defaultFileList: {
type: Array,
value: [],
},
fileList: {
type: Array,
value: [],
observer(newVal) {
if (this.data.controlled) {
this.setData({
uploadFileList: newVal,
})
}
},
},
controlled: {
type: Boolean,
value: false,
},
showUploadList: {
type: Boolean,
value: true,
},
showRemoveIcon: {
type: Boolean,
value: true,
},
},
data: {
uploadMax: -1,
uploadCount: 9,
uploadFileList: [],
isVideo: false,
},
computed: {
classes: ['prefixCls, disabled, listType', function(prefixCls, disabled, listType) {
const wrap = classNames(prefixCls, {
[`${prefixCls}--${listType}`]: listType,
[`${prefixCls}--disabled`]: disabled,
})
const files = `${prefixCls}__files`
const file = `${prefixCls}__file`
const thumb = `${prefixCls}__thumb`
const remove = `${prefixCls}__remove`
const select = `${prefixCls}__select`
const button = `${prefixCls}__button`
return {
wrap,
files,
file,
thumb,
remove,
select,
button,
}
}],
},
methods: {
/**
* 计算最多可以选择的图片张数
*/
updated() {
const { count, max } = this.data
const { uploadMax, uploadCount } = this.calcValue(count, max)
// 判断是否需要更新
if (this.data.uploadMax !== uploadMax || this.data.uploadCount !== uploadCount) {
this.setData({
uploadMax,
uploadCount,
})
}
},
/**
* 计算最多可以选择的图片张数
*/
calcValue(count, max) {
const realCount = parseInt(count)
const uploadMax = parseInt(max) > -1 ? parseInt(max) : -1
let uploadCount = realCount
// 限制总数时
if (uploadMax !== -1 && uploadMax <= 9 && realCount > uploadMax) {
uploadCount = uploadMax
}
return {
uploadMax,
uploadCount,
}
},
/**
* 从本地相册选择图片或使用相机拍照
*/
onSelect() {
const {
uploadCount,
uploadMax,
sizeType,
sourceType,
uploaded,
disabled,
uploadFileList: fileList,
isVideo,
compressed,
maxDuration,
camera,
} = this.data
const { uploadCount: count } = this.calcValue(uploadCount, uploadMax - fileList.length)
const success = (res) => {
res.tempFilePaths = res.tempFilePaths || [res.tempFilePath]
this.tempFilePaths = res.tempFilePaths.map((item) => ({ url: item, uid: this.getUid() }))
this.triggerEvent('before', {...res, fileList })
// 判断是否取消默认的上传行为
if (uploaded) {
this.uploadFile()
}
}
// disabled
if (disabled) return
// choose video
if (isVideo) {
wx.chooseVideo({
sourceType,
compressed,
maxDuration,
camera,
success,
})
return
}
// choose image
wx.chooseImage({
count,
sizeType,
sourceType,
success,
})
},
/**
* 上传文件改变时的回调函数
* @param {Object} info 文件信息
*/
onChange(info = {}) {
if (!this.data.controlled) {
this.setData({
uploadFileList: info.fileList,
})
}
this.triggerEvent('change', info)
},
/**
* 开始上传文件的回调函数
* @param {Object} file 文件对象
*/
onStart(file) {
const targetItem = {
...file,
status: 'uploading',
}
this.onChange({
file: targetItem,
fileList: [...this.data.uploadFileList, targetItem],
})
},
/**
* 上传文件成功时的回调函数
* @param {Object} file 文件对象
* @param {Object} res 请求响应对象
*/
onSuccess(file, res) {
const fileList = [...this.data.uploadFileList]
const index = fileList.map((item) => item.uid).indexOf(file.uid)
if (index !== -1) {
const targetItem = {
...file,
status: 'done',
res,
}
const info = {
file: targetItem,
fileList,
}
// replace
fileList.splice(index, 1, targetItem)
this.triggerEvent('success', info)
this.onChange(info)
}
},
/**
* 上传文件失败时的回调函数
* @param {Object} file 文件对象
* @param {Object} res 请求响应对象
*/
onFail(file, res) {
const fileList = [...this.data.uploadFileList]
const index = fileList.map((item) => item.uid).indexOf(file.uid)
if (index !== -1) {
const targetItem = {
...file,
status: 'error',
res,
}
const info = {
file: targetItem,
fileList,
}
// replace
fileList.splice(index, 1, targetItem)
this.triggerEvent('fail', info)
this.onChange(info)
}
},
/**
* 监听上传进度变化的回调函数
* @param {Object} file 文件对象
* @param {Object} res 请求响应对象
*/
onProgress(file, res) {
const fileList = [...this.data.uploadFileList]
const index = fileList.map((item) => item.uid).indexOf(file.uid)
if (index !== -1) {
const targetItem = {
...file,
progress: res.progress,
res,
}
const info = {
file: targetItem,
fileList,
}
// replace
fileList.splice(index, 1, targetItem)
this.triggerEvent('progress', info)
this.onChange(info)
}
},
/**
* 上传文件支持多图递归上传
*/
uploadFile() {
if (!this.tempFilePaths.length) return
const { url, name, header, formData, disabled, progress } = this.data
const file = this.tempFilePaths.shift()
const { uid, url: filePath } = file
if (!url || !filePath || disabled) return
this.onStart(file)
this.uploadTask[uid] = wx.uploadFile({
url,
filePath,
name,
header,
formData,
success: (res) => this.onSuccess(file, res),
fail: (res) => this.onFail(file, res),
complete: (res) => {
delete this.uploadTask[uid]
this.triggerEvent('complete', res)
this.uploadFile()
},
})
// 判断是否监听上传进度变化
if (progress) {
this.uploadTask[uid].onProgressUpdate((res) => this.onProgress(file, res))
}
},
/**
* 点击文件时的回调函数
* @param {Object} e 参数对象
*/
onPreview(e) {
this.triggerEvent('preview', {...e.currentTarget.dataset, fileList: this.data.uploadFileList })
},
/**
* 点击删除图标时的回调函数
* @param {Object} e 参数对象
*/
onRemove(e) {
const { file } = e.currentTarget.dataset
const fileList = [...this.data.uploadFileList]
const index = fileList.map((item) => item.uid).indexOf(file.uid)
if (index !== -1) {
const targetItem = {
...file,
status: 'remove',
}
const info = {
file: targetItem,
fileList,
}
// delete
fileList.splice(index, 1)
this.triggerEvent('remove', {...e.currentTarget.dataset, ...info })
this.onChange(info)
}
},
/**
* 中断上传任务
* @param {String} uid 文件唯一标识
*/
abort(uid) {
const { uploadTask } = this
if (uid) {
if (uploadTask[uid]) {
uploadTask[uid].abort()
delete uploadTask[uid]
}
} else {
Object.keys(uploadTask).forEach((uid) => {
if (uploadTask[uid]) {
uploadTask[uid].abort()
delete uploadTask[uid]
}
})
}
},
},
/**
* 组件生命周期函数在组件实例进入页面节点树时执行
*/
created() {
this.index = 0
this.createdAt = Date.now()
this.getUid = () => `wux-upload--${this.createdAt}-${++this.index}`
this.uploadTask = {}
this.tempFilePaths = []
},
/**
* 组件生命周期函数在组件实例进入页面节点树时执
*/
attached() {
const { defaultFileType, defaultFileList, fileList, controlled } = this.data
const uploadFileList = controlled ? fileList : defaultFileList
const isVideo = defaultFileType === 'video'
this.setData({ uploadFileList, isVideo })
},
/**
* 组件生命周期函数在组件实例被从页面节点树移除时执行
*/
detached() {
this.abort()
},
})