uniapp图片上传组件

文章描述:

uniapp封装图片上传组件,图片上传后可以预览以及删除

 

 

上传成功

 

图片预览

main.js

配置接口访问地址和图片访问地址

Vue.prototype.$baseUrl="http://localhost:10005"
Vue.prototype.$baseUrl_imgs="http://localhost:10005"

 

组件

components/m-upload/m-upload.vue

<template>
	<view class="s-add-list">
		<view class="s-add-list-items" :style="{
				height: size[0],
				width: size[1]
			}" v-for="(item, index) in imageList" :key="index">
			<image :src="item[filedImage]" :url="item.url" @click="showImgs(index)" class="s-add-list-img"
				:mode="imgMode"></image>
			<view class="s-add-list-remove s-icons icon-close" @tap.stop="removeImg" :id="'s-items-img-' + index">
				<icon type="clear" :color="closeColor"></icon>
			</view>
			<view class="upload-progress" :style="{ width: size[1] }">
				<progress :percent="item.progress" :stroke-width="progressSize" :activeColor="progressColor"
					:backgroundColor="progressBgColor" />
			</view>
			<view class="s-add-list-reup" @tap.stop="retry" :data-index="index" v-if="item.error">
				<text class="s-add-list-reup-icon s-icons icon-retry"></text>
				<text class="s-add-list-reup-text">{{ item.errorInfo }}</text>
			</view>
		</view>
		<view class="s-add-list-items s-add-list-btn" :style="{
				height: size[0],
				width: size[1],
				backgroundColor: backgroundColor
			}" :class="disabled ? 's-disabled' : ''" @tap="addImg" v-if="imageList.length < number">
			<slot name="icon"></slot>
			<view class="s-add-list-btn-text">{{ title }}</view>
		</view>
	</view>
