You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

537 lines
16 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="d-block tm-input overflow"
:class="[
black_tmeme?(bgTheme?'grey-darken-5':''):bgTheme,
flat?'':`px-${padding[0]}`,
'round-'+ bgRound,
`shadow-${color}-${bgShadow}`
]"
>
<view
:class="(flat?'':` py-${padding[1]} `)+` ${borderBottom?black_tmeme?'border-grey-darken-4-b-1 ':'border-grey-lighten-4-b-1':''}`"
>
<view @click="onclickInput" :class="[vertical?'tm-input-col':'flex-between ']" :style="{
width: '100%',height: 'auto',
alignItems:inputType=='textarea'?'flex-start':'center'
}">
<!-- 左边内容 -->
<view v-if="leftIcon||title" class="tm-input-left flex-start flex-shrink" :class="[vertical?'pb-24':'']">
<!-- icon -->
<view v-if="leftIcon" class="pr-16 vertical-align-middle flex-center">
<tm-icons dense :name="leftIcon" :color="color_tmeme"></tm-icons>
</view>
<!-- 标题 -->
<view v-if="title" class="d-inline-block "
:style="{fontSize:title_size}"
:class="[titleClass,black_tmeme?'bk text-grey-lighten-3':'']">
<text v-if="_required" class="text-red">*</text>
<slot name="default" :title="title">
{{title}}
</slot>
</view>
</view>
<view class="flex-between " :class="[disabled?'opacity-6':'',]" style="width: 100%;">
<!-- input主体 -->
<view class="tm-input-center relative fulled" >
<view class="flex-start tm-input-center-wk"
:class="['round-'+round,showIndent?'px-16':'',
black_tmeme?(bgColor?'grey-darken-4 text-grey-lighten-3':'text-grey-lighten-3'):bgColor,
`text-${textColor}`,isFocus&&focusShow?(black_tmeme?`border-${color_tmeme}-a-1`:`${color_tmeme} outlined `):``,
`border-${black_tmeme?(borderColor?'grey-darken-4':''):borderColor}-a-1`,
]">
<view class="flex-shrink px-16 flex-center" v-if="prefixpIcon" style="line-height: 0;">
<tm-icons dense :name="prefixpIcon" :size="28" :color="(prefixpIconColor||color_tmeme)" ></tm-icons>
</view>
<view :style="{fontSize:font_size}" class="flex-shrink pr-24" :class="[titleClass,black_tmeme?'bk text-grey-lighten-3':'']" v-if="prefixpText">
{{prefixpText}}
</view>
<input always-embed v-if="inputType!='textarea'" @confirm="$emit('confirm',$event)" @input="input"
@keyboardheightchange="$emit('keyboardheightchange',$event)" @blur="blur"
@focus="focusFun" :focus="focus_fs" :maxlength="maxlength" :adjust-position="adjustPosition"
:auto-focus="autoFocus" :confirm-type="confirmType" :disabled="disabled"
:password="password" :type="inputType" :value="value" class="tm-input-center-input "
:class="['text-align-'+align,showError?'text-red':'',' py-5 ']" :placeholder="placeholder"
:placeholder-class="black_tmeme? 'text-grey-darken-1 ':' ' +` text-size-n ` + placeholderClass"
:style="{
fontSize:font_size,
height:height_rpx+'rpx'
}"
/>
<!-- uniapp的bug当输入框禁用时点击此处来获取新的焦点以让键盘收起。 -->
<view v-if="disabled" class="absolute fulled t-0 r-0" :style="{
height:height_rpx+'rpx'
}"></view>
<textarea always-embed v-if="inputType=='textarea'" @confirm="$emit('confirm',$event)" @input="input"
@keyboardheightchange="$emit('keyboardheightchange',$event)" @blur="blur"
@focus="focusFun" :focus="focus_fs" :maxlength="maxlength" :adjust-position="adjustPosition"
:auto-focus="autoFocus" :confirm-type="confirmType" :disabled="disabled"
:value="value" class="tm-input-center-input " :style="{
height:height_rpx+'rpx',
fontSize:font_size,
}"
:class="[maxlength>0?'pb-46':'','text-align-'+align,showError?'text-red':'','pt-16 fulled']" :placeholder="placeholder"
:placeholder-class="black_tmeme? 'text-grey-darken-1 ':' text-grey-lighten-1 ' +` text-size-n `+ placeholderClass" >
</textarea>
<!-- 清除图标 -->
<view v-if="clear&&valdata.length!=''" class="flex-center pl-16">
<tm-icons @click.stop="clearVal" name="icon-times-circle-fill" :color="color_tmeme"></tm-icons>
</view>
<view v-if="suffixIcon" class="flex-center">
<tm-icons :size="26" :name="suffixIcon" :color="(suffixIconColor||color_tmeme)"></tm-icons>
</view>
</view>
<view v-if="maxlength>0&&inputType=='textarea'"
:style="{bottom:'16rpx',right:'16rpx'}"
class="tm-input-center-numXz text-align-right text-size-xxs pt-12 text-grey absolute fulled">{{valueLen}}/{{maxlength}}</view>
</view>
<!-- 右边。 -->
<view class="tm-input-right flex-end flex-shrink">
<!-- 后缀文字,比如单位,等 -->
<text v-if="suffix" class=" text-grey-darken-4 pl-10" :style="{fontSize:font_size}">{{suffix}}</text>
<!-- 后台图标。 -->
<view v-if="rightIcon" class="pl-10" style="line-height: 0;">
<tm-icons dense :name="rightIcon" color="grey-lighten-1"></tm-icons>
</view>
<!-- 插入的按钮等内容。 -->
<slot name="rightBtn"></slot>
</view>
</view>
</view>
<!-- detail出错成功等信息。 -->
<view v-if="showError" class="text-size-xs text-red pt-12">{{errorText}}</view>
</view>
</view>
</template>
<script>
/**
* 输入框
* @property {Number} maxlength = [-1] 默认:-1最大输入字符数。
* @property {Boolean} black = [] 默认false暗黑模式。
* @property {Function} verify = [] 默认: (val) => {check: val.length <= 0 ? false : true,text: "必填项不能为空。"},校验规则函数。
* @property {String} title-class = [] 默认: text-grey-darken-4,自定左边标题或者上标题的类。
* @property {Boolean} required = [] 默认: false, 是否是必填。如果必填写将会触发基础的校验,不能为空。
* @property {Boolean} adjust-position = [] 默认: false, 是否上推键盘。
* @property {Boolean} auto-focus = [] 默认: false, 自动获得焦点。
* @property {String} confirm-type = [done|go|next|send|search] 默认: done, 键盘右下角确认按钮文字。
* @property {Boolean} disabled = [] 默认: false, 禁用。
* @property {Boolean} focus-show = [] 默认: false, 是否显示聚焦状态。
* @property {Boolean} show-indent = [] 默认: false, 是滞使输入框内容两边缩进。默认是。
* @property {Boolean} password = [] 默认: false, 密码模式
* @property {String} input-type = [digit|text|number|password|idcard|textarea] 默认: text, 输入模式
* @property {String} value = [] 默认: "", 输入内容同v-model
* @property {String} right-icon = [] 默认: "", 后缀图标
* @property {String} left-icon = [] 默认: "", 外层前缀图标
* @property {String} prefixp-icon = [] 默认: "", 输入框内部前缀图标
* @property {String} prefixp-icon-color = [] 默认: "", 默认空使用主题color颜色
* @property {String} suffix = [] 默认: "", 后缀文字
* @property {String} suffix-icon = [] 默认: "", 输入框内后缀图标
* @property {String} suffix-icon-color = [] 默认: "", 默认使用主题图标
* @property {String} title = [] 默认: "", 左边标题。
* @property {String} title-font-size = [xxs/xs/s/n/g/lg/xl] 默认: "n",同类的字号,xxs,xs,s,n,g,lg,xl
* @property {Number|String} font-size = [xxs/xs/s/n/g/lg/xl/任意数字] 默认: "n",同类的字号,xxs,xs,s,n,g,lg,xl也可以是数字单位rpx
* @property {String} align = [left|center|right] 默认: "", 输入框文字对齐方式。left,center,right
* @property {Boolean} clear = [false|true] 默认: false, 显示清除图标。
* @property {String} color = [] 默认: primary, 主题色名称
* @property {String} bg-color = [grey-lighten-5|white] 默认: grey-lighten-5, 输入框背景色。
* @property {String} border-color = [] 默认: "", 输入框边框类型主题颜色名称。
* @property {Boolean} border-bottom = [false|true] 默认: true, 是否显示下划线
* @property {String} text-color = [black|primary] 默认: black, 输入框文字颜色。
* @property {String} placeholder = [] 默认: 请输入, 占位文字
* @property {Boolean} vertical = [false|true] 默认: false, 是否上下排列
* @property {Number} round = [] 默认: 2, 输入框圆角。
* @property {Boolean} showIndent = [] 默认: true, 是否输入框内部两边缩进
* @property {Number} bg-round = [] 默认: 0, 整体框圆角。
* @property {Number} bg-shadow = [] 默认: 0, 整体框投影。
* @property {String} bg-theme = [] 默认white, 整体框背景
* @property {Boolean} flat = [] 默认: false, 是否去除所有边框
* @property {Number|String} height = [] 默认: 68,
* @property {String} name = [] 默认:'',提交表单时的的字段名称标识
* @property {String} prefixp-text = [] 默认:'',输入框内前缀文字
* @property {String} placeholder-class = [] 默认:'',点位符的自定义类。
* @property {Array} padding = [] 默认:[32,12],左右,上下内间距。
* @property {Function} click 点击输入框时触发发的函数。
* @property {Function} clear 清空时触发携带相关数据
* @property {Function} input 输入时触发携带相关数据
* @example <tm-input ></tm-input>
*
*/
import tmSheet from "@/tm-vuetify/components/tm-sheet/tm-sheet.vue"
import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
export default {
components:{tmSheet,tmIcons},
name:"tm-input",
props: {
//提交表单时的的字段名称
name:{
type:String,
default:''
},
prefixpText:{
type:String,
default:''
},
flat: {
type: Boolean,
default: false
},
//是否输入框内部两边缩进。默认是
showIndent:{
type:Boolean,
default:true
},
maxlength: {
type: Number,
default: -1
},
black: {
type:Boolean|String,
default:null
},
//是否显示聚焦状态
focusShow: {
type:Boolean|String,
default:false
},
titleFontSize:{
type:String,
default:'n',//同类的字号,xxs,xs,s,n,g,lg,xl
},
height:{
type:Number|String,
default:68
},
// 校验规则函数。
verify: {
type: Function,
default: ()=>{
return (val) => {
return {
check: val?.length <= 0 ? false : true,
text: "必填项不能为空。"
};
}
}
},
titleClass: {
type: String,
default: 'text-grey-darken-4'
},
// 是否是必填。如果必填写将会触发基础的校验,不能为空。
required: Boolean,
adjustPosition: Boolean,
autoFocus: Boolean,
confirmType: String,
disabled: Boolean,
password: Boolean,
inputType: {
type: String,
default: 'text'
},
value: {
type: String|Number,
default: ''
},
// 右边外层后缀图标。
rightIcon: {
type: String,
default: ''
},
// 输入框内部前缀图标。
prefixpIcon: {
type: String,
default: ''
},
prefixpIconColor: {
type: String,
default: ''
},
// 左边外层图标。
leftIcon: {
type: String,
default: ''
},
// 后缀文字
suffix: {
type: String,
default: ''
},
// 输入框后缀图标
suffixIcon: {
type: String,
default: ''
},
suffixIconColor:{
type: String,
default: ''
},
// 左边标题。
title: {
type: String,
default: ''
},
fontSize:{
type:Number|String,
default:'n'
},
// 输入框文字对齐方式。left,center,right
align: {
type: String,
default: 'left'
},
// 显示清除图标。
clear: Boolean,
// 主题色名称。
color: {
type: String,
default: 'primary'
},
//输入框背景色。grey-lighten-5
bgColor: {
type: String,
default: ''
},
// 输入框边框类型主题颜色名称。
borderColor: {
type: String,
default: ''
},
// 是否显示下划线
borderBottom: {
type: Boolean,
default: true
},
// text输入框文字颜色。
textColor: {
type: String,
default: 'black'
},
placeholder: {
type: String,
default: "请输入"
},
placeholderClass:{
type:String,
default:'text-grey-lighten-1'
},
// 是否上下排列输入框。
vertical: Boolean,
round:{
type:Number|String,
default:2
},
bgRound:{
type:Number|String,
default:0
},
bgShadow:{
type:Number|String,
default:0
},
bgTheme:{
type:String,
default:'white'
},
//获取焦点。
focus:{
type:Boolean,
default:false
},
padding:{
type:Array,
default:()=>{
return [32,12];
}
},
// 跟随主题色的改变而改变。
fllowTheme:{
type:Boolean|String,
default:true
}
},
data() {
return {
showError: false,
errorText: "请正确填写",
FOCUS_Auto:false,
isFocus:false,
};
},
computed: {
_required(){
return this.required
},
height_rpx:function(){
return this.height;
},
font_size:function () {
let font = {
'xxs':'20rpx',
'xs':'22rpx',
's':'24rpx',
'm':'26rpx',
'n':'28rpx',
'g':'32rpx',
'lg':'36rpx',
'xl':'40rpx'
}
if(typeof this.fontSize=='string') return font[this.fontSize];
return this.fontSize+'rpx';
},
title_size:function () {
let font = {
'xxs':'20rpx',
'xs':'22rpx',
's':'24rpx',
'm':'26rpx',
'n':'28rpx',
'g':'32rpx',
'lg':'36rpx',
'xl':'40rpx'
}
if(typeof this.titleFontSize=='string') return font[this.titleFontSize];
return this.titleFontSize+'rpx';
},
focus_fs:{
get:function(){
return this.FOCUS_Auto;
},
set:function(val){
this.FOCUS_Auto = val;
}
},
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme:function(){
if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
return this.$tm.vx.state().tmVuetify.color;
}
return this.color;
},
valueLen:function(){
// 为了兼容ios不能使用this.valdata.length.
let p = String(this.valdata);
return p?.split('').length||0 ;
},
valdata:{
get:function(){
return this.value;
},
set:function(val){
this.$emit('input', val)
this.$emit('update:value', val)
if (this._required) {
this.$nextTick(function(){
this.verifyInput();
})
}
}
}
},
mounten(){
this.FOCUS_Auto = this.focus;
},
methods: {
onclickInput(e){
this.$emit('click',e)
},
input(e) {
this.valdata = e.target.value;
},
// 校验是否通过。
verifyInput() {
let verify = this.verify.bind(this, this.valdata||'');
verify = verify.call(this,this.valdata||'')
if(typeof verify ==='function'){
verify = verify.call(this,this.valdata||'')
}
if (typeof verify !== 'object') verify = {};
this.showError = !(verify.check??true);
this.errorText = verify.text??"";
return verify.check??true;
},
//清除校验显示 的内容。
clearVerify() {
this.showError = false;
this.errorText = "";
},
blur(e) {
this.isFocus=false;
this.$emit('blur', e)
},
focusFun(e){
this.isFocus=true;
this.$emit('focus',e)
},
clearVal(e){
this.valdata ="";
this.$emit('clear', this.valdata)
}
},
}
</script>
<style lang="scss" scoped>
.tm-input {
.tm-input-center {
width: 100%;
.tm-input-center-wk{
transition: all 0.2s;
}
.tm-input-center-input {
border: none;
background: none;
box-shadow: 0;
width: 100%;
}
}
.tm-input-left {
flex-shrink: 0;
height: 100%;
min-width: 80rpx;
padding-right: 24rpx;
}
.tm-input-col {
.tm-input-left {
max-width: inherit;
padding-right: 0;
}
.tm-input-center {
.tm-input-center-input {
height: 76upx;
}
}
}
.tm-input-right {
height: 100%;
// width: 300upx;
}
}
</style>