uniapp 上传图片、视频、文件

5,323 阅读1分钟

此篇是做了一个上传图片、视频或者word、excel的相关代码,点击相应位置可以预览对应文件,点击删除按钮可删除。

<view class="gap-title">面访总结</view>
    <view class="check-content">
      <view class="check-title">
        <text>附件上传</text>
      </view>
      <p class="tips">
        注:附件支持上传图片或视频或文件,上传面访凭证(与业主合照等)
      </p>
      <view class="upload-content">
        <view class="upload-result" v-for="item in uploadFile" :key="item.id">
          <view
            class="upload-item"
            v-if="['.jpg', '.jpeg', '.png'].includes(item.ext)"
            data-title="图片"
          >
            <!-- mode="center" -->
            <image :src="item.url" @tap="goToWebView(item)"></image>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
          <view
            class="upload-item"
            data-title="视频"
            v-if="item.ext.includes('mp4')"
          >
            <video
              :src="item.url"
              :controls="false"
              @tap="goToWebView(item)"
            ></video>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
          <view
            class="upload-item upload-item_file"
            v-if="item.ext.includes('.doc')"
          >
            <image
              src="https://imgtest.0be.cn/FileUpload/PicFile_AHouseF2021/7/15/1b21eb52135a4e78afa596afe281ce5f.png"
            ></image>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
          <view
            class="upload-item upload-item_file"
            v-if="item.ext.includes('.zip')"
          >
            <image
              src="https://imgtest.0be.cn/FileUpload/PicFile_AHouseF2021/7/15/1335411731004331bbfa03ba7e3c59c2.png"
            ></image>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
          <view
            class="upload-item upload-item_file"
            v-if="item.ext.includes('.pdf')"
          >
            <image
              src="https://imgtest.0be.cn/FileUpload/PicFile_AHouseF2021/7/15/24d03c0d951e491a8cc72795d6e94d1e.png"
            ></image>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
          <view
            class="upload-item upload-item_file"
            v-if="item.ext.includes('.xlsx')"
          >
            <image
              src="https://imgtest.0be.cn/FileUpload/PicFile_AHouseF2021/7/15/a580f1f4504b4583a2481368a8e4a50f.png"
            ></image>
            <view
              class="remove-resource iconguanbi1 iconfont"
              @tap.stop="removeResource(item)"
            ></view>
          </view>
        </view>
        <view
          class="upload-button"
          v-if="uploadFile.length == 0"
          @tap="chooseData"
        ></view>
      </view>
    </view>
    <ls-mask v-if="isMask"></ls-mask>
    <view class="fixed-content" v-if="isMask">
      <view class="fixed-head">
        <view class="fixed-btn-item" @tap="chooseImage">上传图片</view>
        <view class="fixed-btn-item" @tap="chooseVideo">上传视频</view>
        <view class="fixed-btn-item" @tap="chooseFile">上传文件</view>
      </view>
      <view class="fixed-close" @tap="closeMask">取消</view>
    </view>
//查看文件
goToWebView(item) {
  uni.navigateTo({
    url: "./webViewPage?url=" + item.url,
  });
},
/**
 * @example: 关闭
 */
closeMask() {
  this.isMask = false;
},
/**
     * @example: 选择视频
     */
    chooseVideo() {
      this.closeMask();
      uni.chooseVideo({
        count: 9 - this.uploadFile.length,
        sourceType: ["camera", "album"],
        success: (res) => {
          this.upLoadFile(res.tempFilePath);
        },
      });
    },
    /**
     * @example: 选择文件
     */
    chooseFile() {
      this.closeMask();
      uni.chooseMessageFile({
        count: 1, //默认100
        extension: ["zip", "doc", "pdf", "xlsx"],
        type: "file",
        success: (res) => {
          this.upLoadFile(res.tempFiles[0].path);
        },
      });
    },
    /**
     * @example: 删除资源
     * @param {object} file 文件
     */
    removeResource(file) {
      api.commonAjax(
        {
          AjaxUrl: `/applet/sale/interview/file/${file.id}`,
          method: "DELETE",
          contentType: "application/x-www-form-urlencoded",
          query: {
            url: file.url,
          },
        },
        (json) => {
          if (json.code == 200) {
            this.uploadFile = this.uploadFile.filter(
              (item) => item.id != file.id
            );
          }
          setTimeout(() => {
            uni.showToast({
              title: json.message,
              icon: "none",
            });
          });
        }
      );
    },
    /**
     * @example: 选择图片
     */
    chooseImage() {
      this.closeMask();
      uni.chooseImage({
        count: 9 - this.uploadFile.length,
        success: (chooseImageRes) => {
          const tempFilePaths = chooseImageRes.tempFiles;
          uni.showLoading({
            title: "上传中.",
          });
          let counter = 0;
          tempFilePaths.forEach((tempPath) => {
            this.upLoadFile(tempPath.path).then(() => {
              counter++;
              if (counter == tempFilePaths.length) {
                uni.hideLoading();
              }
            });
          });
        },
      });
    },
    /**
     * @example: 上传
     */
    upLoadFile(tempPath) {
      return new Promise((r, s) => {
        uni.uploadFile({
          url: resultUrl("applet/sale/interview/file"),
          filePath: tempPath,
          name: "file",
          header: {
            "Content-Type": "multipart/form-data",
            accept: "application/json",
            tk: util.getStorageSync(TOKEN_BWEB),
          },
          formData: {
            uploadName: tempPath,
          },
          success: (uploadFileRes) => {
            try {
              console.log(uploadFileRes, tempPath);
              const v = JSON.parse(uploadFileRes.data);

              if (v.code == 200) {
                this.uploadFile.push(v.data);
              }
            } catch (e) {
              uni.showToast({
                title: "上传失败",
                icon: "none",
              });
              console.log("图片or视频JSON.parse出错:", e);
            }
          },
          complete: () => {
            r();
          },
        });
      });
    },
    /**
     * @example: 选择文件
     */
    chooseData() {
      if (this.uploadFile.length <= 1) {
        this.isMask = true;
      } else {
        uni.showToast({
          title: "最多上传1个文件",
          icon: "none",
        });
      }
    },
