<template> <el-input ref="input" :id="id" type="textarea" :cols="cols" :rows="rows" v-bind="attrs" v-bind:disabled="isDisable" :value="value" @input="onInput" > <template v-slot:suffix> <slot name="suffix"></slot> </template> </el-input> </template> <script> const SP_STR = "✌"; const SP_CHAR=SP_STR.charCodeAt(0); const LINE_CHAR="\n" const SWIFT_CHARS = " \r'()+,-./01234567890:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const SWIFTZ_CHARS = " \r!\"#%&'()+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz{"; const CHARSET = ["","",SWIFT_CHARS,SWIFTZ_CHARS] export default { props: { value: { type: [String, Number], default: undefined }, disabled: { type: Boolean, default: false }, id: { type: String, default: undefined }, cols:{ type:Number, default:1 }, rows:{ type:Number, default:1 }, chsbit:{ type:Number, default:2 }, charmod:{ type:Number, default:0 //0任意模式,1英文模式,2 swift模式 3 swiftz模式 } }, computed: { mode () { return this.$store.state.Status.mode }, isDisable: { get () { return this.mode === 'display' || this.disabled } }, highlight () { return this.$store.state.Status.highlights.indexOf(this.id) !== -1 }, highlightChanges () { return this.$store.state.Status.highlightChanges.indexOf(this.id) !== -1 }, attrs(){ if(this.mode === 'display' || this.disabled) { let {placeholder,...rest} = this.$attrs return rest } return this.$attrs } }, methods:{ formatVal(oriVal){ let val = oriVal; if(!val){ return val; } let position = this.getCursorPosition(); val = val.substring(0,position)+SP_STR+val.substring(position) let arr = val.split(/\r?\n|\r/g); let arrNew = []; arr.forEach(line=>{ let lineArr = this.formatLine(line); arrNew.push(...lineArr); }); if(arrNew.length > this.rows){ let obj = this.getTextarea(); //内容已经输满了 if(obj.selectionStart == obj.selectionEnd && oriVal.length == this.value.length+1){ this.$position = position - 1; return this.value; } arrNew = arrNew.slice(0,this.rows); } let result = arrNew.join(LINE_CHAR); position = result.indexOf(SP_STR); result = result.substring(0,position)+result.substring(position+1); this.$position = position return result; }, formatLine(val){ if(!val){ return [""]; } if(val == SP_STR){ return [SP_STR] } let valCopy = val; let newVal = []; while(valCopy && valCopy!=SP_STR){ let length = 0; let i=0; let spCnt =0; let autoLine = ""; for(; i<valCopy.length && i<this.cols+spCnt && length<this.cols; i++) { var c = valCopy.charCodeAt(i); let cStr = valCopy.charAt(i); if(c == SP_CHAR){ spCnt++; autoLine+=SP_STR; continue; } else if ((c >= 0x0001 && c <= 0x007e) || ( c >= 0xff60 && c <= 0xff9f )){ //判断字符集 if(this.charmod>1 && CHARSET[this.charmod].indexOf(cStr)==-1){ spCnt++; //非法字符集 continue; } length ++; autoLine+=cStr; } else if(length <= this.cols - this.chsbit){ //中文字符 if(this.charmod){ spCnt++; //非法字符集 continue; } length += this.chsbit; autoLine+=cStr; } else{ break; } } //autoLine = valCopy.substring(0,i); newVal.push(autoLine); valCopy = valCopy.substring(i); } //不要丢失光标 if(valCopy == SP_STR){ newVal[newVal.length - 1] = newVal[newVal.length - 1]+SP_STR; } return newVal; }, getTextarea(){ return this.$refs.input.$el.children[0]; }, getCursorPosition(){ let obj = this.getTextarea(); let position = obj.selectionStart return position; }, setCursorPosition(position){ let obj = this.getTextarea(); if(obj.createTextRange) { var tr = obj.createTextRange(); tr.collapse(true); tr.moveStart('character', position); tr.select(); } else if (obj.setSelectionRange) obj.setSelectionRange(position, position); }, onInput(newVal){ let extraCnt = 0; if(this.value && newVal.length == this.value.length -1 ){ let obj = this.getTextarea(); if(obj.selectionStart == obj.selectionEnd && obj.selectionStart<newVal.length && this.value.charAt(obj.selectionStart)=="\n"){ //删除中间换行符,额外再筛除一个字符,避免被重新格式化 newVal = newVal.substring(0,obj.selectionStart - 1)+newVal.substring(obj.selectionStart) extraCnt = -2; } } newVal = this.formatVal(newVal); console.log(newVal) this.$emitNewValue = newVal; this.$emit('input', newVal) setTimeout(()=>{ this.setCursorPosition(this.$position+extraCnt) },0) } }, watch:{ cols(){ let newVal = this.formatVal(this.value); this.$emitNewValue = newVal; this.$emit('input', newVal) }, rows(){ let newVal = this.formatVal(this.value); this.$emitNewValue = newVal; this.$emit('input', newVal) }, value(val,oldval){ if(val == this.$emitNewValue){ return; } let newVal = this.formatVal(val); this.$emit('input', newVal); } } } </script> <style> /* .el-input.highlight .el-input__inner{ border-color: red; } .el-textarea.highlight .el-textarea__inner { border-color: red; } .el-input.change-light .el-input__inner{ border-color: #E6A23C; } .el-textarea.change-light .el-textarea__inner { border-color: #E6A23C; } */ </style>