</template>
<script>
	export default {
		props: {
			// 图片字段
			filedImage: {
				type: String,
				default: 'url'
			},
			// 背景颜色
			backgroundColor: {
				type: String,
				default: '#f7f7f7'
			},
			// 是否禁用
			disabled: {
				type: Boolean,
				default: false
			},
			// 上传数量
			number: {
				type: Number,
				default: 9
			},
			// 按钮名称
			title: {
				type: String,
				default: '添加工作照片'
			},
			// 上传文字颜色
			titleColor: {
				type: String,
				default: "#666"
			},
			// 图片大小
			size: {
				type: Array,
				default: () => ['222rpx', '222rpx']
			},
			// 上传前钩子
			beforeUpload: {
				type: Function
			},
			// 关闭按钮颜色
			closeColor: {
				type: String,
				default: "#666"
			},
			// 服务器地址
			url: {
				type: String,
				default: ''
			},

			// 进度条进度
			progressSize: {
				type: Number,
				default: 5
			},
			// 进度条颜色
			progressColor: {
				type: String,
				default: "#2079ff"
			},
			// 进度条背景颜色
			progressBgColor: {
				type: String,
				default: "#666"
			},
			// 上传文件名称
			fileName: {
				type: String,
				default: 'file'
			},
			// 携带的form数据
			formData: {
				type: Object,
				default: () => {
					return {};
				}
			},
			// 图片模式
			imgMode: {
				type: String,
				default: 'widthFix'
			},
			// 携带的请求头
			header: {
				type: Object,
				default: () => {
					return {};
				}
			}
		},
		data() {
			return {
				imageList: [],
				upDate: false
			};
		},
		watch: {
			imageList(newVal, oldVal) {
				if (!this.upDate) {
					this.$emit('change', newVal);
				}
			}
		},
		methods: {
			clearAllImgs() {
				this.imageList = [];
			},
			/* addImg() {
				if (this.disabled) return;
				let num = this.number - this.imageList.length;
				if (num < 1) {
					return false;
				}
				uni.chooseImage({
					count: num,
					sizeType: ['compressed'],
					success: async res => {
						let file = res.tempFiles;
						for (let i = 0; i < res.tempFilePaths.length; i++) {
							if (this.beforeUpload) {
								const valid = await this.beforeUpload(file[i], i);
								if (valid === false) {
									return false;
								}
							}
							// this.imageList.push({ url: res.tempFilePaths[i], progress: 0, error: false });
							let quality = 80;
							// this.imageList.push({ url: res.tempFilePaths[i], progress: 0, error: false });
							console.log("设置压缩质量",quality);
							uni.compressImage({
							    src: res.tempFilePaths[i],
							    quality: quality, // 设置压缩质量
							    success: compressRes => {
							        this.imageList.push({ url: compressRes.tempFilePath, progress: 0, error: false });
							    }
							});
						}
					}
				});
			},*/
			/**
			 *在上传文件时,需要压缩图片
			 *还需动态的根据 图片越大压缩比率越高,图片越小压缩比率越小【还需测试】
			 **/

			addImg() {
				if (this.disabled) return;
				let num = this.number - this.imageList.length;
				if (num < 1) {
					return false;
				}
				uni.chooseImage({
					count: num,
					sizeType: ['compressed'],
					success: async res => {
						let file = res.tempFiles;
						for (let i = 0; i < res.tempFilePaths.length; i++) {
							if (this.beforeUpload) {
								const valid = await this.beforeUpload(file[i], i);
								if (valid === false) {
									return false;
								}
							}
							if (file[i].size > 70 * 1024) { // 判断图片大小是否超过70KB
								uni.getImageInfo({
									src: res.tempFilePaths[i],
									success: imageInfo => {
										let width = imageInfo.width;
										let height = imageInfo.height;
										let maxSize = Math.max(width, height);
										let quality = 80;
										if (maxSize > 1024) {
											let ratio = maxSize / 1024;
											quality = Math.floor(80 / ratio);
										}
										console.log("设置压缩质量", quality);
										uni.compressImage({
											src: res.tempFilePaths[i],
											quality: quality, // 设置压缩质量
											success: compressRes => {
												this.imageList.push({
													url: compressRes
														.tempFilePath,
													progress: 0,
													error: false
												});
											}
										});
									}
								});
							} else {
								this.imageList.push({
									url: res.tempFilePaths[i],
									progress: 0,
									error: false
								}); // 不压缩,直接添加到imageList中
							}
						}
					}
				});
			},
			removeImg(e) {
				let index = e.currentTarget.id.replace('s-items-img-', '');
				let removeImg = this.imageList.splice(index, 1);
				this.$emit('remove', removeImg[0]);
			},
			showImgs(e) {
				let imgs = [];
				for (let i = 0; i < this.imageList.length; i++) {
					imgs.push(this.imageList[i][this.filedImage]);
				}
				uni.previewImage({
					urls: imgs,
					current: e
				});
			},
			upload(index) {
				if (this.upDate) {
					return;
				}
				this.upDate = true;
				if (!index) {
					index = 0;
				}
				uni.showLoading({
					title: '图片上传中···'
				});
				this.uploadBase(index);
			},
			retry(e) {
				let index = e.currentTarget.dataset.index;
				this.upload(index);
			},
			uploadBase(index) {
				// 全部上传完成
				if (index > this.imageList.length - 1) {
					uni.hideLoading();
					this.upDate = false;
					this.$emit('upload', this.imageList);
					return;
				}
				// 验证后端
				if (this.url == '') {
					uni.showToast({
						title: '没有配置api',
						icon: 'none'
					});
					return;
				}
				// 检查是否是默认值
				if (this.imageList[index].progress >= 1) {
					this.uploadBase(index + 1);
					return;
				}
				this.imageList[index].error = false;
				// 创建上传对象
				const upTask = uni.uploadFile({
					url: this.url,
					filePath: this.imageList[index].url,
					name: 'file' || this.fileName,
					// formData: this.formData,
					header: this.header,
					success: res => {
						// console.log(res)
						var uploadRes = JSON.parse(res.data);
						console.log(uploadRes)
						if(uploadRes.code == 200)
						{
							this.imageList[index].progress = 100;
							this.imageList[index].url = `${this.$baseUrl_imgs}/` + uploadRes.data.detault_url;
							this.imageList[index].result = uploadRes.data.detault_url;
							this.uploadBase(index + 1);
						}
						if(uploadRes.code == 400){
							uni.showToast({
								title: '上传失败 : ' + uploadRes.msg,
								icon: 'none'
							});
						}
						
					},
					fail: e => {
						uni.showToast({
							title: '上传失败,请点击图片重试',
							icon: 'none'
						});
						this.error(index);
						this.imageList[index].errorInfo = '失败,请重试!';
					}
				});
				upTask.onProgressUpdate(res => {
					if (res.progress > 0) {
						this.imageList[index].progress = res.progress;
						this.imageList.splice(index, 1, this.imageList[index]);
					}
				});

			},
			// 上传错误
			error(index) {
				this.upDate = false;
				this.imageList[index].error = true;
				this.uploadBase(index + 1);
				this.$emit('uploaderror');
			},
			// 设置默认值
			setItems(items) {
				if (items.length) {
					this.imageList = [];
					for (let i = 0; i < items.length; i++) {
						if (items[i] !== 'undefined' || items[i] !== undefined) {
							this.imageList.push({
								url: `${this.$baseUrl_imgs}` + items[i],
								result: items[i],
								progress: 100
							});
						}
					}
				}
			}
		}
	};
</script>