<style lang="less" scoped>
.content {
  background: #f0f7f7;
  min-height: 100vh;
  padding: 40upx 32upx 0;
  .content-house {
    padding: 32upx;
    background: #fff;
    border-radius: 12upx;
    .content-hend {
      display: flex;
      .content-image {
        width: 232upx;
        height: 168upx;
        flex-shrink: 0;
        position: relative;
        image {
          border-radius: 12upx;
          width: 100%;
          height: 100%;
        }
        .is-vr {
          width: 84upx;
          height: 60upx;
          background: rgba(255, 255, 255, 0.77);
          border-radius: 54upx;
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          text-align: center;
          line-height: 60upx;
          font-size: 26upx;
          color: #303133;
        }
      }
      .content-data {
        flex: 1;
        margin-left: 16upx;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        width: 0;
        .data-title {
          font-size: 36upx;
          color: #303133;
          font-weight: 900;
          .text-over;
        }
        .data-detail {
          font-size: 24upx;
          color: #606266;
          .text-over;
        }
        .data-list-content {
          display: flex;
          .list-item {
            padding: 0 16upx;
            height: 36upx;
            font-size: 24upx;
            color: #247257;
            border-radius: 4upx;
            background: rgba(233, 240, 238, 1);
            line-height: 36upx;
            text-align: center;
            margin-right: 8upx;
            &:last-child {
              margin-right: 0;
            }
          }
        }
        .data-foot {
          //display: flex;
          font-size: 0;
          .data-price {
            display: inline-block;
            .price-num,
            .price-suffix {
              color: #e11c1c;
              display: inline-block;
              font-weight: 500;
              vertical-align: baseline;
              line-height: 1;
            }
            .price-num {
              font-size: 36upx;
              font-weight: 900;
              font-family: "Arial";
            }
            .price-suffix {
              font-size: 24upx;
            }
          }
          .data-avg {
            display: inline-block;
            font-size: 24upx;
            color: #909399;
            vertical-align: baseline;
            margin-left: 16upx;
          }
        }
      }
    }
  }
  .check-content {
    background: #ffffff;
    border-radius: 12px;
    padding: 48upx 32upx;
    margin-top: 32upx;
    .text-area {
      margin-top: 22upx;
      padding-bottom: 22upx;
      height: 224upx;
      border-bottom: 2upx solid #f0f2f5;
      textarea {
        height: 100%;
      }
    }
    .mimesis-input-group {
      display: flex;
      padding-bottom: 32upx;
      border-bottom: 2upx solid #f0f2f5;
      .left-input,
      .right-input {
        flex: 1;
        text-align: center;
        .uni-input {
          height: 32upx;
          font-size: 32upx;
          color: #909399;
          line-height: 1;
        }
      }
      .gap-line {
        width: 12upx;
        height: 2upx;
        background: #303133;
        align-self: center;
      }
    }
    .check-select {
      position: relative;
      z-index: 10;
    }
    .upload-content {
      display: flex;
      flex-wrap: wrap;
      margin: 0 -16upx;
      .upload-result,
      .upload-button {
        flex: 0 0 calc((100% - 96upx) / 3);
        margin: 0 16upx 16upx;
        box-sizing: border-box;
        height: 172upx;
        border-radius: 12upx;
      }
      .upload-result {
        .upload-item {
          width: 100%;
          height: 100%;
          position: relative;
          .remove-resource {
            position: absolute;
            top: 0;
            right: 0;
            transform: translate(50%, -50%);
            width: 40upx;
            height: 40upx;
            color: #fff;
            font-size: 21upx;
            border-radius: 50%;
            text-align: center;
            line-height: 40upx;
            background: rgb(214, 39, 39);
          }
          &::after {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            content: attr(data-title);
            color: #fff;
            background: #247257;
            padding: 8upx;
            border-radius: 6upx;
            pointer-events: none;
          }
          &.upload-item_file {
            display: flex;
            justify-content: center;
            align-items: center;
            border-radius: 8rpx;
            &::after {
              display: none;
            }
          }
          video {
            border-radius: 12upx;
            width: 100%;
            height: 100%;
          }
          image {
            border-radius: 12upx;
            width: 100%;
            height: 100%;
          }
        }
      }
      .upload-button {
        border: 2upx dashed #909399;
        position: relative;
        &::after,
        &::before {
          content: "";
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          position: absolute;
          background: #909399;
        }
        &::after {
          width: 2upx;
          height: 84upx;
        }
        &::before {
          width: 84upx;
          height: 2upx;
        }
      }
    }
    .check-title {
      font-weight: 400;
      color: #303133;
      font-size: 28upx;
      display: flex;
      align-items: center;
      margin-bottom: 32upx;
      margin-top: 48upx;
      &:first-child {
        margin-top: 0;
      }
      &.is-ignore {
        &::before {
          display: none;
        }
      }
      &::before {
        content: "";
        border-radius: 50%;
        width: 12upx;
        height: 12upx;
        background: #f62f2f;
        margin-right: 12upx;
      }
    }
    .tips {
      border-radius: 8upx;
      margin-bottom: 32upx;
      color: #f6a420;
      line-height: 1.5;
      box-sizing: border-box;
      padding: 16upx;
      font-size: 24upx;
      background: #fffbe9;
    }
    .check-flex {
      display: flex;
      flex-wrap: wrap;
      margin: 0 -8upx;

      &.auto-width {
        margin: 0;
        .check-item {
          min-width: 144upx;
          flex: 0 1 auto;
          margin: 0 16upx 0 0;
          padding: 0 20upx;
          box-sizing: border-box;
        }
      }

      .check-item {
        flex: 0 0 calc((100% - 64upx) / 4);
        margin: 0 8upx;
        height: 72upx;
        background: #f4f4f4;
        border-radius: 4upx;
        color: #606266;
        font-size: 26upx;
        text-align: center;
        line-height: 72upx;
        box-sizing: border-box;

        &.active {
          color: #fff;
          background: #247257;
        }

        &:nth-child(-n + 4) {
          margin-bottom: 16upx;
        }
      }
    }
  }
}
.text-over() {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inpout-content {
  &.gap {
    margin-top: 32upx;
  }
  input {
    height: 32upx;
    font-size: 32upx;
  }
  padding-bottom: 32upx;
  border-bottom: 2upx solid #f0f2f5;
}
.gap-title {
  font-weight: bold;
  color: #303133;
  font-size: 36upx;
  padding-top: 32upx;
}
.splie-line {
  height: 188upx;
}
.submit-button {
  position: fixed;
  width: 100%;
  background: #fff;
  bottom: 0;
  left: 0;
  height: 160upx;
  box-shadow: 0px -4upx 12upx 0px rgba(0, 0, 0, 0.06);
  padding: 16upx 32upx;
  box-sizing: border-box;
  z-index: 30;
  .button {
    font-size: 28upx;
    text-align: center;
    line-height: 84upx;
    height: 84rpx;
    border-radius: 8upx;
    background: #247257;
    color: #fff;
  }
}
.fixed-content {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 40;
  background: #fff;
  .fixed-head {
    border-bottom: 2upx solid #f0f2f5;
    .fixed-btn-item {
      height: 120upx;
      text-align: center;
      line-height: 120upx;
      color: #303133;
    }
  }
  .fixed-close {
    .fixed-head > .fixed-btn-item;
  }
}
</style>

ls-mask.vue文件

.mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.34);
  z-index: 5;
}
</style>

<template>
  <view class="mask"
        @touchmove.stop.prevent="handelMove"
        @tap="hideIs"></view>
</template>

<script>
export default {
  props: {
    value: {
      type: Number
    }
  },
  methods: {
    handelMove () { },

    hideIs () {
      this.$emit("input", -1);
    }
  }
}
</script>

webViewPage.vue文件

<template>
  <view>
    <view>
      <web-view :src="url"></web-view>
    </view>
  </view>
</template>

<script>
export default {
  onLoad (options) {
    this.url = options.url;
		console.log("url:", this.url);
  },
  data () {
    return {
      url: ''
    };
  }
}
</script>

上传图片接口返回

image.png

image.png

image.png

image.png

image.png

image.png