<template> <view class="m-input-row" :class="{'after':after,'before':before}" :style="rowStyle"> <text v-if="title" class="m-title" :class="{'separate':separate}" :style="labelStyle">{{title}}</text> <view class="m-input-view" :style="inputStyle"> <!-- hint 只读标签 --> <template v-if="type==='hint'"> <scroll-view :style="{'width':showButton?'90%':'100%'}" class="scroll-view_H" scroll-x="true"> <view style="display: flex;"> <uni-icons v-if="hintIcons" :color="iconColor" :type="inputIcon"/> <text class="m-input" :style="{'justify-content': tempalignment}">{{value.length<=0?placeholder:value}}</text> </view> </scroll-view> </template> <!-- numberbox 数字box --> <template v-else-if="type==='numberbox'"> <view class="uni-numbox"> <view @click="calcValue('minus')" class="uni-numbox__minus"> <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': value <= min || disabled }">-</text> </view> <input class="uni-numbox__value" :disabled="disabled" :focus="focus" type="number" :value="value" :placeholder="placeholder" @input="onInput" @confirm="onConfirm" @blur="onBlurNumberbox"></input> <view @click="calcValue('plus')" class="uni-numbox__plus"> <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': value >= max || disabled }">+</text> </view> </view> <!-- 清空内容图标 --> <uni-icons v-if="clearable&&value.length>0" type="clear" :color="iconColor" @click="clear" size="22"></uni-icons> </template> <!-- checkbox 复选框 --> <template v-else-if="type==='checkbox'"> <checkbox-group @change="checkboxChange"> <view class="radio-checkbox-content" v-for="(item, index) in temprange" :key="item[rangeKey]" :style="radioOrCheckboxStyle"> <checkbox :value="item[rangeKey]" :checked="item.checked"/> <uni-notice-bar class="radio-checkbox-content-notice" :speed="30" :scrollable="item[rangeVal].length>(8/columns)" :single="true" :text="item[rangeVal]" @click="onNoticeClick('checkbox',index)"/> </view> </checkbox-group> </template> <!-- radio 单选框 --> <template v-else-if="type==='radio'"> <radio-group @change="radioChange"> <view class="radio-checkbox-content" style="display: flex;" v-for="(item, index) in temprange" :key="item[rangeKey]" :style="radioOrCheckboxStyle"> <radio :value="item[rangeKey]" :checked="item.checked"/> <uni-notice-bar class="radio-checkbox-content-notice" :speed="30" :scrollable="item[rangeVal].length>(8/columns)" :single="true" :text="item[rangeVal]" @click="onNoticeClick('radio',index)"/> </view> </radio-group> </template> <!-- switch 开关 --> <template v-else-if="type==='switch'"> <switch :checked="switchResult" type="switch" @change="switchChange" /> <text style="font-size: 16px;" :style="{'color':switchResult?'#007aff':'#636363' }"> {{setSwitchResult}} </text> </template> <!-- combox 下拉框 --> <template v-else-if="type==='combox'"> <view class="uni-combox__input-box"> <uni-icons v-if="verify && comboxValue['index']<0 && comboxValue['val'] && comboxValue['val'].length>0" color="#ff0000" type="clear" size="5"></uni-icons> <uni-icons v-if="verify && comboxValue['index']>=0" color="#00ff00" type="checkbox" size="5"></uni-icons> <text v-if="showValueKey">{{comboxValue['key']+(comboxValue['key']?':':'')}}</text> <input class="uni-combox__input" :focus="focus" type="text" :value="comboxValue['val']||''" :placeholder="placeholder" @input="onInputCombox" @focus="onFocusCombox" @blur="onBlurCombox" @confirm="onConfirmCombox" /> <uni-icons v-if="clearable && (comboxValue['val'] && comboxValue['val'].length>0)" :color="iconColor" type="clear" @click="clearCombox" size="22"></uni-icons> <uni-icons v-if="!clearable || !comboxValue['val'] || comboxValue['val'].length <= 0" :color="iconColor" class="uni-combox__input-arrow" type="arrowdown" size="22" @click="toggleSelector"></uni-icons> <view v-if="showSelector" class="uni-combox__selector" :style="{'background-color':selectorColor}" > <scroll-view scroll-y="true" scroll-x="true" class="uni-combox__selector-scroll"> <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0"> <text>{{ emptyTips }}</text> </view> <view class="uni-combox__selector-item" :style="{'text-align':showSelectorAlign}" v-for="(item, index) in filterCandidates" :key="index" v-if="item[rangeKey] && item[rangeVal]" @click="onSelectorClick(index)"> <text>{{ (showSelectorKey?(item[rangeKey]) :"")+ (showSelectorVal?(showSelectorKey?":":"")+item[rangeVal]:"") }}</text> </view> </scroll-view> </view> </view> </template> <!-- slot 自定义卡槽容器 --> <template v-else-if="type==='slot'"> <scroll-view :style="{'width':showButton?'90%':'100%'}" class="scroll-view_H" scroll-x="true"> <view style="display: flex;"> <slot name="slot"></slot> </view> </scroll-view> </template> <!-- date 时间 --> <template v-else-if="type==='date'"> <!-- 日期 --> <picker v-if="isDate" :style="{'width':isTime?'50%':'100%'}" mode="date" :value="defaultDate" fields="day" :start="startDate" :end="endDate" @change="bindDateChange"> <view class="m-input" style="padding-right:10px;">{{defaultDate}}</view> </picker> <!-- 时间 --> <picker v-if="isTime" :style="{'width':isDate?'50%':'100%'}" mode="time" :value="defaultTime" :start="start" :end="end" @change="bindTimeChange"> <view class="m-input">{{defaultTime}}</view> </picker> <!-- 清空内容图标 --> <uni-icons v-if="clearable&&(value.length>0||defaultDateTime)" type="clear" :color="iconColor" @click="clear" size="22"></uni-icons> </template> <!-- text password number 默认为input输入框 --> <template v-else> <input v-if="type!=='textarea'" class="m-input" :maxlength=-1 :focus="focus" :type="inputType" :value="value" @input="onInput" @confirm="onConfirm" @focus="onFocusInput" @blur="onBlurInput" :placeholder="placeholder" :password="type==='password'&&!showPassword"></input> <textarea v-else :style="{'height':rowHeight}" class="m-input" :maxlength=-1 :focus="focus" :value="value" @input="onInput" @confirm="onConfirm" @focus="onFocusInput" @blur="onBlurInput" :placeholder="placeholder"></textarea> <!-- 清空内容图标 --> <uni-icons v-if="clearable&&!displayable&&value.length>0" type="clear" :color="iconColor" @click="clear" size="22"></uni-icons> <!-- 密码小眼睛图标 --> <uni-icons v-if="displayable" :style="{color:showPassword?'#666666':'#cccccc'}" type="eye" @click="display" size="22"></uni-icons> <!-- 扫描图标 --> <uni-icons v-if="canScan&&(!clearable|| value.length<=0)" type="scan" :color="iconColor" size="22" @click="scan"/> </template> <!-- 输入框按钮 --> <uni-icons v-if="showButton && buttonVal.length<=0" :color="iconColor" :type="buttonIcon" size="22" @click="buttonClick"></uni-icons> <button v-if="showButton && buttonVal.length>0" class="rightButton" :type="buttonType" size="mini" :style="buttonStyle" @click="buttonClick"> {{buttonVal}} </button> </view> </view> </template> <script> // import permision from "@/common/permission.js" export default { props: { // 标签 title: String, // row高度 rowHeight:{ type: String, default: '30px' }, // 标签内容宽度 labelWidth: { type: String, default: 'auto' }, // 输入框类型 type: { type: String, default: 'text' }, // 输入框值 value: { type:[Date, Object, Number, String, Boolean, Array], default() { return ''; } }, // 是否必填 mandatory:{ type: Boolean, default: false }, // 默认必填背景颜色 mandatoryColor:{ type: String, default: '#FFFFCC' }, // 默认正常背景颜色 defaultColor:{ type: String, default: '#ffffff'//#fffae8 }, // 默认只读背景颜色 readonlyColor:{ type: String, default: '#f1f1f1' }, // 默认图标颜色 iconColor:{ type: String, default: '#666666' }, // 输入框占位符提示信息 placeholder: String, // 输入框占位符提示信息、只读字体颜色 placeholderColor:{ type: String, default: '#8383a2' }, // 容器顶部边框 before: { type: Boolean, default: false }, // 容器底部边框 after: { type: Boolean, default: true }, //标题和内容之间的分割线 separate:{ type: Boolean, default: false }, //输入内容框边框 inputBorder:{ type: Boolean, default: true }, //输入内容框边框颜色 inputBorderColor:{ type: String, default:"#c5c5e1" }, // 自动获取焦点 focus: { type: Boolean, default: false }, // 输入框是否显示清除按钮 clearable: { type: [Boolean, String], default: true }, // 是否显示密码可见按钮 displayable: { type: [Boolean, String], default: false }, // 是否显示扫描按钮 canScan:{ type: [Boolean, String], default: false }, // 是否显示只读标签图标 hintIcons:{ type: Boolean, default: false }, // 是否显示按钮 showButton:{ type: Boolean, default: false }, // 输入框提示图标类型 inputIcon:{ type: String, default: 'info' }, // 按钮图标类型 buttonIcon:{ type: String, default: 'checkmarkempty' }, //按钮类型 buttonType:{ type: String, default: 'primary'//primary、warn、default }, //按钮宽度 buttonWidth:{ type: String, default: '' }, //按钮背景颜色 buttonColor:{ type: String, default: '#f8f8f8' }, //按钮字体颜色 buttonlabColor:{ type: String, default: '#000000' }, // 右侧按钮响应事件,false-执行自定义按钮点击事件 true-执行输入框提交事件 btConfirm:{ type: Boolean, default: false }, // 按钮内容 buttonVal:{ type: String, default: '' }, // 数字输入框最小值 min: { type: Number, default: 0 }, // 数字输入框最大值 max: { type: Number, default: 100 }, // 数字输入框步长间隔大小 step: { type: Number, default: 1 }, //数字输入框按钮是否为禁用状态 disabled: { type: Boolean, default: false }, //开关、复选框、单选框、下拉框数据源(父控件的值) range:{ type: [Array, Boolean, Object], default() { return []; } }, //开关、复选框、单选框、下拉框数据源对应的key字段名称 rangeKey:{ type: String, default:'value' }, //开关、复选框、单选框、下拉框数据源对应的value字段名称 rangeVal:{ type: String, default:'name' }, //开关、复选框、单选框、下拉框数据源对应默认选择项index rangeSelect:{ type: Number, default:-1 }, //复选框和单选框展示的列数 columns:{ type: Number, default:2 }, //switch开关是否选中 checked:{ type: Boolean, default:false }, //下拉框筛选结果为空时显示的文字 emptyTips:{ type: String, default: '无匹配项' }, // 是否验证下拉框输入内容是否存在 verify:{ type: Boolean, default:true }, //下拉框输入内容是否自动补全(过滤的时候默认选择第一个选项) automatic:{ type: Boolean, default:true }, //下拉框选择器是否显示key内容 showSelectorKey:{ type: Boolean, default:false }, //下拉框选择器是否显示valur内容 showSelectorVal:{ type: Boolean, default:true }, //下拉框输入值是否显示key内容 showValueKey:{ type: Boolean, default:false }, //下拉框选择器字体对齐方式 showSelectorAlign:{ type: String, default:"left" }, //标签颜色 labelColor:{ type: String, default:"#000000" }, //文本内容颜色 textColor:{ type: String, default:"#0000ff" }, //选择器背景颜色 selectorColor:{ type: String, default:"#ffffff" }, //是否显示日期 isDate:{ type: Boolean, default:true }, //是否显示时间 isTime:{ type: Boolean, default:true }, //是否默认日期和时间 defaultDateTime:{ type: Boolean, default:false }, //默认时间的时间间隔(比如昨天、明天:-1、1),默认0,天为单位 dayInterval:{ type: Number, default:0 }, //最小日期 startDate:{ type: String, default:''//getDate('start'); }, //最大日期 endDate:{ type: String, default:''//getDate('end'); }, //最小时间 start:{ type: String, default:'00:00' }, //最大时间 end:{ type: String, default:'23:59' }, //日期结果 date:{ type: String, default:'' }, //时间结果 time:{ type: String, default:'' }, //内容对齐方式 默认左对齐 ;left:flex-start; center:center; right:flex-end; alignment:{ type: String, default:'left' }, }, model: { prop: 'value', event: 'input' }, data() { return { //默认日期 defaultDate:'选择日期', //默认时间 defaultTime:'选择时间', //显示密码明文 showPassword: false, //switch是否选中结果(switchResult) switchResult:false, //显示/隐藏 下拉框选择器内容信息 showSelector: false, //下拉框值内容显示 comboxValue:{index:-1, key:'', val:''}, //初始化数据开关。针对需要数据源,并且需要构建返回值结构的时候 initState:false, //内容对齐方式 默认左对齐 tempalignment:'flex-start', //开关、复选框、单选框、下拉框数据源(子控件的值) temprange:{ type: [Array, Boolean, Object], default() { return []; } } } }, computed: { // 针对密码输入框类型处理,为了显示和隐藏密码 inputType() { const type = this.type; return type === 'password' ? 'text' : type; }, // 处理主容器样式css rowStyle(){ const type = this.type; if (this.rowHeight === '40px' && (type==='checkbox' || type==='radio')) { //复选框和单选框自动设置高度 if (this.temprange.length > 1) { const cbLen= Math.ceil(this.temprange.length/this.columns); return { height: ((cbLen>3 ? 3 : cbLen) * 40)+'px' } } } return { height: this.rowHeight } }, // 处理标签样式css labelStyle() { let css={} if (this.labelWidth !== 'auto') { css['width']=this.labelWidth; } css['color']=this.labelColor; return css; }, // 处理输入部分样式css inputStyle(){ let css={}; const type = this.type; //设置备件颜色 if(type==='hint'){ css['background-color']=this.readonlyColor; css['width']='90px'; css['color']=this.placeholderColor; }else if(this.mandatory){ css['background-color']=this.mandatoryColor; css['width']='90px'; css['color']=this.textColor; }else{ css['background-color']=this.defaultColor; css['width']='90px'; css['color']=this.textColor; } //数字box不用设置边距 if(type==='numberbox'){ css['padding']='0'; } //增加边框 if(this.inputBorder && this.type!=='switch' && this.type!=='slot'){ css['border-style']='solid'; css['border-width']='1px'; css['border-color']=this.inputBorderColor;//'#c5c5e1'; } //存在按钮的时候,并且为文字按钮的时候,容器右侧增加圆角 if(this.showButton && this.buttonVal!==''){ css['border-radius']='0 5px 5px 0'; } //设置内容对齐方式 css['text-align']=this.alignment; return css; }, //按钮样式调整 buttonStyle(){ let css={}; if(this.buttonWidth!==''){ css['width']=this.buttonWidth; } if(this.buttonType==='default'){ css['background-color']= this.buttonColor; css['color']= this.buttonlabColor; } return css; }, // 复选框和单选框样式调整 radioOrCheckboxStyle(){ //复选框和单选框设置宽度 const ratio= Math.floor(100/this.columns); return { width: ratio+'%' } }, // 开关结果处理 setSwitchResult(){ if(this.temprange.length < 2) return ''; if(this.switchResult){ return this.temprange[0][this.rangeVal]; }else{ return this.temprange[1][this.rangeVal]; } }, // 得到过滤后的下拉框数据源(根据key进行过滤) filterCandidatesKey() { if(this.temprange.length<=0){ return []; } return this.temprange.filter((item, index, arr) => { this.$set(item,'index',index); return item[this.rangeKey].indexOf(this.value['key']) > -1; }); }, // 得到过滤后的下拉框数据源(根据key或者val进行过滤) filterCandidates() { if(this.temprange.length<=0){ return []; } return this.temprange.filter((item, index, arr) => { this.$set(item,'index',index); let t =false; //一:key、val都为空的时候;二:key、val都不为空,并且索引不小于0(有选中结果的情况) if((!this.value['key'] && !this.value['val']) ||(this.value['key'] && this.value['val'] && (this.value['index']|| this.value['index']==0) && this.value['index']>=0)){ t=true; }else{ //通过val进行过滤 if(this.value['val']){ t= item[this.rangeVal].indexOf(this.value['val']) > -1|| item[this.rangeKey].indexOf(this.value['val']) > -1; } //通过key进行过滤 if(this.value['key']){ t=t||item[this.rangeKey].indexOf(this.value['key']) > -1; } } return t; }); }, // 得到下拉框选择器数据源的数据长度,用于提示是否有匹配选择项 filterCandidatesLength() { return this.filterCandidates.length; } }, watch: { //内容对齐方式监听 alignment(newVal,oldVal){ if (JSON.stringify(newVal)!=JSON.stringify(oldVal)) { this.setAlignment(); } }, //内容值改变 value(newVal, oldVal) { //用户自定义修改、返回值改变的时候,针对一些需要重新整理的结果集进行处理。 //(现在操作可能不是最优的,因为控件这个操作主要是针对开发的时候通过代码去改,如果通过控件去操作会导致进行两次整理数据,效率会减慢,先用着) let BeforeNewVal=newVal; if (JSON.stringify(newVal)!=JSON.stringify(oldVal)) { switch (this.type){ case 'switch'://开关 if((newVal===true || newVal===false) && this.temprange.length>=2){//只设置直接赋值true、false,暂时不提供其他赋值方式 let switchV={"result":false,key:'',val:''}; let i=0; if(newVal===true){ this.switchResult=true; switchV.result=true; }else{ this.switchResult=false; switchV.result=true; i=1; } switchV.key=this.temprange[i][this.rangeKey]; switchV.val=this.temprange[i][this.rangeVal]; newVal=switchV; } break; case 'date'://日期时间 if(newVal==''){ this.defaultDate='选择日期'; this.defaultTime='选择时间'; } newVal =this.operationDateValue(); break; case 'combox'://下拉框 // console.log("##############"+JSON.stringify(this.temprange)) // console.log('@@@@@@@@@@@@@@'+JSON.stringify(newVal)) if(this.temprange.length<=0) break; // console.log('$$$$$$$$$$$$$') let comboxV={ index:newVal.index||-1, key:newVal.key||'', val:newVal.val||'', }; if((newVal.index || newVal.index==0) && newVal.index>=0){ //优先通过索引过滤整理数据 comboxV={ index:newVal.index, key:this.temprange[newVal.index][this.rangeKey], val:this.temprange[newVal.index][this.rangeVal] }; }else if(newVal.key){//通过key过滤整理数据 let filterItem=this.filterCandidatesKey; if(filterItem.length>0){ comboxV={ index:filterItem[0].index, key:filterItem[0][this.rangeKey], val:filterItem[0][this.rangeVal] }; } }else if((typeof newVal=='string') && newVal.constructor==String){//直接赋key值 if(newVal){ let filterItem=this.temprange.filter((item, index, arr) => { this.$set(item,'index',index); return item[this.rangeKey].indexOf(newVal) > -1; }); if(filterItem.length>0){ comboxV={ index:filterItem[0].index, key:filterItem[0][this.rangeKey], val:filterItem[0][this.rangeVal] }; } } }else if((typeof newVal=='number')&& newVal.constructor==Number){//直接赋索引值 if(newVal >= 0){ comboxV={ index:newVal, key:this.temprange[newVal][this.rangeKey], val:this.temprange[newVal][this.rangeVal] }; } } newVal=comboxV; this.comboxValue=comboxV; // console.log('@@@@@@@@@@@@@@'+JSON.stringify(this.comboxValue)) break; case 'checkbox'://复选框 if(this.temprange.length<=0) break; let checkboxV={ indexs:newVal.indexs||[], keys:newVal.keys||[], vals:newVal.vals||[], }; let selectK=[]; let selectV=[]; let selectI=[]; if(newVal.indexs){//优先通过索引过滤整理数据 this.temprange.forEach((item, index) => { if(newVal.indexs.includes(index)){ this.$set(item,'checked',true) }else{ this.$set(item,'checked',false) } if(item.checked){ selectK.push(item[this.rangeKey]); selectV.push(item[this.rangeVal]); selectI.push(index); } }) }else if(newVal.keys){//通过key过滤整理数据 this.temprange.forEach((item, index) => { if(newVal.keys.includes(item[this.rangeKey])){ this.$set(item,'checked',true) }else{ this.$set(item,'checked',false) } if(item.checked){ selectK.push(item[this.rangeKey]); selectV.push(item[this.rangeVal]); selectI.push(index); } }) } checkboxV.indexs=selectI; checkboxV.keys=selectK; checkboxV.vals=selectV; newVal=checkboxV; break; case 'radio'://单选框 if(this.temprange.length<=0) break; let radioV={ index:newVal.index||-1, key:newVal.key||'', val:newVal.val||'', }; if((newVal.index || newVal.index==0) && newVal.index>=0){ //优先通过索引过滤整理数据 this.temprange[newVal.index].checked=true; radioV={ index:newVal.index, key:this.temprange[newVal.index][this.rangeKey], val:this.temprange[newVal.index][this.rangeVal] }; }else if(newVal.key){//通过key过滤整理数据 let filterItem=this.filterCandidatesKey; if(filterItem.length>0){ this.temprange[filterItem[0].index].checked=true; radioV={ index:filterItem[0].index, key:filterItem[0][this.rangeKey], val:filterItem[0][this.rangeVal] }; } }else if((typeof newVal=='string') && newVal.constructor==String){//直接赋key值 if(newVal){ let filterItem=this.temprange.filter((item, index, arr) => { this.$set(item,'index',index); return item[this.rangeKey].indexOf(newVal) > -1; }); if(filterItem.length>0){ this.temprange[filterItem[0].index].checked=true; radioV={ index:filterItem[0].index, key:filterItem[0][this.rangeKey], val:filterItem[0][this.rangeVal] }; } } }else if((typeof newVal=='number')&& newVal.constructor==Number){//直接赋索引值 if(newVal >= 0){ this.temprange[newVal].checked=true; radioV={ index:newVal, key:this.temprange[newVal][this.rangeKey], val:this.temprange[newVal][this.rangeVal] }; } } newVal=radioV; // 把旧的结果改回去 if(oldVal.index && oldVal.index>=0){ this.temprange[oldVal.index].checked=false; } break; } } let setOnChange=true; //判断是否需要设置 change 事件 //整理之后的结果集合判断是否一致,不一致就反馈到夫控件 if (JSON.stringify(BeforeNewVal)!=JSON.stringify(newVal)) { this.$emit('input', newVal); setOnChange=false;//因为还会返回一次值到父控件,所以不需要触发change事件 } //用来初始化的时候不进行触发change事件 if(!this.initState){ if (JSON.stringify(newVal)!=JSON.stringify(oldVal) && setOnChange) { this.$emit('change', newVal); } }else{ this.initState=false; } }, //数据源变化,更新界面数据绑定信息 range(newVal,oldVal){ //数据源是在页面data中定义,然后通过方法进行赋值的,重新调用初始化数据操作 if (newVal !== oldVal) { //注:这里两个对象判断相等应该是没用的,需要转换成字符串或者其他操作去进行比对,因为表格数据量大,就不比对了,先这样放着 this.temprange=JSON.parse(JSON.stringify(this.range)); this.init(); } } }, created() { this.temprange=JSON.parse(JSON.stringify(this.range)); //初始化内容对齐方式 this.setAlignment(); //在模板渲染成html前调用,初始化属性值。 switch (this.type){ case 'switch': this.switchResult=this.checked; break; case 'date': let resultDate =this.operationDateValue(); this.$emit('input', resultDate); break; } }, mounted() { //在模板渲染成html后调用,初始化页面完成后,对html的dom节点进行一些需要的操作。 // if(this.temprange.length>0){ //数据源是在页面data中进行了初始化的,就调用初始化数据操作 this.init(); // } }, methods: { //设置内容对齐方式 setAlignment(){ switch (this.alignment){ case 'center': this.tempalignment='center'; break; case 'right': this.tempalignment='flex-end'; break; default: this.tempalignment='flex-start'; break; } }, //整合时间类型返回值整理 operationDateValue(){ let d=''; let t=''; let result=''; if(this.value.length>0){ if(this.value.length>15){ d=this.isDate?this.value.substring(0,10):''; t=this.isTime?' '+this.value.substring(11,this.value.length):''; this.defaultDate=this.value.substring(0,10); this.defaultTime=this.value.substring(11,this.value.length); }else{ //已经填写日期 if(this.value.length>=10 && this.value.length<15){ d=this.isDate?this.value.substring(0,10):''; this.defaultDate=this.value.substring(0,10); } //已经填写时间 if(this.value.length>=5 && this.value.length<10){ t=this.isTime?' '+this.value.substring(this.value.length-5,this.value.length):''; this.defaultTime=this.value.substring(this.value.length-5,this.value.length); } } if(d!='' || t!=''){ result=(this.isDate?d:'')+(this.isTime?t:''); } }else{ this.defaultDate=this.date.length>0 ?this.date :this.defaultDateTime?getDate(this.type,this.dayInterval):this.defaultDate; this.defaultTime=this.time.length>0 ?this.time :this.defaultDateTime?getTime(this.type):this.defaultTime; d=this.defaultDate==='选择日期'?'':this.defaultDate; t=this.defaultTime==='选择时间'?'':' '+this.defaultTime; result=(this.isDate?d:'')+(this.isTime?t:''); } return result; }, //初始化数据(针对有数据源的,range) init(){ this.initState=true; const items = this.temprange; var result={}; switch (this.type){ case 'checkbox': result={indexs:[],keys:[],vals:[]}; var selectK=[]; var selectV=[]; var selectI=[]; for (var i = 0, lenI = items.length; i < lenI; ++i) { const item = items[i] if(item.checked){ selectK.push(item[this.rangeKey]); selectV.push(item[this.rangeVal]); selectI.push(i); } } result.indexs=selectI; result.keys=selectK; result.vals=selectV; this.$emit('input', result); break; case 'radio': var select=false; result={index:-1,key:'',val:''}; for (var i = 0, lenI = items.length; i < lenI; ++i) { const item = items[i]; if(item['checked'] && !select){ result={ index:i, key:item[this.rangeKey], val:item[this.rangeVal] }; select=true; continue; } this.$set(item,'checked',false); } this.$emit('input', result); break; case 'switch': result={ result:this.switchResult, key:'', val:'', }; if(items.length<2){ this.$emit('input', result); break; } var i=this.switchResult?0:1; result.key=this.temprange[i][this.rangeKey]; result.val=this.temprange[i][this.rangeVal]; this.$emit('input', result); break; case 'combox': result={index:-1,key:'',val:''}; if(this.value!=={} && this.value.index>=0 && (this.temprange.length-1)>=this.value.index){ result={ index:this.value.index, key:this.temprange[this.value.index][this.rangeKey], val:this.temprange[this.value.index][this.rangeVal] }; } this.$emit('input', result); break; } }, //密码框眼睛图标点击切换显示隐藏密码 display() { this.showPassword = !this.showPassword }, //普通输入框清空图标事件 clear() { this.$emit('input', ''); this.$emit('clear', ''); //时间控件清空操作 if(this.type==='date'){ this.defaultDate='选择日期'; this.defaultTime='选择时间'; } }, //按钮点击事件 buttonClick(){ if(this.btConfirm){ this.$emit('confirm', this.value); }else{ this.$emit('buttonClick', this.value); } }, //普通输入框输入事件 onInput(e) { this.$emit('input', e.detail.value); }, //普通输入框提交事件 onConfirm(e){ this.$emit('confirm', e.detail.value); }, //数字box输入框【+】【-】按钮点击事件 calcValue(type) { if (this.disabled) { return; } const scale = this.getDecimalScale(); let value = this.value * scale; let step = this.step * scale; if (type === "minus") { value -= step; if (value < (this.min * scale)) { return; } if (value > (this.max * scale)) { value = this.max * scale } } else if (type === "plus") { value += step; if (value > (this.max * scale)) { return; } if (value < (this.min * scale)) { value = this.min * scale } } this.$emit('input', String(value / scale)); }, //数字box输入框值转换 getDecimalScale() { let scale = 1; // 浮点型 if (~~this.step !== this.step) { scale = Math.pow(10, (this.step + "").split(".")[1].length); } return scale; }, // 数字box输入框失去焦点事件 onBlurNumberbox(e) { let value = e.detail.value; if (!value) { this.$emit('input', ''); return; } value = +value; if (value > this.max) { value = this.max; } else if (value < this.min) { value = this.min; } this.$emit('input', value); }, //复选框选择项改变事件 checkboxChange(e){ var items = this.temprange; var checkboxV={indexs:[],keys:[],vals:[]}; var selectK=[]; var selectV=[]; var selectI=[]; for (var i = 0, lenI = items.length; i < lenI; ++i) { const item = items[i] if(e.detail.value.includes(item[this.rangeKey])){ this.$set(item,'checked',true) }else{ this.$set(item,'checked',false) } if(item.checked){ selectK.push(item[this.rangeKey]); selectV.push(item[this.rangeVal]); selectI.push(i); } } checkboxV.indexs=selectI; checkboxV.keys=selectK; checkboxV.vals=selectV; this.$emit('input', checkboxV); }, //单选框选择项改变事件 radioChange(e) { var items = this.temprange; var radioV={}; for (var i = 0, lenI = items.length; i < lenI; ++i) { const item = items[i] if(e.target.value===item[this.rangeKey]){ this.$set(item,'checked',true); radioV={index:i,key:e.target.value,val:item[this.rangeVal]}; }else{ this.$set(item,'checked',false); } } this.$emit('input', radioV); }, //复选框、单选框字体点击事件 onNoticeClick(type,index){ let item =this.temprange[index]; let results={}; if(type==='checkbox'){ results={ indexs:this.value.indexs, keys:this.value.keys, vals:this.value.vals }; if(item['checked']){ //取消选择 let oldIndex = results.indexs.indexOf(index); if (index > -1) { results.indexs.splice(oldIndex, 1); results.keys.splice(oldIndex, 1); results.vals.splice(oldIndex, 1); } this.$set(item,'checked',false); }else{ //选择 results.indexs.push(index); results.keys.push(item[this.rangeKey]); results.vals.push(item[this.rangeVal]); this.$set(item,'checked',true); } this.$emit('input', results); }else if(type==='radio'){ this.$set(this.temprange[this.value.index],'checked',false); results={ index:index, key:item[this.rangeKey], val:item[this.rangeVal] }; this.$set(item,'checked',!item['checked']); this.$emit('input', results); } }, //开关选择项改变事件 switchChange(e) { this.switchResult=e.target.value; var result={result:this.switchResult,key:'',val:''}; var i=this.switchResult ? 0 : 1; if (this.temprange.length<2){ this.$emit('input', result); return; } result.key=this.temprange[i][this.rangeKey]; result.val=this.temprange[i][this.rangeVal]; this.$emit('input', result); }, //下拉框展开图标点击事件 toggleSelector() { this.showSelector = !this.showSelector; }, //下拉框清空图标点击事件 clearCombox(){ this.$emit('input', {index:-1, key:'', val:''}); }, //下拉框输入内容事件 onInputCombox(e) { this.$emit('input', {index:-1, key:'', val:e.detail.value}); setTimeout(()=>{ let filter= this.filterCandidates; if(filter.length === 1 && filter[0][this.rangeVal]===e.detail.value){ let result={ index:filter[0]["index"], key:filter[0][this.rangeKey], val:filter[0][this.rangeVal] }; this.$emit('input', result); } }, 100); }, //下拉框提交内容事件 onConfirmCombox(){ this.$emit('confirm', this.value); }, //输入框类得到焦点 onFocusInput(){ this.$emit('resetFocus', true); this.$emit('focus', this.value); }, //输入框类失去焦点 onBlurInput(){ this.$emit('resetFocus', false); this.$emit('blur', this.value); }, //下拉框得到焦点事件 onFocusCombox() { this.showSelector = true; this.$emit('focus', this.value); }, //下拉框失去焦点事件 onBlurCombox() { //需要延迟执行,防止输入框失去焦点后,马上隐藏选项内容信息,导致无法选择 setTimeout(()=>{ const filter= this.filterCandidates; var result=this.value; if(filter.length<=0){ result=this.verify ? {index:-1, key:'', val:''} : result; }else if(this.value['index']<0 && this.value['val'].length>0){ if(this.automatic){ result={ index:filter[0]['index'], key:filter[0][this.rangeKey], val:filter[0][this.rangeVal] } }else if(this.verify && result['index']<=0){ result={index:-1, key:'', val:''}; } } this.$emit('input', result); this.$emit('blur', result); this.showSelector = false; }, 100); }, //下拉框选择器内容选项点击事件 onSelectorClick(index) { this.showSelector = false; const item =this.filterCandidates[index]; const result={ index:item["index"], key:item[this.rangeKey], val:item[this.rangeVal] }; this.$emit('input', result); }, //时间输入框-日期点击选择事件 bindDateChange(e) { this.defaultDate = e.detail.value let result=(this.isDate?this.defaultDate:'')+(this.isTime &&this.defaultTime!=='选择时间' ?(' '+this.defaultTime):''); this.$emit('input', result); this.$emit('confirm', {date:e.detail.value,time:this.defaultTime==='选择时间'?'':this.defaultTime}); }, //时间输入框-时间点击选择事件 bindTimeChange(e) { this.defaultTime = e.detail.value let result=(this.isDate&&this.defaultDate!=='选择日期'?this.defaultDate:'')+(this.isTime?(' '+this.defaultTime):''); this.$emit('input', result); this.$emit('confirm', {date:this.defaultTime==='选择日期'?'':this.defaultTime, time:e.detail.value}); }, //跳转到微信扫一扫,用于在微信推广吧。 // scan(){ // if (plus.os.name == "iOS") { // plus.runtime.openURL("weixin://scanqrcode") // } else if (plus.os.name == "andriod") { // var Intent = plus.android.importClass("android.content.Intent"); // var ComponentName = plus.android.importClass('android.content.ComponentName') // var intent = new Intent(); // intent.setComponent(new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI")); // intent.putExtra("LauncherUI.From.Scaner.Shortcut", true); // intent.setFlags(335544320); // intent.setAction("android.intent.action.VIEW"); // var main = plus.android.runtimeMainActivity(); // main.startActivity(intent); // } // } //扫一扫事件 async scan() { let status = await this.checkPermission(); if (status !== 1) { return; } uni.scanCode({ success: (res) => { this.$emit('input', res.result); this.$emit('confirm', res.result); }, fail: (err) => { uni.getSetting({ success: (res) => { let authStatus = res.authSetting['scope.camera']; if (!authStatus) { uni.showModal({ title: '授权失败', content: 'Hello uni-app需要使用您的相机,请在设置界面打开相关权限', success: (res) => { if (res.confirm) { uni.openSetting() } } }) } } }) } }); }, //扫一扫功能必须的手机权限验证 async checkPermission(code) { let status = permision.isIOS ? await permision.requestIOS('camera') : await permision.requestAndroid('android.permission.CAMERA'); if (status === null || status === 1) { status = 1; } else { uni.showModal({ content: "需要相机权限", confirmText: "设置", success: function(res) { if (res.confirm) { permision.gotoAppSetting(); } } }) } return status; } } } //获取日期,只在时间类型控件才使用 function getDate(type, dayInterval) { if(type!=='date') return ''; let dateTime = new Date(); dateTime=dateTime.setDate(dateTime.getDate()+dayInterval); const date=new Date(dateTime) let year = date.getFullYear(); let month = date.getMonth() + 1; let day = date.getDate(); if (type === 'start') { year = year - 60; } else if (type === 'end') { year = year + 2; } month = month > 9 ? month : '0' + month;; day = day > 9 ? day : '0' + day; return `${year}-${month}-${day}`; } //获取时间,只在时间类型控件才使用 function getTime(type){ if(type!=='date') return ''; const date = new Date(); let h=date.getHours(); let m =date.getMinutes(); return (h<10?'0'+h:h)+':'+(m<10?'0'+m:m); } </script> <style> .rightButton { padding:0 20rpx; height: 30px; margin-left: 10rpx; } .scroll-view_H { white-space: nowrap; /* width: 100%; */ } .uni-combox { display: flex; height: 40px; line-height: 40px; flex-direction: row; align-items: center; position: relative; } .uni-combox.before::before { position: absolute; right: 0; top: 0; left: 0; height: 1px; content: ''; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); background-color: #c8c7cc; z-index: 99; /* 这里会被input覆盖1px给了一个置顶 */ } .uni-combox.after::after { position: absolute; right: 0; bottom: 0; left: 0; height: 1px; content: ''; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); background-color: #c8c7cc; } .uni-combox__input-box { position: relative; display: flex; flex: 1; flex-direction: row; align-items: center; /* color: #0000ff; */ height: 100%; } .uni-combox__input { flex: 1; font-size: 16px; height: 22px; line-height: 22px; } .uni-combox__input-arrow { /* padding: 10px; */ } .uni-combox__selector { box-sizing: border-box; position: absolute; top: 42px; left: 0; width: 100%; background-color: #ffffff; border-radius: 6px; box-shadow: #dddddd 4px 4px 8px, #dddddd -4px -4px 8px; z-index: 99; } .uni-combox__selector-scroll { max-height: 200px; box-sizing: border-box; white-space: nowrap; } .uni-combox__selector::before { content: ''; position: absolute; width: 0; height: 0; border-bottom: solid 6px #ffffff; border-right: solid 6px transparent; border-left: solid 6px transparent; left: 50%; top: -6px; margin-left: -6px; } .uni-combox__selector-empty, .uni-combox__selector-item { /* #ifdef APP-NVUE */ display: flex; /* #endif */ line-height: 36px; font-size: 14px; text-align: left; border-bottom: solid 1px #dddddd; margin: 0px 10px; } .uni-combox__selector-empty:last-child, .uni-combox__selector-item:last-child { border-bottom: none; } uni-radio-group, uni-checkbox-group{ width: 100%; height: 100%; /* max-height: 120px; */ overflow-y: scroll; } .radio-checkbox-content { display: flex; float: left; margin: 2px 0; } .radio-checkbox-content-notice{ padding:0; margin-bottom:0; } .uni-numbox { display: flex; flex-direction: row; height: 28px; line-height: 28px; width: 100%; } .uni-numbox__value { height: 28px; width: 100%; text-align: center; font-size: 16px; border-style: solid; border-color: #e5e5e5; border-width: 0 1px 0 1px; } .uni-numbox__minus { display: flex; flex-direction: row; align-items: center; justify-content: center; width: 30px; height: 28px; font-size: 20px; color: #333; background-color: #f8f8f8; border-style: solid; border-color: #e5e5e5; border-top-left-radius: 3px; border-bottom-left-radius: 3px; border-width: 0 0 0 1px; } .uni-numbox__plus { display: flex; flex-direction: row; align-items: center; justify-content: center; width: 30px; height: 28px; border-width: 0 1px 1px 0; border-style: solid; border-color: #e5e5e5; border-top-right-radius: 3px; border-bottom-right-radius: 3px; background-color: #f8f8f8; } .uni-numbox--text { font-size: 40rpx; color: #333; } .uni-numbox--disabled { color: #c0c0c0; } .m-input-view { display: inline-flex; flex-direction: row; align-items: center; width: 100%; flex: 1; padding: 0 0 0 5px; } .m-input-row { display: flex; flex-direction: row; position: relative; font-size: 16px; line-height: 30px; height: 30px; padding: 5px 1px; } .m-input-row.before::before { position: absolute; right: 0; top: 0; left: 0; height: 1px; content: ''; -webkit-transform: scaleY(.5); transform: scaleY(.5); background-color: #b0b0d9; } .m-input-row.after::after { position: absolute; right: 0; bottom: 0; left: 0; height: 1px; content: ''; -webkit-transform: scaleY(.5); transform: scaleY(.5); background-color: #b0b0d9; } .m-title { /* width: 25%; */ width: 80px; padding-left: 5px; } /* 标签右侧边框 */ .m-title.separate::after { position: absolute; bottom: 0; top: 0; width: 1px; content: ''; background-color: #b0b0d9; } .m-input { width: 100%; display: flex; flex: 1; font-size: 16px; } </style>