浅记前端遇到的问题 input上传文件属性以及第三方组件库上传文件属性

1,input设置type为file类型的问题

首先所有的组件库包括element,ant等,自动默认capture属性为false,这会导致手机端用该组件库打开会直接弹出摄像头拍摄,而无法调用相册的问题,即便用自定义指令删除该属性,第一次进入后第二次属性依然存在的问题

如果只是用一次,不会回来重新上传,使用ele,ant组件可以使用自定义指令解决

<Upload 
        v-removeCaptrue  //自定义指令
        type="file" 
        :file-list="item.fileList" 
        class="upload" 
        accept="image/*" 
        :onRemove="(file,fileLists)=>{onRemove(file,fileLists, index)}"
        :disabled="uploading" 
        :maxCount="Number(item.keyAndvalueList[5].showValue)"    
        :before-upload="fileBeforeUpload"
          >
          <Button type="primary" :disabled="uploading" @click="uploadBtn(index)"> 上传文件</Button>
        </Upload>

js
自定义指令
  directives:{
    removeCaptrue:{ //这里创建自定义指令,里面的生命周期的回调参数会拿到所有配置这个v-指令的dom元素,可以在这里进行操作
      mounted(e) {
        const f = e.querySelector("input") //拿到上传文件的元素
        f.removeAttribute("capture")  //删除属性
        console.log(f,111111111)
      },
      updated(e) {
        const f = e.querySelector("input")
        f.removeAttribute("capture")
        console.log(f,111111111)

      }
    }
  },

2,如果是上传完了回来依然会是1情况,直接打开摄像头,说明元素回显了,删除的属性出现了,所以用input解决这个问题把

<div class="main">
          <div>
            <span>上传文件
              <input
                id="upload"
                accept="image/*"
                class="img-input"
                type="file"
                @change="(file)=>fileBeforeUploadchange(file,index)"
              />
            </span>
          </div>
          <ul>
            <li v-for="(v,i) in item.fileList"><span>{{ v.name }}</span><img src="@/assets/img/删除.svg" alt="" @click="onRemovefile(i)"/></li>
          </ul>
          
 </div>

js上传交互+校验
const fileBeforeUploadchange= async (e,index) => {
       console.log(e,e.target.files[0])
       let file = e.target.files[0]
        const types = ['image/jpg', 'image/jpeg', 'image/png']
        if (!types.includes(file.type)) {
          message.destroy()
          message.error('图片格式不符合要求,请重新上传')
          return 
        }
//校验上传文件数量,后台配置
        if (fileList.length >= 100)) {
          message.destroy()
          message.error(`只能上传${xxx}个文件`)
          return 
        }
//   校验大小
        if (file.size / 1024 / 1024 >50M) {
          message.destroy() 
          message.error(`图片上传超过${baseForm.value[index].keyAndvalueList[4].showValue}M,请重新上传`)
          return 
        }
        let formData = new FormData();
        formData.append('image', file);
        try {
          const res = await API.upfile(formData); //掉上传接口

          if (res?.code === 0 && res?.data) {
            value.push(res?.data)  //表单提交时候的数据
            fileList.push(file)   //展示上传成功的list列表
            message.success('上传成功')
          } else {
            message.config({
              content: res?.msg || '上传失败,请重试',
              top: 200,
              duration: 3
            })
          }
          return uploading.value = false
        } catch (error) {
          console.log(error, '上传失败')
          uploading.value = false
        }


      return false
    }

//上传成功之后删除对应文件按钮
const onRemovefile = (i)=>{
    fileList.splice(i,1)
   }

3,如果是for循环出来的按钮,多个上传表单

