网站首页 编程语言 正文
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)
原文链接:https://blog.csdn.net/m0_64207574/article/details/131113506
- 上一篇:没有了
- 下一篇:没有了
相关推荐
- 2022-12-14 C++利用类实现矩阵的数乘,乘法以及点乘_C 语言
- 2022-08-01 Flutter移动端进行多渠道打包发布的全过程_Android
- 2023-03-20 解读C#中ReadString的一些小疑惑_C#教程
- 2022-11-19 React组件的应用介绍_React
- 2022-09-05 Spring 解决循环依赖
- 2023-01-29 python index() 与 rindex() 方法的使用示例详解_python
- 2023-04-02 Python中time库的使用(日期时间)_python
- 2022-08-04 python连接FTP服务器的实现方法_python
- 栏目分类
-
- 最近更新
-
- window11 系统安装 yarn
- 超详细win安装深度学习环境2025年最新版(
- Linux 中运行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存储小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基础操作-- 运算符,流程控制 Flo
- 1. Int 和Integer 的区别,Jav
- spring @retryable不生效的一种
- Spring Security之认证信息的处理
- Spring Security之认证过滤器
- Spring Security概述快速入门
- Spring Security之配置体系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置权
- redisson分布式锁中waittime的设
- maven:解决release错误:Artif
- restTemplate使用总结
- Spring Security之安全异常处理
- MybatisPlus优雅实现加密?
- Spring ioc容器与Bean的生命周期。
- 【探索SpringCloud】服务发现-Nac
- Spring Security之基于HttpR
- Redis 底层数据结构-简单动态字符串(SD
- arthas操作spring被代理目标对象命令
- Spring中的单例模式应用详解
- 聊聊消息队列,发送消息的4种方式
- bootspring第三方资源配置管理
- GIT同步修改后的远程分支