app || h5上传

h5的话任何上传组件都是可以的,app的话需要调用起文件管理,这个就是很麻烦,找了半天没有,本人是结合uView组件库写的,废话不多说,直接上代码!!!!

子组件:

<template>
	<view ref="parent" class="lsj-file" :style="[getStyles]" :class="loding ? 'active' : ''">
		<view ref="lsj" class="hFile" :style="[getStyles]" @click="onClick">
			<slot>
				<view class="defview" :style="[getStyles]">附件上传</view>
			</slot>
		</view>
	</view>
</template>

<script>
	// 查看文档:https://ext.dcloud.net.cn/plugin?id=5459
	import {
		LsjFile
	} from './LsjFile.js'
	export default {
		name: 'Lsj-upload',
		props: {
			// 打印日志
			debug: {
				type: Boolean,
				default: false
			},
			// 自动上传
			instantly: {
				type: Boolean,
				default: false
			},
			// 上传接口参数设置
			option: {
				type: Object,
				default: () => {}
			},
			// 文件大小上限
			size: {
				type: Number,
				default: 10
			},
			// 文件选择个数上限,超出后不触发点击
			count: {
				type: Number,
				default: 2
			},
			loding: {
				type: Boolean,
				default: false
			},
			// 是否允许多选文件
			multiple: {
				type: Boolean,
				default: true
			},
			// 允许上传的文件格式(多个以逗号隔开)
			formats: {
				type: String,
				default: ''
			},
			// input file选择限制
			accept: {
				type: String,
				default: ''
			},
			// 微信选择文件类型 
			//all=从所有文件选择,
			//video=只能选择视频文件,
			//image=只能选择图片文件,
			//file=可以选择除了图片和视频之外的其它的文件
			wxFileType: {
				type: String,
				default: 'all'
			},
			// webviewID需唯一,不同窗口也不要同Id
			childId: {
				type: String,
				default: 'lsjUpload'
			},
			// 文件选择触发面宽度
			width: {
				type: String,
				default: '100%'
			},
			// 文件选择触发面高度
			height: {
				type: String,
				default: '80rpx'
			},

			// top,left,bottom,right仅position=absolute时才需要传入
			top: {
				type: [String, Number],
				default: ''
			},
			left: {
				type: [String, Number],
				default: ''
			},
			bottom: {
				type: [String, Number],
				default: ''
			},
			right: {
				type: [String, Number],
				default: ''
			},
			// nvue不支持跟随窗口滚动
			position: {
				type: String,
				// #ifdef APP-NVUE
				default: 'absolute',
				// #endif
				// #ifndef APP-NVUE
				default: 'static',
				// #endif
			},
		},
		data() {
			return {

			}
		},
		watch: {
			option(v) {
				// #ifdef APP-PLUS
				this.lsjFile && this.show();
				// #endif
			}
		},
		updated() {
			// #ifdef APP-PLUS
			if (this.isShow) {
				this.lsjFile && this.show();
			}
			// #endif
		},
		computed: {
			getStyles() {
				let styles = {
					width: this.width,
					height: this.height
				}
				if (this.position == 'absolute') {
					styles['top'] = this.top
					styles['bottom'] = this.bottom
					styles['left'] = this.left
					styles['right'] = this.right
					styles['position'] = 'fixed'
				}

				return styles
			}
		},
		mounted() {
			this._size = 0;
			let WEBID = this.childId + new Date().getTime();
			this.lsjFile = new LsjFile({
				id: WEBID,
				debug: this.debug,
				width: this.width,
				height: this.height,
				option: this.option,
				instantly: this.instantly,
				// 限制条件
				prohibited: {
					// 大小
					size: this.size,
					// 允许上传的格式
					formats: this.formats,
					// 限制选择的格式
					accept: this.accept,
					count: this.count,
					// 是否多选
					multiple: this.multiple,
				},
				onchange: this.onchange,
				onprogress: this.onprogress,
			});
			this.create();
			// 需判断是否当前页显示
			uni.$on('lsjShow', this.show);
		},
		beforeDestroy() {
			uni.$off('lsjShow', this.show);

			// #ifdef APP-PLUS
			this.lsjFile.dom.close();
			// #endif
		},
		methods: {
			setFiles(array) {
				if (array instanceof Map) {
					for (let [key, item] of array) {
						item['progress'] = 100;
						item['type'] = 'success';
						this.lsjFile.files.set(key, item);
					}
				} else if (Array.isArray(array)) {
					array.forEach(item => {
						if (item.name) {
							item['progress'] = 100;
							item['type'] = 'success';
							this.lsjFile.files.set(item.name, item);
						}
					});
				}
				this.onchange(this.lsjFile.files);
			},
			setData() {
				this.lsjFile && this.lsjFile.setData(...arguments);
			},
			getDomStyles(callback) {
				// #ifndef APP-NVUE
				let view = uni
					.createSelectorQuery()
					.in(this)
					.select('.lsj-file')
				view.fields({
						size: true,
						rect: true
					},
					({
						height,
						width,
						top,
						left,
						right,
						bottom
					}) => {
						uni.createSelectorQuery()
							.selectViewport()
							.scrollOffset(({
								scrollTop
							}) => {
								return callback({
									top: parseInt(top) + parseInt(scrollTop) + 'px',
									left: parseInt(left) + 'px',
									width: parseInt(width) + 'px',
									height: parseInt(height) + 'px'
								})
							})
							.exec()
					}
				).exec()
				// #endif
				// #ifdef APP-NVUE
				const dom = weex.requireModule('dom')
				dom.getComponentRect(this.$refs.lsj, ({
					size: {
						height,
						width,
						top,
						left,
						right,
						bottom
					}
				}) => {
					return callback({
						top: parseInt(top) + 'px',
						left: parseInt(left) + 'px',
						width: parseInt(width) + 'px',
						height: parseInt(height) + 'px',
						right: parseInt(right) + 'px',
						bottom: parseInt(bottom) + 'px'
					})
				})
				// #endif
			},
			show() {
				if (this._size && (this._size >= this.count)) {
					return;
				}
				this.isShow = true;
				// #ifdef APP-PLUS
				this.lsjFile && this.getDomStyles(styles => {
					this.lsjFile.dom.setStyle(styles)
				});
				// #endif
				// #ifdef H5
				this.lsjFile.dom.style.display = 'inline'
				// #endif
			},
			hide() {
				this.isShow = false;
				// #ifdef APP-PLUS
				this.lsjFile && this.lsjFile.dom.setStyle({
					top: '-100px',
					left: '0px',
					width: '1px',
					height: '100px',
				});
				// #endif
				// #ifdef H5
				this.lsjFile.dom.style.display = 'none'
				// #endif
			},
			/**
			 * 手动提交上传
			 * @param {string}name 文件名称,不传则上传所有type等于waiting和fail的文件
			 */
			upload(name) {
				this.lsjFile && this.lsjFile.upload(name);
			},
			/**
			 * @returns {Map} 已选择的文件Map集
			 */
			onchange(files) {
				this.$emit('change', files);
				this._size = files.size;
				return files.size >= this.count ? this.hide() : this.show();
			},
			/**
			 * @returns {object} 当前上传中的对象
			 */
			onprogress(item, end = false) {
				this.$emit('progress', item);
				if (end) {
					setTimeout(() => {
						this.$emit('uploadEnd', item);
					}, 0);
				}
			},
			/**
			 * 移除组件内缓存的某条数据
			 * @param {string}name 文件名称,不指定默认清除所有文件
			 */
			clear(name) {
				this.lsjFile.clear(name);
			},
			// 创建选择器
			create() {
				// 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去,并将此处path改成服务器上的地址
				let path = '/uni_modules/lsj-upload/hybrid/html/uploadFile.html';
				let dom = this.lsjFile.create(path);
				// #ifdef H5
				this.$refs.lsj.$el.appendChild(dom);
				// #endif
				// #ifndef APP-PLUS
				this.show();
				// #endif
				// #ifdef APP-PLUS
				dom.setStyle({
					position: this.position
				});
				dom.loadURL(path);
				setTimeout(() => {
					// #ifdef APP-NVUE
					plus.webview.currentWebview().append(dom);
					// #endif
					// #ifndef APP-NVUE
					this.$root.$scope.$getAppWebview().append(dom);
					// #endif
					this.show();
				}, 300)
				// #endif
			},
			// 点击选择附件
			onClick() {

				if (this._size >= this.count) {
					this.toast(`只允许上传${this.count}个文件`);
					return;
				}

				// #ifdef MP-WEIXIN
				if (!this.isShow) {
					return;
				}
				let count = this.count - this._size;
				this.lsjFile.chooseMessageFile(this.wxFileType, count);
				// #endif
			},
			toast(msg) {
				uni.showToast({
					title: msg,
					icon: 'none'
				});
			}
		}
	}