<template>
  <div class="form" id="form" ref="form">
    <div class="form-item" v-for="(item, index) in baseForm" :key="item.sort">
      <!-- 输入框 -->
      <div v-if="item.type == 1">
        <div class="title">{{ `${index + 1} 、 ${item.keyAndvalueList[0].showValue}` }}
          <img src="@/assets/img/必填.svg" alt="" v-if="item.keyAndvalueList[3].showValue == '1'">
        </div>
        <!-- 提示 -->
        <div class="hint">
          <div>{{ item.keyAndvalueList[1].showValue }}</div>
          <img :src="item.keyAndvalueList[2].showValue" alt="" v-if="item.keyAndvalueList[2].showValue">
        </div>
        <Input :disabled="item.keyAndvalueList[4].showValue == '0'" v-model:value="item.value" :maxlength="200"
          :type="item.keyAndvalueList[4].showValue == '2' ? 'number' : 'text'"
          :placeholder="`请输入${item.keyAndvalueList[0].showValue}`"></Input>
      </div>
      <!-- 单选 -->
      <div v-if="item.type == 3">
        <div class="title">{{ `${index + 1} 、 ${item.keyAndvalueList[0].showValue}` }}
          <img src="@/assets/img/必填.svg" alt="" v-if="item.keyAndvalueList[2].showValue == '1'">
        </div>
        <div class="hint">
          <div>{{ item.keyAndvalueList[1].showValue }}</div>
        </div>
        <RadioGroup v-model:value="item.index">
          <Radio :value="v.lable" v-for="(v, i) in item.keyAndvalueList[3].showValue" :key="i">{{ v.value }}</Radio>
        </RadioGroup>
        
      </div>
      <!-- 多选 -->
      <div v-if="item.type == 4">
        <div class="title">{{ `${index + 1} 、 ${item.keyAndvalueList[0].showValue}` }}
          <img src="@/assets/img/必填.svg" alt="" v-if="item.keyAndvalueList[2].showValue == '1'">
        </div>
        <div class="hint">
          <div>{{ item.keyAndvalueList[1].showValue }}</div>
        </div>
        <CheckboxGroup v-model:value="item.value">
          <Checkbox v-for="v in item.keyAndvalueList[3].showValue" :value="v" :key="v.key">{{ v }}</Checkbox>
        </CheckboxGroup>
      </div>
      <!-- 附件上传 -->
      <div v-if="item.type == 2">
        <div class="title">{{ `${index + 1} 、 ${item.keyAndvalueList[0].showValue}` }}
          <img src="@/assets/img/必填.svg" alt="" v-if="item.keyAndvalueList[3].showValue == '1'">
        </div>
        <div class="hint">
          <div>{{ item.keyAndvalueList[1].showValue }}</div>
          <img :src="item.keyAndvalueList[2].showValue" alt="" v-if="item.keyAndvalueList[2].showValue">
        </div>
        <!-- <Upload v-removeCaptrue type="file" :file-list="item.fileList" class="upload" 
        accept="image/*" 
        :onRemove="(file,fileLists)=>{onRemove(file,fileLists, index)}"
          :disabled="uploading" :maxCount="Number(item.keyAndvalueList[5].showValue)" :before-upload="fileBeforeUpload"
          >
          <Button type="primary" :disabled="uploading" @click="uploadBtn(index)"> 上传文件</Button>
        </Upload> -->
        <div class="main">
          <div>
            <span>上传文件
              <input
                :id="`upload${index}`"
                accept="image/*"
                class="img-input"
                type="file"
                @change="(file)=>fileBeforeUploadchange(file,index)"
              />
            </span>
          </div>
          <ul>
            <li v-for="(v,i) in item.fileList"><span>{{ v.name }}</span><img src="@/assets/img/删除.svg" alt="" @click="onRemovefile(item,i)"/></li>
          </ul>
          
        </div>
        
      </div>
    </div>
    <div class="submitBtn" @click="submitBtn" v-if="baseForm.length > 0">提交</div>
  </div>
</template>

