李兴辉 89b04fb058 init
2025-03-10 13:49:13 +08:00

1647 lines
45 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>