1647 lines
45 KiB
Vue
Raw Permalink Normal View History

2025-03-10 13:49:13 +08:00
<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 centercenter rightflex-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>