<style lang="scss" scoped>
	.s-disabled {
		cursor: not-allowed;
	}

	.s-add-list {
		display: flex;
		flex-wrap: wrap;
	}

	.s-add-list-btn {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.s-add-list-btn-text {
		font-size: 26rpx;
		line-height: 36rpx;
		text-align: center;
		color: #999;
		width: 100%;
	}

	.s-add-list-items {
		width: 222rpx;
		height: 222rpx;
		overflow: hidden;
		margin-bottom: 6rpx;
		margin-right: 11rpx;
		background: #f6f7f8;
		font-size: 0;
		position: relative;
		border-radius: 6rpx;
	}

	.s-add-list-image {
		width: 222rpx;
	}

	.s-add-list-remove {
		position: absolute;
		z-index: 15;
		right: 10rpx;
		top: 0;
		color: #888888;
	}

	.upload-progress {
		position: absolute;
		z-index: 99;
		left: 0;
		bottom: 0rpx;
		// width: 180rpx;
		padding: 0 2rpx;
	}

	.s-add-list-reup {
		position: absolute;
		z-index: 3;
		left: 0;
		top: 0rpx;
		width: 222rpx;
		height: 222rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: rgba(0, 0, 0, 0.3);
		flex-direction: column;
	}

	.s-add-list-reup-icon {
		text-align: center;
		width: 100%;
		color: #ffffff;
		display: block;
		font-size: 80rpx;
		line-height: 100rpx;
	}

	.s-add-list-reup-text {
		text-align: center;
		width: 100%;
		color: #ec0b0b;
		display: block;
		font-weight: bold;
		font-size: 30rpx;
		line-height: 30rpx;
	}

	.s-add-list-img {
		width: 100%;
		height: 100%;
	}
</style>

 

vue页面使用

<template>
	<view class="service">
			<view class="service_title">图片上传<span class="jh">*</span><span class="dcts">(最多4张)</span></view>
			<view class="service_content">
				<view label="限制上传图片格式/大小">
					<m-upload :url="upPicUrl" :header="headerUpload" :fileName="file" ref="upload3" title="添加图片"
						@upload="handleLoaded3" @change="handleChange3" :number="4"  :formData="formData">
						<template v-slot:icon>
							<text class="s-add-list-btn-icon">+</text>
						</template>
					</m-upload>
				</view>
			
			</view>
	</view>
	
</template>

<script>
export default{
	data(){
		return{
			upPicUrl: `${this.$baseUrl}/index/upload`,
			init_photos: [],
			headerUpload: {
				'token': uni.getStorageSync('token')
			},
			type:0,
			formData: {
				type:0
			},
			upload_site_photos:[]
		}
	},
	methods:{
		handleChange3() {
				this.$refs.upload3.upload();
		},

		// 获取上传或者预览后的图片
		handleLoaded3(arr) {
			console.log("获取上传或者预览后的图片:")
			console.log(arr)
			var imageStr = "";
			for (var i = 0; i < arr.length; i++) {
					imageStr += arr[i].result + ",";
			}
			//去掉最后一个逗号
			if (imageStr.length > 0) {
				imageStr = imageStr.substr(0, imageStr.length - 1);
			}
			console.log(imageStr);
			this.upload_site_photos = imageStr
		}
	}
}
</script>

<style lang="scss">

</style>

 

后端

common.php

<?php
// 应用公共文件
/**
 * 成功返回
 *
 * @param array  $data 数据
 * @param string $msg  提示
 * @param int    $code 返回码
 *
 * @return json
 */
function success($data = [], $msg = RetCodeUtils::SUCCESS_MSG, $code = RetCodeUtils::SUCCESS)
{
    $res['code'] = $code;
    $res['msg']  = $msg;
    $res['data'] = $data;

    return json($res);
}

/**
 * 错误返回
 *
 * @param array  $data 数据
 * @param string $msg  提示
 * @param int    $code 返回码
 *
 * @return json
 */
function error($msg = RetCodeUtils::ERROR_MSG, $data = [], $code = RetCodeUtils::ERROR)
{
    $res['code'] = $code;
    $res['msg']  = $msg;
    $res['data'] = $data;

    return json($res);
}

/**
 * 错误返回(调试使用)
 *
 * @param array  $data 数据
 * @param string $msg  提示
 * @param int    $code 返回码
 *
 * @return json
 */
function error_e($data = [], $msg = RetCodeUtils::ERROR_MSG, $code = RetCodeUtils::ERROR)
{
    $res['code'] = $code;
    $res['msg']  = $msg;
    $res['time'] = time();
    $res['data'] = $data;

    print_r(json_encode($res, JSON_UNESCAPED_UNICODE));

    exit;
}

 

upload方法

public function upload()
    {
        if ($this->request->isPost()) {
            $file = request()->file('file');
            // 上传到本地服务器
            $extension = $file->getOriginalExtension();

            $arr = array('jpg','png');
            $boolvalue = in_array($extension,$arr,false);
            if(!$boolvalue){
                $data['message'] = '请上传正确格式';
                return error($data['message'],'',400);
            }

            $savename = \think\facade\Filesystem::disk('public')->putFile( 'file', $file);

            //获取文件路径
            $path = '/storage/'.$savename;

            //echo $path;
            $path = str_replace('\\','/',$path);

            $data['detault_url'] = $path;
            return success($data,'上传成功',200);
        }
    }

 

 

发布时间:2023/12/17

发表评论