| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <template>
- <view>
- <div class="upload-box">
- <slot>
- <ul>
- <li
- class="list_img"
- v-for="(item,index) in showImgList"
- :key="index"
- :style="{ width: size + 'rpx', height: size + 'rpx' }"
- >
- <div
- v-if="isMain"
- class="main-btn"
- :class="{'mian': index == 0}"
- @click.stop="mainImg(index)"
- >主</div>
- <view class="iconfont icondelete" @click="delImg(index)"></view>
- <img
- :src="item"
- @click="viewImg(item)"
- :style="{ width: size + 'rpx', height: size + 'rpx' }"
- :mode="imgMode"
- v-if="!prefixShow"
- />
- <img
- :src="`${constant.imgUrl}/${item}`"
- @click="viewImg(item)"
- :style="{ width: size + 'rpx', height: size + 'rpx' }"
- :mode="imgMode"
- v-if="prefixShow"
- />
- </li>
- <li
- v-if="showImgList.length < num && (multiple || showImgList.length == 0)"
- class="uploadImg"
- @click="chooseImage"
- :style="{ width: size + 'rpx', height: size + 'rpx' }"
- >
- <view class="iconfont icontupiantianjia"></view>
- </li>
- </ul>
- </slot>
- </div>
- </view>
- </template>
- <script>
- import { uploadPic } from "@/api/common";
- import { picAdd } from "@/api/img-store";
- export default {
- name: "app-uploader",
- props: {
- // 传入的图片数组
- imgList: {
- type: Array,
- default: () => []
- },
- manualDel: {
- type: Boolean,
- default: false
- },
- // 图片的尺寸
- size: {
- type: Number,
- default: 200
- },
- // 上传图片数量
- num: {
- type: Number,
- default: 9
- },
- // 压缩图片
- compress: {
- type: Boolean,
- default: true
- },
- // 默认限制图片1.5M,单位为M
- maxSize: {
- type: String,
- default: "1.5M"
- },
- // 是否记录用户的选择记录
- isSave: {
- type: Boolean,
- default: false
- },
- // 记录用户的缓存字段
- saveStr: {
- type: String,
- default: "chooseImage"
- },
- // 是否转base64 受数据传输长度限制,不建议在组件中使用,如果一定要使用,在返回结果中自己转换
- isBase64: {
- type: Boolean,
- default: false
- },
- multiple: {
- // 是否多图上传
- type: Boolean,
- default: true
- },
- disabled: {
- // 是否只读
- type: Boolean,
- default: false
- },
- // 图片展示模式
- imgMode: {
- type: String,
- default: "scaleToFill"
- },
- // uploadPic: {
- // type: Function,
- // default: uploadPic
- // },
- // 是否显示主图切换
- isMain: {
- type: Boolean,
- default: false
- },
- //图库图片上传 shish 2020.5.18
- isStorage: {
- type: Boolean,
- default: false
- },
- // 是否需要拼接路径 true 需要 false 不需要
- prefixShow: {
- type: Boolean,
- default: false
- }
- },
- data() {
- return {
- resultData: {},
- showImgList: [],
- base64ImgList: [],
- xssarr: [
- "data:",
- "text",
- "txt",
- "html",
- "js",
- "css",
- "json",
- "exe",
- "sql",
- "xml",
- "doc",
- "docx"
- ]
- };
- },
- mounted() {
- if (this.isSave) {
- let str = uni.getStorageSync(this.saveStr);
- if (str !== "") {
- str = str.split(",");
- if (str.length > this.num) {
- str = str.slice(0, this.num);
- }
- this.showImgList = str;
- }
- } else {
- uni.removeStorageSync(this.saveStr);
- }
- this.showImgList = [...this.imgList];
- },
- methods: {
- chooseImage: async function() {
- if (this.disabled) {
- return;
- }
- let that = this;
- let tempFilePaths = await that.getImage();
- await that.blobToBase64(tempFilePaths);
- await that.autoUploadImg();
- await that.postMsg();
- return this.showImgList;
- },
- postMsg() {
- this.$emit("update:imgList", this.showImgList);
- this.$emit("chooseImage", this.showImgList);
- this.$emit("resultData", this.resultData);
- },
- autoUploadImg() {
- let that = this;
- let base64ImgList = that.base64ImgList;
- let params = {};
- if (base64ImgList.length === 1) {
- params["content"] = base64ImgList[0];
- } else {
- base64ImgList.forEach((item, index) => {
- params[`file[${index}][content]`] = item;
- });
- }
- return new Promise((resolve, reject) => {
- //这块需要优化,我只是简单复制了下 shish 2020.5.18
- if (this.isStorage) {
- picAdd({
- ...params
- }).then(res => {
- let imgArr
- if (res.code === 1) {
- if(this.prefixShow) {
- imgArr = [res.data.shortUrl]
- } else {
- imgArr = [res.data.url];
- }
- that.showImgList = [...that.showImgList, ...imgArr];
- that.resultData = res.data;
- this.$emit("currentUpload", imgArr);
- this.$emit("getResult", that.showImgList);
- resolve(that.showImgList);
- } else {
- reject(res);
- }
- });
- } else {
- uploadPic({
- ...params
- }).then(res => {
- let imgArr
- if (res.code === 1) {
- if(this.prefixShow) {
- imgArr = [res.data.shortUrl]
- } else {
- imgArr = [res.data.url];
- }
- that.showImgList = [...that.showImgList, ...imgArr];
- that.resultData = res.data;
- this.$emit("currentUpload", imgArr);
- this.$emit("getResult", that.showImgList);
- resolve(that.showImgList);
- } else {
- reject(res);
- }
- });
- }
- });
- },
- // 转64
- async blobToBase64(tempFilePaths) {
- let that = this;
- that.base64ImgList = [];
- let newImgList = [...tempFilePaths];
- for (let i = 0; i < newImgList.length; i++) {
- let blob = newImgList[i];
- // 转64位后可以看文件类型 data:text/
- // #ifdef H5
- // 如果是服务器返回的图片不转base64
- // if (blob.indexOf('blob') !== 0) {
- // that.imgPathList.push(blob)
- // continue
- // }
- await that.h5b64(blob).then(res => {
- let startindex = res.indexOf(":");
- let endindex = res.indexOf("/");
- let type = res.substring(startindex + 1, endindex);
- if (that.xssarr.indexOf(type) === -1) {
- that.base64ImgList.push(res);
- }
- });
- // #endif
- // #ifdef MP-WEIXIN
- // 微信临时文件 http://tmp/wx3a16...
- // if (blob.indexOf('http://tmp/') !== 0) {
- // that.imgPathList.push(blob)
- // continue
- // }
- await that.WEIXINb64(blob).then(res => {
- that.base64ImgList.push(res);
- });
- // #endif
- }
- },
- WEIXINb64(blob) {
- return new Promise((resolve, reject) => {
- uni.getFileSystemManager().readFile({
- filePath: blob, // 选择图片返回的相对路径
- encoding: "base64", // 编码格式
- success: function(res) {
- let b64str = "data:image/jpeg;base64," + res.data;
- resolve(b64str);
- },
- fail: function(err) {
- console.log(err);
- }
- });
- });
- },
- h5b64(blob) {
- return fetch(blob, {
- method: "GET",
- headers: new Headers({
- "Access-Control-Allow-Origin": "*",
- "Content-Type": "text/plain"
- }),
- mode: "no-cors"
- })
- .then(data => {
- const blob = data.blob();
- return blob;
- })
- .then(async blob => {
- let reader = new FileReader();
- reader.readAsDataURL(blob);
- // return await new Promise((res, reg) => {
- // reader.onloadend = function() {
- // const data = reader.result
- // res(data)
- // }
- // })
- return await new Promise((res, reg) => {
- reader.onloadend = function() {
- let data = reader.result;
- let str = data.substring(0, 30);
- if (str.indexOf(":image/jpeg;") == -1) {
- data = data.replace("data:;", "data:image/jpeg;");
- }
- res(data);
- };
- });
- });
- },
- // 上传图片
- getImage() {
- let that = this;
- let showImgList = that.showImgList;
- let count = that.num - showImgList.length;
- return new Promise((resolve, reject) => {
- uni.chooseImage({
- count: this.multiple ? count : 1, // 默认9
- sizeType: ["original", "compressed"], // 可以指定是原图还是压缩图,默认二者都有
- sourceType: ["album", "camera"], // 从相册选择
- success: async function(res) {
- await that.fileValid(res);
- var tempFilePaths = res.tempFilePaths;
- if (that.isSave) {
- uni.setStorageSync(that.saveStr, showImgList.join(","));
- }
- resolve(tempFilePaths);
- }
- });
- });
- },
- // 文件过滤
- fileValid(res) {
- let tempFiles = res.tempFiles;
- let tempFilePaths = res.tempFilePaths;
- let newtempFiles = [];
- let newtempFilePaths = [];
- for (let i = 0; i < tempFiles.length; i++) {
- // 大于1.5m就不让上传
- let fileSize = tempFiles[i].size;
- if (fileSize > 1024 * 1024 * 1.5) {
- uni.showToast({
- title: "过滤不能大于1.5m的文件",
- duration: 2000,
- icon: "none"
- });
- continue;
- }
- // 文件类型设置
- let spl = tempFiles[i].path.split(".");
- let fileType = spl[spl.length - 1];
- if (fileType && this.xssarr.indexOf(fileType) >= 0) {
- uni.showToast({
- title: "过滤不符合规范文件",
- duration: 2000,
- icon: "none"
- });
- continue;
- }
- newtempFiles.push(tempFiles[i]);
- newtempFilePaths.push(tempFilePaths[i]);
- }
- res.tempFiles = newtempFiles;
- res.tempFilePaths = newtempFilePaths;
- },
- // 设为主图
- mainImg(index) {
- return false;
- if (index == 0){
- return false;
- }
- this.$msg("操作成功!");
- // let imgArr = JSON.parse(JSON.stringify(this.showImgList))
- let imgUrl = this.showImgList[index];
- this.showImgList.splice(index, 1);
- this.showImgList.unshift(imgUrl);
- // this.$emit('mainImg', index)
- this.postMsg();
- },
- // 删除
- async delImg(index) {
- if (this.disabled) {
- return;
- }
- if (this.isSave) {
- uni.setStorageSync(this.saveStr, this.showImgList.join(","));
- }
- if (!this.manualDel) {
- this.showImgList.splice(index, 1);
- } else {
- this.$emit("delImage", index);
- }
- await this.postMsg();
- },
- // 预览
- viewImg(path) {
- uni.previewImage({
- urls: this.showImgList,
- current: path
- });
- },
- // 获取图片信息
- getImageInfo(image, cb) {
- uni.getImageInfo({
- src: image,
- success: function(image) {
- cb(image);
- return image;
- }
- });
- },
- // 图片压缩
- compressImage() {
- uni.compressImage({
- src: image,
- quality: 80,
- complete: res => {}
- });
- }
- },
- watch: {
- imgList(val) {
- this.showImgList = [...val];
- }
- }
- };
- </script>
- <style scoped lang="scss">
- .uni-system-preview-image {
- background-color: rgba(0, 0, 0, 0.9);
- .uni-preview-image {
- max-width: 100%;
- }
- }
- .upload-box {
- padding: 0 30px;
- &:first-child {
- padding-left: 0;
- }
- & > ul {
- display: inline-block;
- display: flex;
- flex-wrap: wrap;
- & > li {
- list-style: none;
- width: 210px;
- height: 210px;
- margin: 0 20px 20px 0;
- position: relative;
- background-color: #fff;
- .icondelete {
- font-size: 25px;
- z-index: 999;
- position: absolute;
- right: 0;
- bottom: 0;
- color: #fff;
- padding: 0 2px;
- background-color: rgba(0, 0, 0, 0.45);
- }
- .main-btn {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 999;
- @include disFlex(center, center);
- width: 44px;
- height: 44px;
- background-color: #ccc;
- color: #fff;
- &.mian {
- background-color: $mainColor;
- color: #fff;
- }
- }
- }
- }
- & .list_img {
- & > img {
- width: 100%;
- height: 100%;
- }
- }
- & .uploadImg {
- border: 1px dashed #e5e5e5;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
- .upload_ipt {
- position: absolute;
- width: 100%;
- height: 100%;
- /*overflow:hidden;*/
- cursor: pointer;
- opacity: 0;
- }
- .iconfont {
- color: rgb(150, 151, 153);
- font-size: 40px;
- }
- }
- }
- </style>
|