一、图片上传
内容:通过对uniapp提供的文件上传组件进行二次封装
思路:将上传成功后获取接口返回的数据进行处理
注意:token,上传路径,父子组件之间传递的值是否一致
将组件命名为 image-upload
<template>
<uni-file-picker
v-if="!disabled"
:auto-upload="true"
:limit="limit"
v-model="imageValue"
fileMediatype="image"
mode="grid"
@select="select"
@progress="progress"
@success="success"
@fail="fail"
:title="'最多选择' + limit + '张图片'"
/>
<view v-else class="preview">
<img
v-for="(item, i) in imageValue"
@click="previewImage(item.url)"
class="viewImg"
:src="item.url"
:key="i"
/>
</view>
</template>
<script>
import { baseUrl } from "@/config"; // 默认路径
export default {
props: {
value: {
default: "",
},
// 上传张数
limit: {
default: "9",
},
disabled: {
default: false,
// default: true,
},
},
data() {
return {
imageValue: [],
};
},
watch: {
value: {
handler(val, oval) {
// 监听父组件的值,时并实时赋值给imageValue
if (val && val != oval) {
this.imageValue = [];
let arr = val.split(",");
if (arr) {
arr.forEach((item) => {
this.imageValue.push({
url: item,
});
});
}
}
},
deep: true, //是否深度监听
immediate: true, //是否监听初始值
},
imageValue: {
handler(val, oval) {
// 监听imageValue的值(删除图片,上传图片),并同步给父组件
if (val.length >= 0) {
let arr = [];
val.forEach((item) => {
arr.push(item.url);
});
const str = arr.join(",");
this.$emit("input", str); // 同步给父组件
}
},
deep: true, //是否深度监听
immediate: true, //是否监听初始值
},
},
methods: {
updata(filePath) {
const that = this;
// const accessToken = uni.getStorageSync("Authorization") || null; //获取token
uni.uploadFile({
url: baseUrl + "api/App/CDN/UploadImg", // 上传路径
filePath: filePath,
header: {
// 请求头,不需要可以不传
// Authorization: `Bearer ${accessToken}`,
},
formData: {
// 其他需要携带的参数,没有可以不传
},
success(res) {
// 上传成功,返回值是后端返回的值,组件以json格式获取到值,所以需要转换成对象
let response = JSON.parse(res.data);
// console.log("=======上传图片完成======>", response);
if (response.data.url != undefined) {
// 判断上传成功与否,也可以通过状态码进行判断
// 把后端返回的上传后的图片路径组装成字符串,传递给父组件
let str;
if (that.value) {
str = that.value + "," + response.data.url;
} else {
str = response.data.url;
}
that.$emit("input", str); // 同步给父组件
uni.showToast({
title: "上传图片成功",
duration: 2000,
});
} else {
uni.showToast({
title: "上传图片失败,请重试!",
icon: "none",
duration: 2000,
});
}
},
fail(err) {
console.log("=======上传图片失败======>", err);
uni.showToast({
title: "上传图片失败,请重试!",
icon: "none",
duration: 2000,
});
},
});
},
// 获取上传状态
select(e) {
// console.log("选择文件:", e);
e.tempFilePaths.forEach((item) => {
this.updata(item);
});
},
// 获取上传进度
progress(e) {
console.log("上传进度:", e);
},
// 上传成功
success(e) {
console.log("上传成功");
},
// 上传失败
fail(e) {
console.log("上传失败:", e);
},
previewImage(url) {
// 预览图片
uni.previewImage({
urls: [url],
});
},
},
};
</script>
<style lang="scss" scoped>
.preview {
display: grid;
grid-template-columns: 240rpx 240rpx 240rpx;// 三列
/* 设置间距 */
grid-gap: 20rpx;
.viewImg {
width: 240rpx;
height: 240rpx;
}
}
</style>
二、上传文件
思路与上传图片一样
将上传文件组件命名为file-upload
<template>
<uni-file-picker
:limit="limit"
v-model="filesValue"
mode="grid"
file-mediatype="all"
:disabled="disabled"
@select="select"
@progress="progress"
@success="success"
@fail="fail"
:del-icon="!disabled"
>
<uni-button v-if="disabled"></uni-button>
</uni-file-picker>
</template>
<script>
import { baseUrl } from "@/config";
export default {
props: {
value: {
default: "",
},
// 上传数
limit: {
default: "9",
},
disabled: {
default: false,
},
},
data() {
return {
filesValue: [],
};
},
watch: {
value: {
handler(val, oval) {
if (val && val != oval) {
this.filesValue = [];
let arr = val.split(",");
if (arr) {
arr.forEach((item) => {
let name = item.split("/").pop(); // 文件名
let extname = name.split(".")[1]; // 后缀名
this.filesValue.push({
url: item,
name,
extname,
});
});
}
}
},
deep: true, //是否深度监听
immediate: true, //是否监听初始
},
filesValue: {
handler(val, oval) {
if (val.length > 0) {
let arr = [];
val.forEach((item) => {
arr.push(item.url);
});
const str = arr.join(",");
this.$emit("input", str);
} else {
this.$emit("input", "");
}
},
deep: true, //是否深度监听
immediate: true, //是否监听初始
},
},
methods: {
updata(filePath) {
const that = this;
// const accessToken = uni.getStorageSync("App-Token") || null; // 获取token
uni.uploadFile({
url: baseUrl + "api/App/CDN/UploadOffice", // 上传路径
filePath: filePath,
name: "file",
header: {
// Authorization: `Bearer ${accessToken}`,
},
// HTTP 请求中其他额外的 form data
formData: {
},
success(res) {
// 上传成功,返回值是后端返回的值,组件以json格式获取到值,所以需要转换成对象
let response = JSON.parse(res.data);
// console.log("=======上传文件完成======>", response);
if (response.data.url != undefined) {
// 判断上传成功与否,也可以通过状态码进行判断
// 把后端返回的上传后的文件路径组装成字符串,传递给父组件
let str;
if (that.value) {
str = that.value + "," + response.data.url;
} else {
str = response.data.url;
}
that.$emit("input", str); // 同步给父组件
uni.showToast({
title: "上传文件成功",
duration: 2000,
});
} else {
uni.showToast({
title: "上传文件失败,请重试!",
icon: "none",
duration: 2000,
});
}
},
fail(err) {
uni.showToast({
title: "上传文件失败,请重试!",
icon: "none",
duration: 2000,
});
},
});
},
// 获取上传状态
select(e) {
console.log("选择文件:", e);
e.tempFilePaths.forEach((item) => {
this.updata(item);
});
},
// 获取上传进度
progress(e) {
console.log("上传进度:", e);
},
// 上传成功
success(e) {
console.log("上传成功");
},
// 上传失败
fail(e) {
console.log("上传失败:", e);
},
},
};
</script>
<style lang="scss" scoped></style>
三、使用
<template>
<view>
<view>
<view>图片上传</view>
<image-upload v-model="form.img" style="flex-grow: 1" />
</view>
<view>
<view>文件上传</view>
<file-upload v-model="form.file" style="flex-grow: 1" /> </view
><view><button @click="look">提交</button></view>
</view>
</template>
<script>
export default {
data() {
return {
form: {
img: "",
file: "",
},
};
},
methods: {
look() {
console.log(this.form);
},
},
};
</script>