</script>

<style scoped>
	.active {
		display: none !important;
	}

	.lsj-file {
		display: inline-block;
	}

	.defview {
		background-color: #007aff;
		color: #fff;
		border-radius: 10rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 28rpx;
	}

	.hFile {
		position: relative;
		overflow: hidden;
	}
</style>

父组件:

<template>
	<view class="content">
		<view class="uploadBtn">
			<!-- lsj-upload里面的:width="width" :height="height"  :count="count"上传数量 -->
			<lsj-upload :loding="loding" :count="count" childId="upload1" :option="option" :size="size" :formats="formats"
				:debug="debug" :instantly="instantly" @uploadEnd="onuploadEnd" @change="onChange">
				<!-- class="btn"里面的 :style="{width: width,height: height}" -->
				<view class="btn"
					style="width: 100%;height: 80rpx;background-color: #007AFF;color: #fff;border-radius: 10rpx;display: flex;align-items: center;justify-content: center;font-size: 28rpx;">
					<text>上传文件</text>
				</view>
			</lsj-upload>
			<view class="btn" v-if="loding"
				style="width: 100%;height: 80rpx;background-color: #007AFF;color: #fff;border-radius: 10rpx;display: flex;align-items: center;justify-content: center;font-size: 28rpx;">
				<u-loading-icon color="#fff" text="上传中..." textSize="24"></u-loading-icon>
			</view>
		</view>
		<view v-if="files">
			<view @click="clickItem(item)" style="margin-bottom: 20rpx;" class="list-box" v-for="(item, index) in files">
				<text>{{item.name}}</text>
				<view class="x-shape" @click.stop="deletItem(index)">
					<u-icon name="close" color="#000" size="28"></u-icon>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import storage from '@/common/storage.js'
	export default {
		data() {
			return {
				// 上传接口参数
				option: {
					// 上传服务器地址,需要替换为你的接口地址
					url: 'http://192.168.8.106:8769/portal/system/file/v1/upload?tenantId=-1', // 该地址非真实路径,需替换为你项目自己的接口地址
					type: 'post',
					responseType: 'arrayBuffer',
					// 上传附件的key
					name: 'file',
					// 根据你接口需求自定义请求头,默认不要写content-type,让浏览器自适配
					header: {
						Authorization: storage.getItemSync('token') ? storage.getItemSync('token') : ''
					},
					// 根据你接口需求自定义body参数
					formData: {
						// 'orderId': 1000
					}
				},
				// 上传的时候有动画
				loding: false,
				// 选择文件后是否立即自动上传,true=选择后立即上传
				instantly: true,
				// 必传宽高且宽高应与slot宽高保持一致
				// width: '180rpx',
				// height: '180rpx',
				// 限制允许上传的格式,空串=不限制,默认为空
				formats: '',
				// 文件上传大小限制
				size: 30,
				// 文件数量限制
				count: 2,
				// 是否多选
				multiple: true,
				// 文件回显列表
				files: [],
				// 是否打印日志
				debug: false,
				// 演示用
				tabIndex: 0,
			}
		},
		methods: {
			// 某文件上传结束回调(成功失败都回调)
			onuploadEnd(item) {
				if (item.type === 'success') {
					this.loding = false
					// 更新当前窗口状态变化的文件
					this.files.push(item)
				} else {
					this.loding = false
					return uni.$u.toast('上传失败')
				}
			},
			// 点击每一条上传
			clickItem(item) {
				let obj = JSON.parse(item.responseText)
				obj.token = storage.getItemSync('token')
				this.$api.preview(item.fileId).then(res => {
					uni.navigateTo({
						url: '/pages/FilePreview/FilePreview?url=' + JSON.stringify(obj)
					})
				})
			},
			// 删除每一条
			deletItem(index) {
				this.files.splice(index, 1) // 删除H5后端返回成功的文件数据
			},
			// 文件选择回调
			onChange(files) {
				this.loding = true
			},
		}
	}
</script>

<style>
	.header {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		height: 130rpx;
		line-height: 130rpx;
		text-align: center;
		font-size: 32rpx;
		background-color: #3F536E;
		color: #fff;
		z-index: 9999;
	}

	/* 按钮距离顶部高度 */
	/* 	.content {
		padding-top: 130rpx;
	} */



	.uploadBtn {
		width: 100%;
		height: 80rpx;
		position: relative;
	}

	::v-deep .u-loading-icon__text {
		color: #fff !important;
	}

	// 文件上传
	.list-box {
		width: 100vw;
		height: 80rpx;
		display: flex;
		align-items: center;
		padding: 0 30rpx;
		box-sizing: border-box;
		justify-content: space-between;
		background-color: #eee;
		overflow: hidden;

		.x-shape {
			width: 100rpx;
			height: 80rpx;
			display: flex;
			align-items: center;
			justify-content: center;
		}
	}
</style>

插件地址:全文件上传选择非原生2.0版 - DCloud 插件市场 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值