绩效考核手机版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

230 lines
7.0 KiB

<template>
<view class="s-code-input" :class="c_class" :style="c_style">
<view
v-for="(item, index) of list"
:key="index"
class="s-code-input__item"
:style="item_style[index]"
>
<view
v-if="dot && codeValues.length > index"
class="s-code-input__item__dot"
:style="dot_style"
></view>
<text v-else class="s-code-input__item__text" :style="text_style">
{{ codeValues[index] || "" }}
</text>
<view
v-if="mode === 'line'"
class="s-code-input__item__line"
:style="line_style"
></view>
<view
v-if="isFocus && codeValues.length === index"
:style="cursor_style"
class="s-code-input__item__cursor"
></view>
</view>
<input
:disabled="disabledKeyboard"
type="number"
:focus="focus"
:value="inputValue"
:maxlength="maxlength"
class="s-code-input__input"
:style="input_style"
@input="handleChange"
@focus="isFocus = true"
@blur="isFocus = false"
/>
</view>
</template>
<script>
import componentMixin from '../../mixins/componentMixin';
/**
* s-code-input
* @description 用于验证用户短信验证码的场景
* @property {Number} maxlength 最大输入长度 (默认 4 )
* @property {Boolean} dot 是否用圆点填充 (默认 false )
* @property {String} mode 显示模式,box-盒子模式,line-底部横线模式 (默认 'box' )
* @property {Boolean} hairline 是否细边框 (默认 false )
* @property {String|Number} gutter 字符间的距离 (默认 20 )
* @property {String|Number} value 预置值
* @property {Boolean} focus 是否自动获取焦点 (默认 false )
* @property {Boolean} bold 字体和输入横线是否加粗 (默认 false )
* @property {String} color 字体颜色
* @property {String|Number} fontSize 字体大小,单位px (默认 36 )
* @property {String|Number} size 输入框的大小,宽等于高 (默认 70 )
* @property {Boolean} disabledKeyboard 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true (默认 false )
* @property {String} borderColor 边框和线条颜色
* @property {String|Number} borderRadius mode等于box时边框圆角 (默认 6 )
* @property {Boolean} disabledDot 是否禁止输入"."符号 (默认 true )
* @property {String|Object} textStyle 数字样式
* @property {String|Object} itemStyle 数字块样式
* @property {String|Object} lineStyle 下划线样式
* @property {String|Object} dotStyle dot点样式
* @property {String|Object} cursorStyle 光标样式
* @event {Function} change(value) 输入内容发生改变时触发,具体见上方说明 value:当前输入的值
* @event {Function} finish(value) 输入字符个数达maxlength值时触发,见上方说明 value:当前输入的值
* @example <s-code-input v-model="value" />
*/
export default {
name: 'SCodeInput',
mixins: [componentMixin],
props: {
maxlength: {
type: Number,
default: 4,
},
dot: Boolean,
mode: {
type: String,
default: 'box',
},
hairline: Boolean,
gutter: {
type: [String, Number],
default: 20,
},
value: {
type: [String, Number],
default: '',
},
focus: Boolean,
bold: Boolean,
color: String,
fontSize: [String, Number],
size: [String, Number],
disabledKeyboard: Boolean,
borderColor: String,
borderRadius: {
type: [String, Number],
default: 6,
},
disabledDot: {
type: Boolean,
default: true,
},
textStyle: [String, Object],
itemStyle: [String, Object],
lineStyle: [String, Object],
dotStyle: [String, Object],
cursorStyle: [String, Object],
},
data: () => ({
inputValue: '',
isFocus: false,
}),
computed: {
c_class() {
return this.$mergeClass({
[`s-code-input--${this.mode}`]: this.mode && this.mode !== 'none',
's-code-input--dot]': this.dot,
}, this.custom_class);
},
c_style() {
return this.$mergeStyle(this.custom_style);
},
input_style() {
return this.$mergeStyle({
height: this.$addUnit(this.size),
});
},
list() {
return new Array(Number(this.maxlength)).fill(1);
},
item_style() {
const { size, mode, hairline, borderColor, gutter, list } = this;
const borderRadius = this.$addUnit(this.borderRadius);
return this.list.map((_, index) => {
const style = {
width: this.$addUnit(size),
height: this.$addUnit(size),
};
if (index > 0) {
style.marginLeft = this.$addUnit(gutter);
}
if (mode === 'box') {
style.borderWidth = `${hairline ? 0.5 : 1}px`;
style.borderColor = borderColor;
if (this.$toPx(gutter) > 0) {
style.borderRadius = borderRadius;
} else {
if (index === 0) {
style.borderTopLeftRadius = borderRadius;
style.borderBottomLeftRadius = borderRadius;
}
if (index === list.length - 1) {
style.borderTopRightRadius = borderRadius;
style.borderBottomRightRadius = borderRadius;
}
if (index !== list.length - 1) {
style.borderRight = 'none';
}
}
}
return this.$mergeStyle(style, this.itemStyle);
});
},
text_style() {
return this.$mergeStyle({
fontSize: this.$addUnit(this.fontSize),
fontWeight: this.bold ? 'bold' : '',
color: this.color,
}, this.textStyle);
},
codeValues() {
return String(this.inputValue).split('');
},
line_style() {
const style = {};
style.width = this.$addUnit(this.size);
style.backgroundColor = this.borderColor;
return this.$mergeStyle(style, this.lineStyle);
},
dot_style() {
return this.$mergeStyle(this.dotStyle);
},
cursor_style() {
return this.$mergeStyle({
backgroundColor: this.color,
}, this.cursorStyle);
},
},
watch: {
value: {
immediate: true,
handler(val) {
this.inputValue = String(val).substring(0, this.maxlength);
},
},
},
created() {
this.isFocus = this.focus;
},
methods: {
handleChange(e) {
const value = e.detail.value;
this.inputValue = value;
// 是否允许输入“.”符号
if (this.disabledDot) {
this.$nextTick(() => {
this.inputValue = value.replace('.', '');
});
}
// 未达到maxlength之前,发送change事件,达到后发送finish事件
this.$emit('change', value);
// 修改通过v-model双向绑定的值
this.$emit('input', value);
// 达到用户指定输入长度时,发出完成事件
if (String(value).length >= Number(this.maxlength)) {
this.$emit('finish', value);
}
},
},
};
</script>
<style lang="scss" src="./index.scss"></style>