mrr.sj.front/components/highlight-textarea/highlight-textarea.vue

297 lines
7.1 KiB
Vue
Raw Permalink 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="highlight-box">
<template v-if="type === 'textarea'">
<view v-if="value"
class="textarea-outer"
ref="textareaOuter"
>
<view ref="outerInner" class="outer-inner"
v-html="highlightHtml(value)">
</view>
</view>
<textarea
ref="textareaBox"
maxlength="1000"
auto-height
:autoSize="true"
@blur="blur"
:placeholder="placeholder"
v-model:value="value">
</textarea>
</template>
<template v-if="type === 'input'">
<view v-if="value"
class="input-outer"
v-html="highlightHtml(value)">
</view>
<a-input type="text" class="ant-input"
:placeholder="placeholder"
v-model:value.trim="value"/>
</template>
</view>
</template>
<script >
export default {
name: 'HighlightTextarea',
data() {
return {
value: ''
};
},
props: {
placeholder: {
type: String,
required: false,
default: '请输入'
},
text: {
type: String,
required: false,
default: ''
},
highlightKey: {
type: Array,
require: false,
default: () => []
},
type: {
type: String,
required: true,
default: 'textarea'
},
maxHeight: {
type: Number,
required: false,
default: 220
},
modelValue: {
type: String,
default: ''
}
},
watch: {
value (v) {
// this.value = this.text.replace(/(^\s*)|(\s*$)/g, '').replace(/<br \/>|<br\/>|<br>/g, '\n');
this.$emit("input", v);
},
modelValue: {
deep: true,
immediate: true,
handler(v) {
console.log(v, 'modelValue 3333')
this.value = v ? this.modelValue : ''
},
},
disabled: {
deep: true,
immediate: true,
handler(v) {
// this.editorConfig.readOnly = v
// this.$nextTick(() => {
// if (this.editor) v ? this.editor.disable() : this.editor.enable();
// })
},
}
},
created() {
// this.value = this.text.replace(/(^\s*)|(\s*$)/g, '').replace(/<br \/>|<br\/>|<br>/g, '\n');
},
mounted() {
// this.scrollMousewheel();
},
methods: {
setValue(newValue) {
this.value = newValue;
// 触发所有必要的事件
this.$emit('input', newValue);
this.$emit('update:modelValue', newValue);
this.$emit('change', newValue);
},
highlightHtml(str) {
if ((!str || !this.highlightKey || this.highlightKey.length === 0) && this.type !== 'textarea') {
return str;
}
let rebuild = str;
if (this.type === 'textarea') {
rebuild = rebuild.replace(/\n/g, '<br/>').replace(/\s/g, '&nbsp;');
// textarea有滚动条时view底部不能和textarea重合故加一个<br/>
// const wrap = this.$refs.textareaBox;
// if (wrap && wrap.scrollHeight > this.maxHeight) {
// rebuild = rebuild + '<br/>';
// }
}
if (this.highlightKey.filter(item => ~str.indexOf(item)).length) {
let regStr = '';
let regExp = null;
this.highlightKey.forEach(list => {
regStr = this.escapeString(list);
regExp = new RegExp(regStr, 'g');
rebuild = rebuild.replace(regExp,`<span style="color:red">${list}</span>`);
});
}
return rebuild;
},
blur(){
this.$emit("blur")
},
syncScrollTop() {
const wrap = this.$refs.textareaBox;
const outerWrap = this.$refs.textareaOuter;
const outerInner = this.$refs.outerInner;
if (wrap.scrollHeight > this.maxHeight && outerInner.scrollHeight !== wrap.scrollHeight) {
outerInner.style.height = `${wrap.scrollHeight}px`;
}
if (wrap.scrollTop !== outerWrap.scrollTop) {
outerWrap.scrollTop = wrap.scrollTop;
}
},
// scrollMousewheel() {
// if (this.type === 'input') {
// return;
// }
// this.$nextTick(() => {
// this.eventHandler('add');
// });
// },
// 处理字符串中可能对正则有影响的字符
escapeString(value) {
const characterss = ['(', ')', '[', ']', '{', '}', '^', '$', '|', '?', '*', '+', '.'];
let str = value.replace(new RegExp('\\\\', 'g'), '\\\\');
characterss.forEach(function (characters) {
let r = new RegExp('\\' + characters, 'g');
str = str.replace(r, '\\' + characters);
});
return str;
},
eventHandler(type) {
const wrap = this.$refs.textareaBox;
if (wrap) {
let mousewheelevt = (/Firefox/i.test(navigator.userAgent))
? 'DOMMouseScroll' : 'mousewheel';
wrap[`${type}EventListener`](mousewheelevt, this.syncScrollTop);
wrap[`${type}EventListener`]('scroll', this.syncScrollTop);
}
}
},
destroyed() {
// this.eventHandler('remove');
}
};
</script>
<style lang="less">
@width: 100%; // 500px
.highlight-box {
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
position: relative;
display: flex;
//font-size: 12px;
width: @width;
//position: relative;
//color: #333333;
background: #ffffff;
border-radius: 2px;
overflow: hidden;
.textarea-outer,
.input-outer {
box-sizing: border-box;
width: @width;
position: absolute;
top: 0;
left: 0;
right: 0;
// border: 1px solid transparent;
border-top: 0;
// 鼠标事件失效 ie6-10不支持
pointer-events: none;
cursor: text;
color: #333333;
font-weight: 400;
font-size: 28rpx;
line-height: 40rpx;
span {
color: red; // #F27C49
}
&:hover {
border-color: #4C84FF;
}
}
.textarea-outer {
overflow-y: auto;
//line-height: 20px;
word-break: break-all;
.outer-inner {
// padding: 5px 8px;
width: 100%;
box-sizing: border-box;
}
}
textarea {
width: @width;
//line-height: 20px;
resize: none;
}
.input-outer,
input {
width: @width;
height: 32px;
line-height: 32px;
}
.input-outer {
bottom: 0;
padding: 0 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
textarea,
input {
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
//font-size: 12px;
// position: relative;
// z-index: 2;
// 光标的颜色
//color: #333333;
// 文本颜色
text-shadow: 0 0 0 rgba(0, 0, 0, 0);
-webkit-text-fill-color: transparent;
// color: transparent;
// color: #333333;
font-weight: 400;
font-size: 28rpx;
line-height: 40rpx;
min-height: 300rpx;
background: transparent;
border-radius: 2px;
// border: 1px solid #d9d9d9;
padding: 0px;
box-sizing: border-box;
//&::placeholder {
// -webkit-text-fill-color: #d5d5d5;
//}
//&:hover {
// border-color: #36cfc9;
//}
//&:focus {
// border-color:#36cfc9;
// box-shadow: 0 0 0 2px #DBE4FF;
// outline: none;
//}
.textarea-placeholder{
-webkit-text-fill-color: #B8B8B8;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 28rpx;
color: #B8B8B8;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
}
}
</style>