|
12 | 12 | <template>
|
13 | 13 | <div class="tag-textarea">
|
14 | 14 | <div class="rf-form-wrapper">
|
15 |
| - <template v-if="formMode"> |
16 |
| - <div class="rf-form-wrap" :class="{ 'input-focus': input.focus, 'input-disable': isDisabled }"> |
17 |
| - <div |
18 |
| - ref="input" |
19 |
| - class="div-input" |
20 |
| - :class="{ |
21 |
| - 'input-before': !input.value && !pasteIng |
22 |
| - }" |
23 |
| - :contenteditable="!isDisabled" |
24 |
| - :data-placeholder="placeholder" |
25 |
| - data-test-name="formTag_textarea_divInput" |
26 |
| - v-bk-clickoutside="handleClickOutSide" |
27 |
| - @mouseup="handleInputMouseUp" |
28 |
| - @focus="handleInputFocus" |
29 |
| - @keydown="handleInputKeyDown" |
30 |
| - @input="handleInputChange" |
31 |
| - @blur="handleBlur"> |
32 |
| - </div> |
| 15 | + <div class="rf-form-wrap" :class="{ 'input-focus': input.focus, 'input-disable': isDisabled, 'view-mode': !formMode }"> |
| 16 | + <div |
| 17 | + ref="input" |
| 18 | + class="div-input" |
| 19 | + :class="{ |
| 20 | + 'input-before': !input.value && !pasteIng |
| 21 | + }" |
| 22 | + :contenteditable="!isDisabled" |
| 23 | + :data-placeholder="placeholder" |
| 24 | + data-test-name="formTag_textarea_divInput" |
| 25 | + v-bk-clickoutside="handleClickOutSide" |
| 26 | + @mouseup="handleInputMouseUp" |
| 27 | + @focus="handleInputFocus" |
| 28 | + @keydown="handleInputKeyDown" |
| 29 | + @input="handleInputChange" |
| 30 | + @blur="handleBlur"> |
33 | 31 | </div>
|
34 |
| - <transition> |
35 |
| - <div |
36 |
| - class="rf-select-list" |
37 |
| - :style="`${varListPosition}`" |
38 |
| - v-show="showVarList && isListOpen"> |
39 |
| - <ul class="rf-select-content"> |
40 |
| - <li |
41 |
| - class="rf-select-item" |
42 |
| - v-for="item in varList" |
43 |
| - :key="item.key" |
44 |
| - :class="{ 'is-hover': hoverKey === item.key }" |
45 |
| - @click.stop="onSelectVal(item.key)"> |
46 |
| - <span class="key">{{ item.key }}</span> |
47 |
| - <span class="name" v-bk-overflow-tips>{{ item.name }}</span> |
48 |
| - </li> |
49 |
| - </ul> |
50 |
| - </div> |
51 |
| - </transition> |
52 |
| - </template> |
53 |
| - <span v-else class="rf-view-value">{{ viewValue }}</span> |
| 32 | + </div> |
| 33 | + <transition> |
| 34 | + <div |
| 35 | + class="rf-select-list" |
| 36 | + :style="`${varListPosition}`" |
| 37 | + v-show="showVarList && isListOpen"> |
| 38 | + <ul class="rf-select-content"> |
| 39 | + <li |
| 40 | + class="rf-select-item" |
| 41 | + v-for="item in varList" |
| 42 | + :key="item.key" |
| 43 | + :class="{ 'is-hover': hoverKey === item.key }" |
| 44 | + @click.stop="onSelectVal(item.key)"> |
| 45 | + <span class="key">{{ item.key }}</span> |
| 46 | + <span class="name" v-bk-overflow-tips>{{ item.name }}</span> |
| 47 | + </li> |
| 48 | + </ul> |
| 49 | + </div> |
| 50 | + </transition> |
54 | 51 | </div>
|
55 | 52 | <span v-show="!validateInfo.valid" class="common-error-tip error-info">{{validateInfo.message}}</span>
|
56 | 53 | </div>
|
|
170 | 167 | const divInputDom = this.$el.querySelector('.div-input')
|
171 | 168 | if (divInputDom) {
|
172 | 169 | const value = typeof this.value === 'string' ? this.value : JSON.stringify(this.value)
|
173 |
| - divInputDom.innerText = value |
174 |
| - if (this.render && value) { |
| 170 | + divInputDom.innerText = this.formMode ? value : this.viewValue |
| 171 | + if (this.formMode && this.render && value) { |
175 | 172 | this.updateInputHtml()
|
176 | 173 | }
|
177 | 174 | divInputDom.addEventListener('paste', this.handlePaste)
|
|
286 | 283 | const lastNode = textNode.childNodes[startOffset - 1]
|
287 | 284 | previousText = lastNode.textContent
|
288 | 285 | }
|
289 |
| - // 如果不包含$则不进行后续计算、 如果是完整全局变量则不进行后续操作 |
290 |
| - if (previousText.indexOf('$') === -1 || /\${[a-zA-Z_][\w|.]*}/.test(previousText)) { |
| 286 | + // 过滤掉完整变量结构,取最后面一段的纯文本 |
| 287 | + previousText = previousText.split(/\${[a-zA-Z_][\w|.]*}/).pop() |
| 288 | + // 如果不包含$则不进行后续计算 |
| 289 | + if (previousText.indexOf('$') === -1) { |
291 | 290 | this.isListOpen = false
|
292 | 291 | return
|
293 | 292 | }
|
|
390 | 389 | const varRegexp = /\${([^${}]+)}/g
|
391 | 390 | const divInputDom = this.$el.querySelector('.div-input')
|
392 | 391 | const childNodes = Array.from(divInputDom.childNodes).filter(item => item.nodeName !== 'TEXT')
|
393 |
| - const deleteMap = {} // 需要删除的br下标 |
394 | 392 | childNodes.forEach((dom, index) => {
|
395 |
| - // 删除多余的br标签 |
396 |
| - if (deleteMap[index]) { |
397 |
| - divInputDom.removeChild(dom) |
398 |
| - return |
399 |
| - } |
400 | 393 | // 获取行内纯文本
|
401 | 394 | let domValue = dom.textContent
|
402 | 395 | if (dom.childNodes.length) {
|
|
437 | 430 | })
|
438 | 431 | // 初始化时\n会转化为【独占一行】的<br>标签,导致渲染异常。当我们手动把text标签转为div标签时需要删除【紧挨】着的<br>标签
|
439 | 432 | if (dom.nodeName === '#text') {
|
440 |
| - // 记录需要被删除的br标签下标 |
441 |
| - if (dom.nextSibling?.nodeName === 'BR') { |
442 |
| - deleteMap[index + 1] = true |
443 |
| - } |
444 | 433 | const newDom = document.createElement('div')
|
445 | 434 | newDom.innerHTML = innerHtml
|
446 | 435 | divInputDom.replaceChild(newDom, dom)
|
447 | 436 | } else if (dom.nodeName === 'DIV' && innerHtml) {
|
448 | 437 | dom.innerHTML = innerHtml
|
449 | 438 | } else if (dom.nodeName === 'BR') {
|
450 |
| - // br标签实际上是初始化时\n转化的,\n表示当前行换行了,那么br标签必定会有下一行!!! |
451 |
| - if (!dom.nextSibling) { |
452 |
| - const appendDom = document.createElement('div') |
453 |
| - appendDom.innerHTML = '<br>' |
454 |
| - divInputDom.appendChild(appendDom) |
| 439 | + if (dom.previousSibling && dom.nextSibling && dom.nextSibling?.nodeName !== 'BR') { |
| 440 | + divInputDom.removeChild(dom) |
| 441 | + } else { |
| 442 | + const newDom = document.createElement('div') |
| 443 | + newDom.innerHTML = '<br>' |
| 444 | + divInputDom.replaceChild(newDom, dom) |
455 | 445 | }
|
456 |
| - const newDom = document.createElement('div') |
457 |
| - newDom.innerHTML = '<br>' |
458 |
| - divInputDom.replaceChild(newDom, dom) |
459 | 446 | }
|
460 | 447 | })
|
461 | 448 | },
|
|
563 | 550 | position: absolute;
|
564 | 551 | top: 40px;
|
565 | 552 | right: 0;
|
| 553 | + width: max-content; |
566 | 554 | max-width: 600px;
|
567 | 555 | background: #ffffff;
|
568 | 556 | border: 1px solid #dcdee5;
|
|
618 | 606 | cursor: not-allowed;
|
619 | 607 | }
|
620 | 608 | }
|
| 609 | + &.view-mode { |
| 610 | + padding: 0; |
| 611 | + border: none; |
| 612 | + background: inherit; |
| 613 | + cursor: default; |
| 614 | + } |
621 | 615 | }
|
622 | 616 | .div-input {
|
623 | 617 | min-height: 36px;
|
|
644 | 638 | word-break: break-all;
|
645 | 639 | }
|
646 | 640 | &.input-before::before {
|
| 641 | + position: absolute; |
647 | 642 | content: attr(data-placeholder);
|
648 | 643 | color: #c4c6cc;
|
649 | 644 | }
|
|
0 commit comments