<template> <div class="app-input-box" :id="maxlengthAppendId"> <InputNumber v-if="type === 'number'" :id="numberId" :placeholder="placeholder" :formatter="numberFormat" :size="size" :max="max" :min="min" :readonly="readonly" :precision="precision" v-model="CurrentVal" :disabled="disabled ? true : false" :active-change="false" @on-blur="blur" ></InputNumber> <i-input v-else :placeholder="placeholder" :class="{ 'is-disabled': disabled }" :size="size" :type="type" :rows="rows" :password="type == 'password' && enableShowPwd" :readonly="readonly" :maxlength="maxlength" :show-word-limit="showWordLimit" v-model="CurrentVal" :disabled="disabled ? true : false" :element-id="textareaId" @on-enter="enter" @on-blur="blur" @on-focus="focus" > <template v-if="append" #append> <span>{{ append }}</span> </template> <template v-if="prepend" #prepend> <span>{{ prepend }}</span> </template> </i-input> <div class="unit-text">{{ unit }}</div> </div> </template> <script lang="ts"> import { Util, debounce } from "ibiz-core"; import { Vue, Component, Prop, Model, Emit } from "vue-property-decorator"; @Component({}) export default class InputBox extends Vue { /** * 双向绑定值 * @type {any} * @memberof InputBox */ @Model("change") readonly itemValue?: any; /** * 单位 * @type {String} * @memberof InputBox */ @Prop() public unit?: string; /** * 多行文本十行 特殊参数样式(模型高度自带) * @type {*} * @memberof InputBox */ @Prop() public textareaStyle?: any; /** * 多行文本十行 特殊参数id(模型高度自带) * @type {String} * @memberof InputBox */ @Prop() public textareaId?: string; /** * 大小 * @type {String} * @memberof InputBox */ @Prop() public size?: string; /** * 最大值 * @type {Number} * @memberof InputBox */ @Prop() public max?: number; /** * 最小值 * @type {Number} * @memberof InputBox */ @Prop() public min?: number; /** * placeholder值 * @type {String} * @memberof InputBox */ @Prop() public placeholder?: string; /** * 是否禁用 * @type {boolean} * @memberof InputBox */ @Prop() public disabled?: boolean; /** * 只读模式 * * @type {boolean} */ @Prop({ default: false }) public readonly?: boolean; /** * 属性类型 * * @type {string} * @memberof InputBox */ @Prop() public type?: string; /** * 文本行数 * @type {String} * @memberof InputBox */ @Prop({ default: 2 }) public rows?: number; /** * 精度 * * @type {number} * @memberof InputBox */ @Prop({ default: 0 }) public precision?: number; /** * 数值格式化 * * @type {string} * @memberof InputBox */ @Prop() public valueFormat?: any; /** * 是否启用防抖 * * @type {Boolean} * @memberof InputBox */ @Prop({ default: true }) public isDebounce?: Boolean; /** * 密码框是否启用显示值切换图标 * * @type {Boolean} * @memberof InputBox */ @Prop({ default: false }) public enableShowPwd!: Boolean; /** * 输入内容最大长度 * * @type {string} * @memberof InputBox */ @Prop() public maxlength?: number; /** * 输入内容前缀 * * @type {string} * @memberof InputBox */ @Prop() public prepend?: any; /** * 输入内容后缀 * * @type {string} * @memberof InputBox */ @Prop() public append?: any; /** * 是否显示输入内容最大长度 * * @type {string} * @memberof InputBox */ @Prop() public showWordLimit?: boolean; /** * 多行文本类型下最小行数 * * @type {string} * @memberof InputBox */ @Prop() public minRows?: number; /** * 多行文本类型下最大行数 * * @type {string} * @memberof InputBox */ @Prop() public maxRows?: number; /** * 多行文本行数 * * @type {string} * @memberof InputBox */ public autoSize: any = {}; /** * 数值框numberId */ public numberId: string = this.$util.createUUID(); //当同时存在最长长度与后缀词时,input组件的id public maxlengthAppendId: string = this.$util.createUUID(); /** * 当前值 * * @memberof InputBox */ get CurrentVal() { if ( Object.is(this.type, "number") && this.itemValue && !isNaN(this.itemValue) ) { return Number(this.itemValue); } else { return !this.itemValue && this.itemValue != 0 ? null : this.itemValue; } } /** * 值变化 * * @memberof InputBox */ set CurrentVal(val: any) { let _data: any = val; if ( Object.is(this.type, "number") && Util.isExistAndNotEmpty(val) && !isNaN(val) ) { try { _data = isNaN(Number(val)) ? null : Number(val); } catch (error) {} } if (Object.is(_data, "")) { _data = null; } if (this.isDebounce) { debounce(this.emitChangeEvent, [_data], this, 300); } else { this.emitChangeEvent(_data); } } /** * 生命周期 * @type {any} * @memberof InputBox */ public created() { if (this.minRows) { this.autoSize.minRows = this.minRows; } if (this.minRows) { this.autoSize.maxRows = this.maxRows; } } /** * 生命周期 (多行文本高度问题) * @type {any} * @memberof InputBox */ public mounted() { if (this.textareaId) { let textarea: any = document.getElementById(this.textareaId); if (textarea && this.textareaStyle) { Object.keys(this.textareaStyle).forEach((key: string) => { textarea.style[key] = this.textareaStyle[key] }) } } if (this.showWordLimit && (this.append || this.prepend)) { this.setAppendStyle(); } } /** * 触发change事件 * * @param {*} data * @memberof InputBox */ emitChangeEvent(data: any) { this.$emit("change", data); } /** * 回车事件 * * @param {*} $event * @memberof InputBox */ @Emit() public enter($event: any) { if (!$event || $event.keyCode !== 13) { return; } return this.CurrentVal; } /** * 失去焦点事件 * * @param {*} $event * @memberof InputBox */ @Emit() public blur(event: any) { return this.CurrentVal; } /** * 聚焦事件 * * @param {*} $event * @memberof InputBox */ @Emit() public focus(event: any) { return this.CurrentVal; } /** * 数值值格式化 * * @param {*} value * @memberof InputBox */ public numberFormat(value: any) { if (!this.valueFormat) { return value; } const _this: any = this; if ( !isNaN(parseFloat(value)) && _this.textFormat && _this.textFormat instanceof Function ) { return _this.textFormat(parseFloat(value), _this.valueFormat); } return value; } /** * 当同时设置了前缀(或后缀词)与显示最长长度时,或同时拥有单位以及后缀等情况 * 动态重新设置样式,iview原本的样式不支持同时设置 * * @memberof InputBox */ public setAppendStyle() { if (Object.is(this.type, "text") || Object.is(this.type, "textarea")) { this.$nextTick(() => { let input: any = document.getElementById( this.maxlengthAppendId ); if (input) { let appendEle = input.querySelector(".ivu-input-group-append"); let maxlengthEle = input.querySelector(".ivu-input-word-count"); let unitEle = input.querySelector(".unit-text"); let appendEleWidth = null; let maxlengthEleWidth = null; if (appendEle) { appendEleWidth = window .getComputedStyle(appendEle) .getPropertyValue("width"); } if (maxlengthEle) { maxlengthEleWidth = window .getComputedStyle(maxlengthEle) .getPropertyValue("width"); } const setEleStyle = (ele: any) => { ele.style.paddingRight = "5px"; ele.style.marginRight = "1px"; ele.style.zIndex = "10"; }; if (appendEleWidth && maxlengthEleWidth) { const width = Number(appendEleWidth.slice(0, -2)) + Number(maxlengthEleWidth.slice(0, -2)); maxlengthEle.style.right = appendEleWidth; unitEle.style.right = width + "px"; } else if (appendEleWidth) { unitEle.style.right = appendEleWidth; } else if (maxlengthEleWidth) { maxlengthEle.style.right = maxlengthEleWidth; } setEleStyle(unitEle); setEleStyle(maxlengthEle); if (this.prepend) { maxlengthEle.style.zIndex = "10"; } } }); } } } </script>