<script>
import API from '@/api/questionnaire.js'
import { ref, toRefs, reactive, watch, defineComponent, onMounted, nextTick } from 'vue'
import { Button, message, Input, Upload, Checkbox, RadioGroup, Radio, CheckboxGroup, Row, Col } from 'ant-design-vue'
import { ngx, obj, isPc } from '../views/mock'
import 'ant-design-vue/es/message/style/css'
import 'ant-design-vue/es/button/style/css'
import 'ant-design-vue/es/modal/style/css'
import 'ant-design-vue/es/checkbox/style/css'
import 'ant-design-vue/es/input/style/css'
import 'ant-design-vue/es/upload/style/css'
import 'ant-design-vue/es/radio/style/css'
import 'ant-design-vue/es/row/style/css'
export default defineComponent({
  components: {
    Button,
    Input,
    Radio,
    RadioGroup,
    Upload,
    Checkbox,
    CheckboxGroup,
    Row,
    Col
  },
  props: {
    baseForm: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  setup(props, { attrs, slots, emit, expose }) {
    console.log(props)
    const uploadRefs = ref([])
    const { baseForm } = toRefs(props)
    // const baseForm = ref(obj.data.fieldList)
    //假数据处理
    const change = () => {
      baseForm.value.forEach((item, index) => {
        console.log(item)
        if (item.type == '1' || item.type == '3') {
          baseForm.value[index].value = ''
        } else {
          baseForm.value[index].value = []
        }
        if (item.type == '4') {
          item.keyAndvalueList[3].showValue = item.keyAndvalueList[3].showValue.split(',')
        }
        if (item.type == '3') {
          item.index = -1
          item.keyAndvalueList[3].showValue = item.keyAndvalueList[3].showValue.split(',')
          console.log(item.keyAndvalueList[3].showValue, item)
          item.keyAndvalueList[3].showValue.forEach((v, i) => {
            item.keyAndvalueList[3].showValue.splice(i, 1, {
              lable: i,
              value: v
            })
          })
        }
        if(item.type == '2'){
          // item.fileList = [{name: "question.png"},{name: "question.png"},{name: "question.png"}]
          item.fileList = []

        }
      })
      console.log(baseForm)
    }
    const uploading = ref(false)
    let form = ref({})
    watch(() => baseForm, async (newVal, oldVal) => {
      console.log(newVal, oldVal)
    }, { deep: true, immediate: true })
    const submitBtn = () => {
      console.log(baseForm, baseForm.value)
      // 这里要处理校验
      for (let i = 0; i < baseForm.value.length; i++) {
        // 输入框做校验
        if (baseForm.value[i].type == "1" && baseForm.value[i].keyAndvalueList[3].showValue == '1') {
          if (baseForm.value[i].keyAndvalueList[4].showValue == '1' && !baseForm.value[i].value) {
            baseForm.value[i].value = ''
            message.destroy()
            message.error(`请正确输入第${i + 1}个问题:${baseForm.value[i].keyAndvalueList[0].showValue}`)
            return
          }
          if (baseForm.value[i].keyAndvalueList[4].showValue == '3' && !ngx.mobile().test(Number(baseForm.value[i].value))) {
            baseForm.value[i].value = ''
            message.destroy()
            return message.error(`第${i + 1}个问题:请正确输入手机号`)
          }
          if (baseForm.value[i].keyAndvalueList[4].showValue == '4' && !ngx.email().test(baseForm.value[i].value)) {
            baseForm.value[i].value = ''
            message.destroy()
            message.error(`第${i + 1}个问题:请正确输入邮箱`)
            return
          }
        }
        //处理上传文档TODO
        if (baseForm.value[i].type == "2") {
          if (baseForm.value[i].keyAndvalueList[3].showValue == '1' && (baseForm.value[i].value == "" || baseForm.value[i].value == [])) {
            message.destroy()
            message.error(`第${i + 1}个问题,请上传${baseForm.value[i].keyAndvalueList[0].showValue}的图片`)
            return
          }
        }
        //单选
        if (baseForm.value[i].type == "3") {
          console.log(baseForm.value[i].keyAndvalueList[2].showValue == '1', !baseForm.value[i].index < 0, baseForm.value[i].index)
          if (baseForm.value[i].keyAndvalueList[2].showValue == '1' && baseForm.value[i].index < 0) {
            console.log(333)
            message.destroy()
            message.error(`第${i + 1}个问题,请选择${baseForm.value[i].keyAndvalueList[0].showValue}`)
            return
          }
          // 处理选项
          if(baseForm.value[i].index>=0){
            baseForm.value[i].value = baseForm.value[i].keyAndvalueList[3].showValue[baseForm.value[i].index].value
          }
        }
        //多选
        if (baseForm.value[i].type == "4") {
          console.log(baseForm.value[i].keyAndvalueList[2].showValue == '1', baseForm.value[i].value.length < 1, baseForm.value[i].value)
          if (baseForm.value[i].keyAndvalueList[2].showValue == '1' && baseForm.value[i].value < 1) {
            message.destroy()
            message.error(`第${i + 1}个问题,请选择${baseForm.value[i].keyAndvalueList[0].showValue}`)
            return
          }

        }

      }
      console.log('submit', baseForm)
      emit('submit', baseForm)
    }
    /**
    * 上传相关
    */
    // 删除文件按钮
   const onRemovefile = (item,i)=>{
    item.value.splice(i,1)
    item.fileList.splice(i,1)
    let inp = document.getElementById(`upload${index}`)
    inp.value = null // 一定要删除掉上传储存得value元素,不然回上传不了,这边都展示到list数组里了,所以这里全部为空就行
   }
 
    const fileBeforeUploadchange= async (e,index) => {
       console.log(e,e.target.files[0])
       let file = e.target.files[0]
        const types = ['image/jpg', 'image/jpeg', 'image/png']
        if (!types.includes(file.type)) {
          message.destroy()
          message.error('图片格式不符合要求,请重新上传')
          return 
        }
        console.log(baseForm.value[index])
        if (baseForm.value[index].fileList.length >= Number(baseForm.value[index].keyAndvalueList[5].showValue)) {
          message.destroy()
          message.error(`只能上传${baseForm.value[index].keyAndvalueList[5].showValue}个文件`)
          return 
        }
        if (file.size / 1024 / 1024 > Number(baseForm.value[index].keyAndvalueList[4].showValue)) {
          message.destroy()
          message.error(`图片上传超过${baseForm.value[index].keyAndvalueList[4].showValue}M,请重新上传`)
          return 
        }
        let formData = new FormData();
        formData.append('image', file);
        try {
          const res = await API.imagefile(formData);
          if (res?.code === 0 && res?.data) {
            baseForm.value[index].value.push(res?.data)
            console.log(baseForm.value[index].value)
            baseForm.value[index].fileList.push(file)
            message.success('上传成功')
          } else {
            message.config({
              content: res?.msg || '上传失败,请重试',
              top: 200,
              duration: 3
            })
          }
          return uploading.value = false
        } catch (error) {
          console.log(error, '上传失败')
          uploading.value = false
        }


      return false
    }

    onMounted(() => {
      nextTick(() => {
        change()
        if (isPc) {
          form.value.style.width = '90%'
        } else {
          form.value.style.width = '40%'
        }
      })

     
    })
    return {
      baseForm,
      uploading,
      form,
      submitBtn,
      fileBeforeUploadchange,
      onRemovefile,
      uploadRefs
    }
  },
});
</script>
<style lang="less" scoped>
.form {
  width: 70%;
  font-size: 16px;
  margin: 0 auto;
  padding: 0px 20px;
  height: 100%;

  &-item {
    margin: 0 auto;
    padding-top: 10px;
    border-radius: 8px;

    .title {
      font-weight: 550;
      margin: 20px 0 10px;

      img {
        width: 14px;
      }
    }

    .hint {
      div{
        color: #999;
      }
      img {
        margin: 10px 0;
        width: 100px;
      }
      
    }
  }
  .main{
    span{
      padding: 8px 10px;
      background-color: #456fff;
      color: #fff;
      line-height: 10px;
      position: relative;
    }
    input{
      width: 80px;
      height: 30px;
      position: absolute;
      top: 10px;
      left: 0px;
      border: 1px solid red;
      opacity: 0;
    }
    ul{
      margin-top: 15px;
      li{
        list-style-type:none;
        transform: translateX(-40px);
        font-size: 14px;
        display: flex;
        justify-content: space-between;
        span{
          background-color: #fff;
          color: #a09e9e;
        }
        img{
          width: 14px;
          height: 14px;
          margin-top: 5px;
        }
      }
    }
  }
    .submitBtn {
    width: 200px;
    padding: 10px 20px;
    background-color: #456fff;
    border-radius: 6px;
    text-align: center;
    color: #fff;
    margin: 20px auto;
    cursor: pointer;
  }
}
</style>
后台返回的mock数据以及正则
export const obj = {
        "code": 0,
        "msg": "成功",
        "data": {
            "id": 7,
            "type": 1,
            "filteFlag": 1,
            "title": "rocks问卷标题更新",
            "questionnaireDesc": "普通问卷,不根据过滤用户,状态未发布",
            "state": 1,
            "fieldList": [
                {
                    "sort": 1,
                    "type": 1,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "数字"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:xx岁"
                        },
                        {
                            "questionnaireFieldKeyId": 3,
                            "showKey": "添加图片说明"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "1"
                        },
                        { //输入框1是不限制,2是数字类型,3是手机,4是邮箱,5是长度
                            "questionnaireFieldKeyId": 5,
                            "showKey": "输入限制",
                            "showValue": "2"
                        }
                    ]
                },
                {
                    "sort": 1,
                    "type": 1,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "手机号"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:xx岁"
                        },
                        {
                            "questionnaireFieldKeyId": 3,
                            "showKey": "添加图片说明"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "0"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "输入限制",
                            "showValue": "3"
                        }
                    ]
                },
                {
                    "sort": 1,
                    "type": 1,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "邮箱4"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:xx岁"
                        },
                        {
                            "questionnaireFieldKeyId": 3,
                            "showKey": "添加图片说明"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "0"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "输入限制",
                            "showValue": "4"
                        }
                    ]
                },
                {
                    "sort": 2,
                    "type": 2,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "上传"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:李xx"
                        },
                        {
                            "questionnaireFieldKeyId": 3,
                            "showKey": "添加图片说明",
                            "showValue":"http://fsvivofsimagestatic-test.vivo.com.cn/NmIfgynmX27oVimD/defaultimage/20220829152440/60649caa6274962b20077ece50c14a56b.png"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "1"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "文件大小",
                            "showValue": "50"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "文件个数",
                            "showValue": "2"
                        }
                    ]
                },
                {
                    "sort": 2,
                    "type": 2,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "上传"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:李xx"
                        },
                        {
                            "questionnaireFieldKeyId": 3,
                            "showKey": "添加图片说明",
                            "showValue":"http://fsvivofsimagestatic-test.vivo.com.cn/NmIfgynmX27oVimD/defaultimage/20220829152440/60649caa6274962b20077ece50c14a56b.png"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "1"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "文件大小",
                            "showValue": "50"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "文件个数",
                            "showValue": "2"
                        }
                    ]
                },
                
                {
                    "sort": 2,
                    "type": 3,
                    // index:-1,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "您的姓名"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:李xx"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "0"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "选项",
                            "showValue": "抖音,快手,西瓜视频,小红书,B站,微博,微视,知乎,微信视频号,爱奇艺,QQ小世界,好看视频,ACfun,腾讯视频,其他"
                        }
                    ]
                },
                {
                    "sort": 2,
                    "type": 4,
                    "keyAndvalueList": [
                        {
                            "questionnaireFieldKeyId": 1,
                            "showKey": "标题",
                            "showValue": "多选"
                        },
                        {
                            "questionnaireFieldKeyId": 2,
                            "showKey": "提示",
                            "showValue": "例如:李xx"
                        },
                        {
                            "questionnaireFieldKeyId": 4,
                            "showKey": "是否必填",
                            "showValue": "0"
                        },
                        {
                            "questionnaireFieldKeyId": 5,
                            "showKey": "选项",
                            "showValue": "抖音,快手,西瓜视频,小红书,B站,微博,微视,知乎,微信视频号,爱奇艺,QQ小世界,好看视频,ACfun,腾讯视频,其他"
                        }
                    ]
                },
                
            ]
        }
    }
export const ngx = {
    // 邮箱
  email: () => /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
  // 手机号
  mobile:() => /^[1]\d{10}$/,
  number:() => /^[0-9]*/,
}
export const isPc = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值