zoukankan      html  css  js  c++  java
  • VUE 图片上传/剪切(vue-cropper)

    1. 概述

    1.1 说明

      项目中为了保证图片展示效果以及分辨率高度匹配,需对图片的尺寸、大小、类型等进行控制;最大限度保证图片在网站、小程序、app端的展示效果保持一致。

    1.2 思路

      使用vue-cropper进行图片裁剪功能,使用iview组件Upload进行图片上传。

      1.2.1 功能选择

        使用下拉框进行功能选择,如图片直接上传、图片剪裁等

        

      1.2.2 图片上传与展现

        使用Upload进行图片上传,根据所需上传图片的大小、格式等进行图片验证;所有验证通过后再进行图片上传操作。

        

      1.2.3 最终组件样式

       

      1.2.4 组件使用样式

       

      1.3 vue-cropper使用

      1.  安装  npm install vue-cropper 或者 yarn add vue-cropper
      2.  main.js引用注入 
        1.   import VueCropper from 'vue-cropper'
        2.   Vue.use(VueCropper)
      3.  页面使用  <vueCropper></vueCropper>

      1.4 图片规则

    2. 代码

    2.1 示例代码结构:

    2.2 图片上传、剪裁、展现公用组件(common)

    2.2.1  图片剪裁组件代码(imageCropper.vue)

    <!-- 图片上传剪裁 -->
    <template>
        <div ref="refCommonImageCropper" class="image-cropper-wrapper">
            <div class="cropper-content">
                <div class="operate-content">
                    <div class="scope-btn">
                        <label class="btn" for="uploads">{{ options.imgUrl ? '更换图片' : '上传图片'}}</label>
                        <input
                            type="file"
                            id="uploads"
                            style="position:absolute; clip:rect(0 0 0 0);"
                            accept="image/png, image/jpeg, image/gif, image/jpg"
                            @change="uploadImg($event)"
                        />
                        <Button @click="changeScale(1)" title="放大">+</Button>
                        <Button @click="changeScale(-1)" title="缩小">-</Button>
                        <Button @click="rotateLeft" title="左旋转"></Button>
                        <Button @click="rotateRight" title="右旋转"></Button>
                        <!-- <Button @click="imageCropperSubmit('blob')">确定</Button> -->
                      </div>
                  </div>
                  <div :style="{'width': options.imgWidth + 'px', 'height': options.imgHeight + 'px'}">
                      <vueCropper
                          ref="cropper"
                          :img="options.imgUrl"
                          :outputSize="options.size"
                          :outputType="option.outputType"
                          :info="true"
                          :full="option.full"
                          :canMove="option.canMove"
                          :canMoveBox="option.canMoveBox"
                          :original="option.original"
                          :autoCrop="option.autoCrop"
                          :autoCropWidth="options.cropWidth"
                          :autoCropHeight="options.cropHeight"
                          :fixedBox="option.fixedBox"
                          @realTime="realTime"
                          @imgLoad="imgLoad"
                      ></vueCropper>
                </div>
            </div>
            <div class="cropper-operate" v-if="isShowView">
                <div style="height:42px;padding:6px;">剪裁图片预览</div>
                <div
                    class="show-preview"
                    :style="{'width': options.cropWidth + 'px', 'height': options.cropHeight + 'px',  'overflow': 'hidden', 'margin': '5px'}"
                >
                    <div :style="previews.div" class="preview">
                        <img :src="previews.url" :style="previews.img" />
                    </div>
                </div>
            </div>
        </div>
    </template>
    <script>
        import { uploadImage } from '../../../api/account.js'
        export default {
            name: 'image-cropper',
            props: {
                /**
                 * 裁剪配置
                 */
                setting: {
                    type: Object,
                    default () {
                        return {
                            imgUrl: '',
                            cropWidth: 200,
                            cropHeight: 200,
                            imgWidth: 350,
                            imgHeight: 300,
                            size: 1
                        }
                    }
                },
                /**
                 * 预览区域是否展示
                 */
                isShowView: {
                    type: Boolean,
                    default: true
                }
            },
            data () {
                return {
                    crap: false,
                    previews: {},
                    option: {
                        full: false,
                        outputType: 'png',
                        canMove: true,
                        original: false,
                        canMoveBox: true,
                        autoCrop: true,
                        fixedBox: true
                    },
                    fileName: ''
                }
            },
            computed: {
                options () {
                    return this.setting
                }
            },
            watch: {
                options: {
                    // eslint-disable-next-line
                    handler (newVal, oldVal) {
                        this.setting = newVal
                    },
                    deep: true
                }
            },
            methods: {
                /**
                 * 更改比例
                 */
                changeScale (num) {
                    num = num || 1
                    this.$refs.cropper.changeScale(num)
                },
                /**
                 * 左旋转
                 */
                rotateLeft () {
                    this.$refs.cropper.rotateLeft()
                },
                /**
                 * 右旋转
                 */
                rotateRight () {
                    this.$refs.cropper.rotateRight()
                },
                /**
                 * 实时预览函数
                 */
                realTime (data) {
                    this.previews = data
                },
                /**
                 * 被剪裁图片的上传以及更改
                 */
                uploadImg (e) {
                    // 上传图片
                    var file = e.target.files[0]
                    if (!/.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
                        this.$Message.warning('图片类型必须是jpeg,jpg,png中的一种')
                        return false
                    }
                    this.fileName = file.name
                    var reader = new FileReader()
                    let type = file.type
                    reader.onload = (e) => {
                        let data
                        if (typeof e.target.result === 'object') {
                            // 把Array Buffer转化为blob 如果是base64不需要
                            data = URL.createObjectURL(new Blob([e.target.result], { type }))
                        } else {
                            data = e.target.result
                        }
                        this.options.imgUrl = data
                    }
                    // 转化为base64
                    reader.readAsDataURL(file)
                    // 转化为blob
                    // reader.readAsArrayBuffer(file)
                },
                imgLoad (msg) {
                    console.log(msg)
                },
                /**
                 * 剪裁图片上传
                 */
                imageCropperSubmit (type) {
                    if (this.options.imgUrl) {
                        if (type === 'blob') {
                            this.$refs.cropper.getCropBlob(data => {
                                let formData = new FormData()
                                formData.append('file', data, this.fileName)
                                uploadImage(formData).then(data => {
                                    this.$Message.success('上传成功')
                                    let cropperData = {
                                        httpOriginalFileUri: data.httpOriginalFileUri,
                                        originalFileUri: data.originalFileUri,
                                        converFileUri: data.converFileUri,
                                        fileName: this.fileName
                                    }
                                    this.$emit('fileSuccess', cropperData)
                                }).catch(err => {
                                    console.log(err)
                                })
                            })
                        } else {
                            // 此处得到的是base64位图片数据,暂无用
                            this.$refs.cropper.getCropData(data => {
                                console.log(data)
                            })
                        }
                    } else {
                        this.$Message.warning('请上传需裁剪图片')
                    }
                }
            }
        }
    </script>
    <style lang="scss" scoped>
    .image-cropper-wrapper{
      display: flex;
      flex-direction: row;
      justify-content: center;
      .cropper-content {
        display: flex;
        display: -webkit-flex;
        flex-direction: column;
          .operate-content {
            margin-bottom: 10px;
            display: flex;
            display: -webkit-flex;
            .scope-btn {
              display: flex;
              display: -webkit-flex;
              >button {
                margin-left: 6px;
              }
            }
            .btn {
              outline: none;
              display: inline-block;
              line-height: 1;
              white-space: nowrap;
              cursor: pointer;
              -webkit-appearance: none;
              text-align: center;
              -webkit-box-sizing: border-box;
              box-sizing: border-box;
              outline: 0;
              margin: 0;
              -webkit-transition: 0.1s;
              transition: 0.1s;
              font-weight: 500;
              padding: 8px 15px;
              font-size: 12px;
              border-radius: 3px;
              color: #fff;
              background-color: #67c23a;
              border-color: #67c23a;
            }
          }
      }
      .cropper-operate{
          display: flex;
          flex-direction: column;
          padding-left: 20px;
        }
        .show-preview {
          flex: 1;
          -webkit-flex: 1;
          display: flex;
          display: -webkit-flex;
          justify-content: center;
          align-items: center;
          -webkit-justify-content: center;
          .preview {
            overflow: hidden;
            border: 1px solid #cccccc;
            background: #cccccc;
          }
        }
    }
    </style>

    2.2.1  图片上传、展现、裁剪组件代码(imageOperate.vue)

    <!-- 图片上传 -->
    <template>
        <div class="image-upload-wrapper">
            <div class="default-upload-list" v-if="formInfo.fileUrl">
                <img :src="formInfo.fileUrl">
                <div class="default-upload-list-cover">
                    <Icon type="ios-eye-outline" @click.native="avatarModal=true"></Icon>
                    <Icon v-if="!isDisable" type="ios-trash-outline" @click.native="handleFileRemove"></Icon>
                </div>
            </div>
            <div v-else class="image-upload-item">
                <Select
                    v-model="formInfo.uploadTypeSelected"
                    placeholder="请选择图片上传方式"
                    :disabled="`${imgHeight}`=='0'"
                    :title="`${imgHeight}`=='0'?'尺寸不限时只能进行直接上传操作':''"
                    @on-change="onChangeImageUploadType">
                    <Option
                      v-for="item in imageUploadType"
                      :value="item.value"
                      :key="item.value"
                    >{{ item.label }}</Option>
                </Select>
                <div class="image-upload-content">
                    <div v-if="formInfo.uploadTypeSelected=='cropperUpload'" class="cut-img-wrapper">
                        <div style=" 58px;height:58px;line-height: 58px;" @click="uploadImage">
                            <Icon
                                type="ios-cut"
                                size="20"
                                style="color: #3399ff"
                            ></Icon>
                        </div>
                    </div>
                    <!-- 直接上传 -->
                    <Upload
                        v-else
                        ref="refWholeUpload"
                        type="drag"
                        action="/api/admin/attach/uploadAttach"
                        style=" 58px;height:58px;"
                        :show-upload-list="false"
                        :on-success="fileSuccess"
                        :before-upload="handleBeforeUpload"
                        :on-progress="uploadProgress"
                        :on-error="uploaderror">
                        <div style=" 58px;height:58px;line-height: 58px;">
                            <Icon
                                type="ios-cloud-upload"
                                size="20"
                                style="color: #3399ff"
                            ></Icon>
                          </div>
                    </Upload>
                    <Alert
                        v-if="!formInfo.fileUrl"
                        :type="imageError?'error':'info'"
                        class="image-info">
                        <div>宽高[{{(`${imgWidth}`!='0'?imgWidth:'不限')}}*{{(`${imgHeight}`!='0'?imgHeight:'不限')}}]&nbsp;&nbsp;格式[{{formInfo.uploadTypeSelected=='IconUpload'?'.ico':'.png/.jpg/.jpeg'}}]&nbsp;&nbsp;最大[{{imgSizeTip}}]</div>
                        <div v-if="imageError" style="color:red;">{{imageError}}</div>
                    </Alert>
                </div>
            </div>
            <Modal
                v-model="avatarModal"
                :mask-closable="false"
                :closable='false'
                :z-index='1001'>
                <img :src="formInfo.fileUrl" style=" 100%">
                <div slot="footer">
                    <Button
                        type="primary"
                        @click="avatarModal = false"
                    >关闭</Button>
                </div>
            </Modal>
            <Modal
                :width="modalCropperWidth"
                v-model="modalImageCropper"
                title='图片剪切处理'
                :mask-closable="false"
                :z-index='2001'
                class-name="vertical-center-modal"
                draggable>
                <image-cropper
                    ref="refImageCropper"
                    @fileSuccess="imageCropperSuccess"
                    :setting="setOptions"
                    :isShowView="isShowViewImg"
                    v-if="modalImageCropper" />
                <div slot="footer">
                    <Button @click="modalImageCropper = false">取消</Button>
                    <Button type="primary" @click="submitImageCropper">确定</Button>
                </div>
            </Modal>
            <Spin
                fix
                style="z-index:9999"
                v-if='isLoading'
                class="spin"
            >图片上传中...</Spin>
        </div>
    </template>
    <script>
        import imageCropper from './imageCropper'
        export default {
            name: 'image-operate',
            props: {
                // 图片路径
                imageUrl: {
                    type: String,
                    default () {
                        return ''
                    }
                },
                // 图片大小
                imageSize: {
                    type: Number,
                    default () {
                        return 500
                    }
                },
                // 图片尺寸——宽
                imgWidth: {
                    type: String | Number,
                    default () {
                        return 100
                    }
                },
                // 图片尺寸——高
                imgHeight: {
                    type: String | Number,
                    default () {
                        return 100
                    }
                },
                // 图片大小文字内容
                imgSizeTip: {
                    type: String,
                    default () {
                        return '500KB'
                    }
                },
                // 是否启用
                isDisable: {
                    type: Boolean,
                    default: false
                },
                // 是否支持icon直接上传
                isIconUpload: {
                    type: Boolean,
                    default: false
                }
            },
            components: {
                'image-cropper': imageCropper
            },
            data () {
                return {
                    isLoading: false,
                    // 图片上传类型选择
                    imageUploadType: [],
                    formInfo: {
                        uploadTypeSelected: 'wholeUpload',
                        fileUrl: '',
                        submitUrl: ''
                    },
                    // 图片预览
                    avatarModal: false,
                    attach: {
                        fileName: '',
                        originalFileUri: '',
                        converFileUri: ''
                    },
                    // 图片直接上传错误
                    imageError: '',
                    // 图片裁剪
                    setOptions: {
                        imgUrl: '',
                        size: 1,
                        cropWidth: 200,
                        cropHeight: 200,
                        imgWidth: 350,
                        imgHeight: 300
                    },
                    isShowViewImg: true,
                    modalCropperWidth: 700,
                    modalImageCropper: false
                }
            },
            mounted () {
                if (this.isIconUpload) {
                    this.imageUploadType = [
                        { label: '图片直接上传', value: 'wholeUpload' },
                        { label: '图片剪裁上传', value: 'cropperUpload' },
                        { label: 'ICON图片直接上传', value: 'IconUpload' }
                    ]
                } else {
                    this.imageUploadType = [
                        { label: '图片直接上传', value: 'wholeUpload' },
                        { label: '图片剪裁上传', value: 'cropperUpload' }
                    ]
                }
                this.imageError = ''
                this.formInfo.fileUrl = this.imageUrl
            },
            methods: {
                /**
                 * 图片上传类型选择
                 */
                onChangeImageUploadType (val) {
                    this.imageError = ''
                    this.handleFileRemove()
                },
                /**
                 * 裁剪图片
                 */
                uploadImage () {
                    this.setOptions.imgUrl = ''
                    this.setOptions.size = 1
                    this.setOptions.cropWidth = this.imgWidth
                    this.setOptions.cropHeight = this.imgHeight
                    this.setOptions.imgWidth = this.imgWidth + 20
                    this.setOptions.imgHeight = this.imgHeight + 20
                    let screenWidth = document.body.clientWidth
                    let maxWidth = screenWidth / 2 - 100
                    if (maxWidth >= this.imgWidth + 50) {
                        this.isShowViewImg = true
                        this.modalCropperWidth = (this.imgWidth + 40) * 2 > 500 ? (this.imgWidth + 50) * 2 : 500
                    } else {
                        this.isShowViewImg = false
                        if ((this.imgWidth + 50) * 2 <= 500) {
                            this.modalCropperWidth = 500
                        } else {
                            this.modalCropperWidth = this.imgWidth + 100
                        }
                    }
                    this.modalImageCropper = true
                },
                /**
                 * 图片确定上传
                 */
                submitImageCropper () {
                    this.$refs.refImageCropper.imageCropperSubmit('blob')
                },
                /**
                 * 图片上传成功后返回对应图片信息
                 */
                imageCropperSuccess (val) {
                    this.formInfo.fileUrl = val.httpOriginalFileUri
                    this.formInfo.submitUrl = val.httpOriginalFileUri
                    const data = {
                        fileName: val.fileName,
                        originalFileUri: val.originalFileUri,
                        converFileUri: val.converFileUri,
                        fileUrl: val.httpOriginalFileUri,
                        submitUrl: val.originalFileUri
                    }
                    this.$emit('imageUploadEmit', data)
                    this.modalImageCropper = false
                },
                /**
                 * 删除图片
                 */
                handleFileRemove () {
                    this.attach = {
                        fileName: this.attach.fileName,
                        originalFileUri: '',
                        converFileUri: ''
                    }
                    this.formInfo.fileUrl = ''
                    this.formInfo.submitUrl = ''
                    const data = {
                        fileName: this.attach.fileName,
                        originalFileUri: '',
                        converFileUri: '',
                        fileUrl: '',
                        submitUrl: ''
                    }
                    this.$emit('imageUploadEmit', data)
                },
                /**
                 * 附件上传成功返回值
                 */
                fileSuccess (res, file) {
                    if (res.result) {
                        const { httpOriginalFileUri, originalFileUri, converFileUri } = res.data
                        this.attach.fileName = file.name
                        this.attach.originalFileUri = originalFileUri
                        this.attach.converFileUri = converFileUri
                        this.formInfo.fileUrl = httpOriginalFileUri
                        this.formInfo.submitUrl = originalFileUri
                        const data = {
                            fileName: file.name,
                            originalFileUri: originalFileUri,
                            converFileUri: converFileUri,
                            fileUrl: httpOriginalFileUri,
                            submitUrl: originalFileUri
                        }
                        this.isLoading = false
                        this.$emit('imageUploadEmit', data)
                    } else {
                        this.formInfo.fileUrl = ''
                        this.imageError = '图片上传失败,请重新上传。'
                        this.isLoading = false
                    }
                },
                uploadProgress (file) {
                    this.isLoading = true
                },
                /**
                 * 附件上传判断
                 */
                handleBeforeUpload (file) {
                    this.isLoading = true
                    this.imageError = ''
                    let check = this.$refs.refWholeUpload.fileList.length < 1
                    let isIcontype = file.type === 'image/x-icon'
                    if (this.formInfo.uploadTypeSelected === 'IconUpload') {
                        if (!isIcontype) {
                            this.imageError = '请选择icon类型的图片上传。'
                            this.isLoading = false
                            return false
                        }
                    }
                    if (!check) {
                        this.imageError = '限制上传一张图片,请删除后重新上传。'
                        this.isLoading = false
                        return false
                    } else {
                        return this.checkImageWH(file, this.imgWidth, this.imgHeight)
                    }
                },
                /**
                 * 判断上传文件类型
                 */
                judgeFileType (type) {
                    let typeList = ['image/jpeg', 'image/png', 'image/jpg', 'image/x-icon']
                    let hasIndex = typeList.findIndex(item => item.indexOf(type) > -1)
                    if (hasIndex > -1) {
                        return true
                    } else return false
                },
                /**
                 * 返回一个promise  检测通过返回resolve  失败返回reject组织图片上传
                 */
                checkImageWH (file, width, height) {
                    let self = this
                    return new Promise(function (resolve, reject) {
                        let accordType = self.judgeFileType(file.type)
                        if (!accordType) {
                            self.imageError = '上传的文件为非图片格式,请选择图片格式文件上传'
                            self.isLoading = false
                            reject(new Error(self.imageError))
                        } else if (file.size / 1024 > self.imageSize) {
                            self.imageError = `上传图片不能超过${self.imgSizeTip}`
                            self.isLoading = false
                            reject(new Error(self.imageError))
                        } else {
                            if (`${width}` !== '0') {
                                let filereader = new FileReader()
                                filereader.onload = e => {
                                    let src = e.target.result
                                    const image = new Image()
                                    image.onload = function () {
                                        let errorInfo = ''
                                        if ((width && this.width !== width)) {
                                            errorInfo = `宽(${this.width})、`
                                        }
                                        if (height && `${height}` !== '0' && this.height !== height) {
                                            errorInfo = `${errorInfo}高(${this.height})`
                                        }
                                        if (errorInfo) {
                                            self.imageError = `上传图片错误:${errorInfo}`
                                            self.isLoading = false
                                            reject(new Error(self.imageError))
                                        } else {
                                            self.isLoading = false
                                            resolve(true)
                                        }
                                    }
                                    image.onerror = reject
                                    image.src = src
                                }
                                filereader.readAsDataURL(file)
                            } else {
                                self.isLoading = false
                                resolve(true)
                            }
                        }
                    })
                },
                /**
                 * 附件上传失败
                 */
                uploaderror (file) {
                    this.isLoading = false
                    this.imageError = '图片上传失败,请重新上传。'
                }
            }
        }
    </script>
    <style lang="scss" scoped>
    .image-upload-wrapper .image-upload-item{
      display:flex;
      flex-direction: column;
    }
    .image-upload-wrapper .image-upload-content{
      margin-top: 10px;
      display: flex;
      .image-info {
        margin-left:10px;
        text-align: left;
        display:flex;
        flex-direction:column;
        justify-content:center;
        padding: 0 10px;
        font-size: 13px;
        height: 60px;
      }
    }
    .cut-img-wrapper{
        background: #fff;
        border: 1px dashed #dcdee2;
        display: felx;
        width: 58px;
        height: 58px;
        border-radius: 4px;
        text-align: center;
        cursor: pointer;
        transition: border-color 0.2s;
    }
    .cut-img-wrapper:hover{
        border: 1px dashed #2d8cf0;
    }
    .default-upload-list{
      display: inline-block;
      width: 60px;
      height: 60px;
      text-align: center;
      line-height: 60px;
      border: 1px solid transparent;
      border-radius: 4px;
      overflow: hidden;
      background: #fff;
      position: relative;
      box-shadow: 0 1px 1px rgba(0,0,0,.2);
      margin-right: 4px;
    }
    .default-upload-list img{
      width: 100%;
      height: 100%;
    }
    .default-upload-list-cover{
      display: none;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background: rgba(0,0,0,.6);
    }
    .default-upload-list:hover .default-upload-list-cover{
      display: block;
    }
    .default-upload-list-cover i{
      color: #fff;
      font-size: 20px;
      cursor: pointer;
      margin: 0 2px;
    }
    </style>

    2.3 使用示例(formOperate.vue/index.vue)

    2.3.1  表单示例代码(formOperate.vue)

    <template>
      <Form ref="refForm" :model="formData" :rules="rules">
          <FormItem label="图片" prop="fileUrl" label-for="fileUrl">
            <Input v-show="false" v-model="formData.fileUrl" />
            <image-upload
              :imageUrl="formData.fileUrl"
              :isIconUpload="true"
              @imageUploadEmit="imageUploadFunction"
              :imageSize="settingImageUpload.maxSize"
              :imgWidth="settingImageUpload.width"
              :imgHeight="settingImageUpload.height"
              :imgSizeTip="settingImageUpload.sizeTip"
            />
          </FormItem>
        </Form>
    </template>
    <script>
    import ImageUpload from "./common/imageOperate";
    export default {
      components: {
        ImageUpload,
      },
      data() {
        return {
          formData: {
            fileUrl: "", // 图片路径
          },
          settingImageUpload: {
             100,
            height: 100,
            maxSize: 100,
            sizeTip: "100kb",
          },
          rules: {
            fileUrl: { required: true, message: '请上传图片' }
          }
        };
      },
      methods: {
        /**
         * 图片上传成功
         */
        imageUploadFunction(val) {
          this.formData.originalFileUri = val.originalFileUri;
          this.formData.obtainIconUrl = val.fileUrl;
        }
      },
    };
    </script>

    2.3.2  入口示例代码(index.vue)

    <template>
      <div class="medo-wrapper">
        <Button type="primary" @click="handleAdd">新建</Button>
        <Drawer
          :title="`${propOperateData.id ? '修改' : '新增'}表单`"
          v-model="showInfoOperate"
          :width="drawerStyles.width"
          :styles="drawerStyles.style"
          :mask-closable="false"
          @on-close="showInfoOperate = false"
        >
          <form-operate
            v-if="showInfoOperate"
            :data="propOperateData"
            ref="refFormOperate"
          />
          <div class="default-drawer-footer">
            <Button type="text" @click="showInfoOperate = false"> 关闭 </Button>
            <Button type="primary" @click="handleSubmit"> 确定 </Button>
          </div>
        </Drawer>
      </div>
    </template>
    <script>
    import formOperate from './formOperate'
    export default {
      components: {
        formOperate
      },
      data() {
        return {
          showInfoOperate: false,
          propOperateData: {
            id: "",
            fileUrl: "",
          },
          drawerStyles: {
            // 内容样式
            styles: {
                height: 'calc(100% - 55px)',
                overflow: 'auto',
                paddingBottom: '53px',
                position: 'static'
            },
             720
          },
        };
      },
      methods: {
        handleAdd () {
          this.showInfoOperate = true
        },
        /**
         * 提交按钮
         */
        handleSubmit() {
          this.$refs.refFormOperate.$refs.refForm.validate(validate => {
            if (validate) {
              console.log('验证成功调用接口')
            }
          })
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    .default-drawer-footer{
      width: 100%;
      position: absolute;
      bottom: 0;
      left: 0;
      border-top: 1px solid #e8e8e8;
      padding: 10px 16px;
      text-align: right;
      background: #fff;
    }
    </style>

    2.3 上传代码接口返回:

  • 相关阅读:
    info plist各个功能的详解
    打个测试包弄成连接供别人下载测试
    封装的数据请求加上风火轮的效果
    福大软工 · BETA 版冲刺前准备(团队)
    福大软工 · 第十一次作业
    Alpha 冲刺 (10/10)
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
  • 原文地址:https://www.cnblogs.com/ajuan/p/14598707.html
Copyright © 2011-2022 走看看