diff --git a/src/components/advancedSearch/TextMode.vue b/src/components/advancedSearch/TextMode.vue index 5aed6786..325995da 100644 --- a/src/components/advancedSearch/TextMode.vue +++ b/src/components/advancedSearch/TextMode.vue @@ -45,6 +45,7 @@ @load="handleHintLoad" @select="handleSelect" @keydownEnter="handleEnter" + :columnList="columnList" :hintParams="hintParams" :hintSearch="searchStr"> diff --git a/src/components/advancedSearch/showhint/Hint/Hint.vue b/src/components/advancedSearch/showhint/Hint/Hint.vue index 2d331b8d..4835e236 100644 --- a/src/components/advancedSearch/showhint/Hint/Hint.vue +++ b/src/components/advancedSearch/showhint/Hint/Hint.vue @@ -3,7 +3,7 @@
- +
@@ -20,7 +20,8 @@ export default { name: 'Hint', props: { hintList: [], - hintSearch: {} + hintSearch: {}, + columnList: [] }, components: { HintInfo, diff --git a/src/components/advancedSearch/showhint/Hint/HintInfo.vue b/src/components/advancedSearch/showhint/Hint/HintInfo.vue index f3cf5ba3..d34ff4b0 100644 --- a/src/components/advancedSearch/showhint/Hint/HintInfo.vue +++ b/src/components/advancedSearch/showhint/Hint/HintInfo.vue @@ -22,6 +22,9 @@ export default { default () { return [] } + }, + columnList: { + type: Array } }, data () { @@ -52,8 +55,24 @@ export default { const item = vm.hintList[vm.currentIndex] if (item) { this.$emit('keydownEnter', 'Enter') - vm.handleSelect(item, vm.currentIndex, vm.hintList) - vm.currentIndex = -1 + const obj = vm.columnList.find(d => d.label === item.displayText) + // 如果选中label,数组更新,光标处在第一行。如果选择操作符,光标位置不变 + if (obj) { + vm.handleSelect(item, vm.currentIndex, vm.hintList) + const itemDom = document.getElementById('filterItem' + vm.currentIndex) + if (itemDom) { + itemDom.style.backgroundColor = '' + } + vm.$nextTick(() => { + vm.currentIndex = 1 + const itemDom1 = document.getElementById('filterItem1') + if (itemDom1) { + itemDom1.style.backgroundColor = 'var(--el-fill-color-dark)' + } + }) + } else { + vm.handleSelect(item, vm.currentIndex, vm.hintList) + } } else { this.$emit('keydownEnter', null) } @@ -75,11 +94,7 @@ export default { const itemDom = document.getElementById('filterItem' + realIndex) if (itemDom) { itemDom.style.backgroundColor = 'var(--el-fill-color-dark)' - if (realIndex >= 10) { - dom.scrollTop = (realIndex - 10) * 26 + 16 - } else { - dom.scrollTop = 0 - } + itemDom.scrollIntoView(false) } } else { const itemDom = document.getElementById('filterItem' + index) @@ -105,12 +120,7 @@ export default { const itemDom = document.getElementById('filterItem' + realIndex) if (itemDom) { itemDom.style.backgroundColor = 'var(--el-fill-color-dark)' - if (realIndex >= 10) { - // 26是24的行高+2px的margin,16是两个标题总的margin - dom.scrollTop = (realIndex - 10) * 26 + 16 - } else { - dom.scrollTop = 0 - } + itemDom.scrollIntoView(false) } } else { const itemDom = document.getElementById('filterItem' + index) diff --git a/src/components/advancedSearch/showhint/TextSearch/manual-show-hint.js b/src/components/advancedSearch/showhint/TextSearch/manual-show-hint.js index 41ec1be9..ea7d71c0 100644 --- a/src/components/advancedSearch/showhint/TextSearch/manual-show-hint.js +++ b/src/components/advancedSearch/showhint/TextSearch/manual-show-hint.js @@ -4,125 +4,134 @@ export default function (CodeMirror,{ keyboardDown, keyboardEnter }) { - - var HINT_ELEMENT_CLASS = "CodeMirror-hint"; - var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active"; + var HINT_ELEMENT_CLASS = 'CodeMirror-hint' + var ACTIVE_HINT_ELEMENT_CLASS = 'CodeMirror-hint-active' // This is the old interface, kept around for now to stay // backwards-compatible. CodeMirror.showHint = function (cm, getHints, options) { - if (!getHints) return cm.showHint(options); - if (options && options.async) getHints.async = true; - var newOpts = {hint: getHints}; - if (options) for (var prop in options) newOpts[prop] = options[prop]; - return cm.showHint(newOpts); - }; + if (!getHints) return cm.showHint(options) + if (options && options.async) getHints.async = true + var newOpts = { hint: getHints } + if (options) for (var prop in options) newOpts[prop] = options[prop] + return cm.showHint(newOpts) + } - CodeMirror.defineExtension("showHint", function (options) { - options = parseOptions(this, this.getCursor("start"), options); + CodeMirror.defineExtension('showHint', function (options) { + options = parseOptions(this, this.getCursor('start'), options) var selections = this.listSelections() - if (selections.length > 1) return; + if (selections.length > 1) return // By default, don't allow completion when something is selected. // A hint function can have a `supportsSelection` property to // indicate that it can handle selections. if (this.somethingSelected()) { - if (!options.hint.supportsSelection) return; + if (!options.hint.supportsSelection) return // Don't try with cross-line selections - for (var i = 0; i < selections.length; i++) - if (selections[i].head.line != selections[i].anchor.line) return; + for (var i = 0; i < selections.length; i++) { + if (selections[i].head.line != selections[i].anchor.line) return + } } - if (this.state.completionActive) this.state.completionActive.close(); - var completion = this.state.completionActive = new Completion(this, options); - if (!completion.options.hint) return; + if (this.state.completionActive) this.state.completionActive.close() + const completion = this.state.completionActive = new Completion(this, options) + if (!completion.options.hint) return - CodeMirror.signal(this, "startCompletion", this); - completion.update(true); + CodeMirror.signal(this, 'startCompletion', this) + completion.update(true) - cb && cb({completion}) - }); + cb && cb({ completion }) + }) - CodeMirror.defineExtension("closeHint", function () { + CodeMirror.defineExtension('closeHint', function () { if (this.state.completionActive) this.state.completionActive.close() }) - function Completion(cm, options) { - this.cm = cm; - this.options = options; - this.widget = null; - this.debounce = 0; - this.tick = 0; - this.startPos = this.cm.getCursor("start"); - this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length; + function Completion (cm, options) { + this.cm = cm + this.options = options + this.widget = null + this.debounce = 0 + this.tick = 0 + this.startPos = this.cm.getCursor('start') + this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length if (this.options.updateOnCursorActivity) { - var self = this; - cm.on("cursorActivity", this.activityFunc = function () { - self.cursorActivity(); - }); + var self = this + cm.on('cursorActivity', this.activityFunc = function () { + self.cursorActivity() + }) } } var requestAnimationFrame = window.requestAnimationFrame || function (fn) { - return setTimeout(fn, 1000 / 60); - }; - var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout; + return setTimeout(fn, 1000 / 60) + } + var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout Completion.prototype = { close: function () { - if (!this.active()) return; - this.cm.state.completionActive = null; - this.tick = null; + if (!this.active()) return + this.cm.state.completionActive = null + this.tick = null if (this.options.updateOnCursorActivity) { - this.cm.off("cursorActivity", this.activityFunc); + this.cm.off('cursorActivity', this.activityFunc) } - if (this.widget && this.data) CodeMirror.signal(this.data, "close"); - if (this.widget) this.widget.close(); - CodeMirror.signal(this.cm, "endCompletion", this.cm); + if (this.widget && this.data) CodeMirror.signal(this.data, 'close') + if (this.widget) this.widget.close() + CodeMirror.signal(this.cm, 'endCompletion', this.cm) }, active: function () { - return this.cm.state.completionActive == this; + return this.cm.state.completionActive == this }, pick: function (data, i) { - var completion = data.list[i], self = this; + const completion = data.list[i]; const self = this this.cm.operation(function () { - if (completion.hint) - completion.hint(self.cm, data, completion); - else - self.cm.replaceRange(getText(completion), completion.from || data.from, - completion.to || data.to, "complete"); - CodeMirror.signal(data, "pick", completion); - self.cm.scrollIntoView(); - }); + if (completion.hint) { + completion.hint(self.cm, data, completion) + } else if (completion.field) { + if (completion.text === 'in' || completion.text === 'like') { + completion.text = ' ' + completion.text + } + let myString = self.cm.getValue().substring(data.from.ch, data.to.ch) + getText(completion) + if (completion.text === 'has') { + myString = getText(completion) + '(' + self.cm.getValue().substring(data.from.ch, data.to.ch) + ', ) ' + } + self.cm.replaceRange(myString, data.from, data.to, 'complete') + } else { + self.cm.replaceRange(getText(completion), completion.from || data.from, completion.to || data.to, 'complete') + } + CodeMirror.signal(data, 'pick', completion) + self.cm.scrollIntoView() + }) if (this.options.closeOnPick) { - this.close(); + this.close() } }, cursorActivity: function () { if (this.debounce) { - cancelAnimationFrame(this.debounce); - this.debounce = 0; + cancelAnimationFrame(this.debounce) + this.debounce = 0 } - var identStart = this.startPos; + var identStart = this.startPos if (this.data) { - identStart = this.data.from; + identStart = this.data.from } - var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); + const pos = this.cm.getCursor(); const line = this.cm.getLine(pos.line) if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || pos.ch < identStart.ch || this.cm.somethingSelected() || (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { - this.close(); + this.close() } else { - var self = this; + var self = this this.debounce = requestAnimationFrame(function () { - self.update(); - }); - if (this.widget) this.widget.disable(); + self.update() + }) + if (this.widget) this.widget.disable() } }, @@ -135,397 +144,430 @@ export default function (CodeMirror,{ }, finishUpdate: function (data, first) { - if (this.data) CodeMirror.signal(this.data, "update"); + if (this.data) CodeMirror.signal(this.data, 'update') - var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); - if (this.widget) this.widget.close(); + const picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle) + if (this.widget) this.widget.close() - this.data = data; + this.data = data if (data && data.list.length) { if (picked && data.list.length == 1) { - this.pick(data, 0); + this.pick(data, 0) } else { - this.widget = new Widget(this, data); - CodeMirror.signal(data, "shown"); + this.widget = new Widget(this, data) + CodeMirror.signal(data, 'shown') } } } - }; + } - function parseOptions(cm, pos, options) { - var editor = cm.options.hintOptions; - var out = {}; - for (var prop in defaultOptions) out[prop] = defaultOptions[prop]; - if (editor) for (var prop in editor) - if (editor[prop] !== undefined) out[prop] = editor[prop]; - if (options) for (var prop in options) - if (options[prop] !== undefined) out[prop] = options[prop]; + function parseOptions (cm, pos, options) { + const editor = cm.options.hintOptions + const out = {} + for (var prop in defaultOptions) out[prop] = defaultOptions[prop] + if (editor) { + for (var prop in editor) { + if (editor[prop] !== undefined) out[prop] = editor[prop] + } + } + if (options) { + for (var prop in options) { + if (options[prop] !== undefined) out[prop] = options[prop] + } + } if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos) - return out; + return out } - function getText(completion) { - if (typeof completion == "string") return completion; - else return completion.text; + function getText (completion) { + if (typeof completion == 'string') { + return completion + } else { + return completion.text + } } - function buildKeyMap(completion, handle) { + function buildKeyMap (completion, handle) { var baseMap = { Up: function () { - handle.moveFocus(-1); + handle.moveFocus(-1) }, Down: function () { - handle.moveFocus(1); + handle.moveFocus(1) }, PageUp: function () { - handle.moveFocus(-handle.menuSize() + 1, true); + handle.moveFocus(-handle.menuSize() + 1, true) }, PageDown: function () { - handle.moveFocus(handle.menuSize() - 1, true); + handle.moveFocus(handle.menuSize() - 1, true) }, Home: function () { - handle.setFocus(0); + handle.setFocus(0) }, End: function () { - handle.setFocus(handle.length - 1); + handle.setFocus(handle.length - 1) }, // Enter: handle.pick, // Tab: handle.pick, Tab: keyboardEnter, Enter: keyboardEnter, Esc: handle.close - }; + } - var mac = /Mac/.test(navigator.platform); + var mac = /Mac/.test(navigator.platform) if (mac) { - baseMap["Ctrl-P"] = function () { - handle.moveFocus(-1); - }; - baseMap["Ctrl-N"] = function () { - handle.moveFocus(1); - }; + baseMap['Ctrl-P'] = function () { + handle.moveFocus(-1) + } + baseMap['Ctrl-N'] = function () { + handle.moveFocus(1) + } } - var custom = completion.options.customKeys; - var ourMap = custom ? {} : baseMap; + var custom = completion.options.customKeys + var ourMap = custom ? {} : baseMap - function addBinding(key, val) { - var bound; - if (typeof val != "string") + function addBinding (key, val) { + var bound + if (typeof val != 'string') { bound = function (cm) { - return val(cm, handle); - }; - // This mechanism is deprecated - else if (baseMap.hasOwnProperty(val)) - bound = baseMap[val]; - else - bound = val; - ourMap[key] = bound; + return val(cm, handle) + } + }// This mechanism is deprecated + else if (baseMap.hasOwnProperty(val)) { + bound = baseMap[val] + } else { + bound = val + } + ourMap[key] = bound } - if (custom) - for (var key in custom) if (custom.hasOwnProperty(key)) - addBinding(key, custom[key]); - var extra = completion.options.extraKeys; - if (extra) - for (var key in extra) if (extra.hasOwnProperty(key)) - addBinding(key, extra[key]); - return ourMap; + if (custom) { + for (var key in custom) { + if (custom.hasOwnProperty(key)) { + addBinding(key, custom[key]) + } + } + } + var extra = completion.options.extraKeys + if (extra) { + for (var key in extra) { + if (extra.hasOwnProperty(key)) { + addBinding(key, extra[key]) + } + } + } + return ourMap } - function getHintElement(hintsElement, el) { + function getHintElement (hintsElement, el) { while (el && el != hintsElement) { - if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el; - el = el.parentNode; + if (el.nodeName.toUpperCase() === 'LI' && el.parentNode == hintsElement) return el + el = el.parentNode } } - function Widget(completion, data) { - this.id = "cm-complete-" + Math.floor(Math.random(1e6)) - this.completion = completion; - this.data = data; - this.picked = false; - var widget = this, cm = completion.cm; - var ownerDocument = cm.getInputField().ownerDocument; - var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow; + function Widget (completion, data) { + this.id = 'cm-complete-' + Math.floor(Math.random(1e6)) + this.completion = completion + this.data = data + this.picked = false + var widget = this, cm = completion.cm + var ownerDocument = cm.getInputField().ownerDocument + var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow - var hints = this.hints = ownerDocument.createElement("ul"); + var hints = this.hints = ownerDocument.createElement('ul') // $(hints).append(` //

lalallalla

// `) - hints.setAttribute("role", "listbox") - hints.setAttribute("aria-expanded", "true") + hints.setAttribute('role', 'listbox') + hints.setAttribute('aria-expanded', 'true') hints.id = this.id - var theme = completion.cm.options.theme; - hints.className = "CodeMirror-hints " + theme; - this.selectedHint = data.selectedHint || 0; + var theme = completion.cm.options.theme + hints.className = 'CodeMirror-hints ' + theme + this.selectedHint = data.selectedHint || 0 - var completions = data.list; + var completions = data.list for (var i = 0; i < completions.length; ++i) { - var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i]; - var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS); - if (cur.className != null) className = cur.className + " " + className; - elt.className = className; - if (i == this.selectedHint) elt.setAttribute("aria-selected", "true") - elt.id = this.id + "-" + i - elt.setAttribute("role", "option") - if (cur.render) cur.render(elt, data, cur); - else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur))); - elt.hintId = i; + var elt = hints.appendChild(ownerDocument.createElement('li')), cur = completions[i] + var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? '' : ' ' + ACTIVE_HINT_ELEMENT_CLASS) + if (cur.className != null) className = cur.className + ' ' + className + elt.className = className + if (i == this.selectedHint) elt.setAttribute('aria-selected', 'true') + elt.id = this.id + '-' + i + elt.setAttribute('role', 'option') + if (cur.render) { + cur.render(elt, data, cur) + } else { + elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur))) + } + elt.hintId = i } - var container = completion.options.container || ownerDocument.body; - var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); - var left = pos.left, top = pos.bottom, below = true; - var offsetLeft = 0, offsetTop = 0; + var container = completion.options.container || ownerDocument.body + var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null) + var left = pos.left, top = pos.bottom, below = true + var offsetLeft = 0, offsetTop = 0 if (container !== ownerDocument.body) { // We offset the cursor position because left and top are relative to the offsetParent's top left corner. - var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1; - var offsetParent = isContainerPositioned ? container : container.offsetParent; - var offsetParentPosition = offsetParent.getBoundingClientRect(); - var bodyPosition = ownerDocument.body.getBoundingClientRect(); - offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft); - offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop); + var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1 + var offsetParent = isContainerPositioned ? container : container.offsetParent + var offsetParentPosition = offsetParent.getBoundingClientRect() + var bodyPosition = ownerDocument.body.getBoundingClientRect() + offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft) + offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop) } - hints.style.left = (left - offsetLeft) + "px"; - hints.style.top = (top - offsetTop) + "px"; + hints.style.left = (left - offsetLeft) + 'px' + hints.style.top = (top - offsetTop) + 'px' // todo 隐藏codemirror自带的提示 hints.style.display = 'none' // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor. - var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth); - var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight); + var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth) + var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight) //不用默认的DOM 下拉提示 // container.appendChild(hints); hints.remove() - cm.getInputField().setAttribute("aria-autocomplete", "list") - cm.getInputField().setAttribute("aria-owns", this.id) - cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint) + cm.getInputField().setAttribute('aria-autocomplete', 'list') + cm.getInputField().setAttribute('aria-owns', this.id) + cm.getInputField().setAttribute('aria-activedescendant', this.id + '-' + this.selectedHint) - var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect(); - var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false; + var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect() + var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false // Compute in the timeout to avoid reflow on init - var startScroll; + var startScroll setTimeout(function () { - startScroll = cm.getScrollInfo(); - }); + startScroll = cm.getScrollInfo() + }) - var overlapY = box.bottom - winH; + var overlapY = box.bottom - winH if (overlapY > 0) { - var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); + var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top) if (curTop - height > 0) { // Fits above cursor - hints.style.top = (top = pos.top - height - offsetTop) + "px"; - below = false; + hints.style.top = (top = pos.top - height - offsetTop) + 'px' + below = false } else if (height > winH) { - hints.style.height = (winH - 5) + "px"; - hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px"; - var cursor = cm.getCursor(); + hints.style.height = (winH - 5) + 'px' + hints.style.top = (top = pos.bottom - box.top - offsetTop) + 'px' + var cursor = cm.getCursor() if (data.from.ch != cursor.ch) { - pos = cm.cursorCoords(cursor); - hints.style.left = (left = pos.left - offsetLeft) + "px"; - box = hints.getBoundingClientRect(); + pos = cm.cursorCoords(cursor) + hints.style.left = (left = pos.left - offsetLeft) + 'px' + box = hints.getBoundingClientRect() } } } - var overlapX = box.right - winW; - if (scrolls) overlapX += cm.display.nativeBarWidth; + var overlapX = box.right - winW + if (scrolls) overlapX += cm.display.nativeBarWidth if (overlapX > 0) { if (box.right - box.left > winW) { - hints.style.width = (winW - 5) + "px"; - overlapX -= (box.right - box.left) - winW; + hints.style.width = (winW - 5) + 'px' + overlapX -= (box.right - box.left) - winW + } + hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + 'px' + } + if (scrolls) { + for (var node = hints.firstChild; node; node = node.nextSibling) { + node.style.paddingRight = cm.display.nativeBarWidth + 'px' } - hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + "px"; } - if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling) - node.style.paddingRight = cm.display.nativeBarWidth + "px" // debugger cm.addKeyMap(this.keyMap = buildKeyMap(completion, { moveFocus: function (n, avoidWrap) { n === -1 ? keyboardUp && keyboardUp() : keyboardDown && keyboardDown() - widget.changeActive(widget.selectedHint + n, avoidWrap); + widget.changeActive(widget.selectedHint + n, avoidWrap) }, setFocus: function (n) { - widget.changeActive(n); + widget.changeActive(n) }, menuSize: function () { - return widget.screenAmount(); + return widget.screenAmount() }, length: completions.length, close: function () { - completion.close(); + completion.close() }, pick: function () { - widget.pick(); + widget.pick() }, data: data - })); + })) if (completion.options.closeOnUnfocus) { - var closingOnBlur; - cm.on("blur", this.onBlur = function () { + var closingOnBlur + cm.on('blur', this.onBlur = function () { closingOnBlur = setTimeout(function () { - completion.close(); - }, 100); - }); - cm.on("focus", this.onFocus = function () { - clearTimeout(closingOnBlur); - }); + completion.close() + }, 100) + }) + cm.on('focus', this.onFocus = function () { + clearTimeout(closingOnBlur) + }) } - cm.on("scroll", this.onScroll = function () { - var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); - if (!startScroll) startScroll = cm.getScrollInfo(); - var newTop = top + startScroll.top - curScroll.top; - var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop); - if (!below) point += hints.offsetHeight; - if (point <= editor.top || point >= editor.bottom) return completion.close(); - hints.style.top = newTop + "px"; - hints.style.left = (left + startScroll.left - curScroll.left) + "px"; - }); + cm.on('scroll', this.onScroll = function () { + var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect() + if (!startScroll) startScroll = cm.getScrollInfo() + var newTop = top + startScroll.top - curScroll.top + var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop) + if (!below) point += hints.offsetHeight + if (point <= editor.top || point >= editor.bottom) return completion.close() + hints.style.top = newTop + 'px' + hints.style.left = (left + startScroll.left - curScroll.left) + 'px' + }) - CodeMirror.on(hints, "dblclick", function (e) { - var t = getHintElement(hints, e.target || e.srcElement); + CodeMirror.on(hints, 'dblclick', function (e) { + var t = getHintElement(hints, e.target || e.srcElement) if (t && t.hintId != null) { - widget.changeActive(t.hintId); - widget.pick(); + widget.changeActive(t.hintId) + widget.pick() } - }); + }) - CodeMirror.on(hints, "click", function (e) { - var t = getHintElement(hints, e.target || e.srcElement); + CodeMirror.on(hints, 'click', function (e) { + var t = getHintElement(hints, e.target || e.srcElement) if (t && t.hintId != null) { - widget.changeActive(t.hintId); - if (completion.options.completeOnSingleClick) widget.pick(); + widget.changeActive(t.hintId) + if (completion.options.completeOnSingleClick) widget.pick() } - }); + }) - CodeMirror.on(hints, "mousedown", function () { + CodeMirror.on(hints, 'mousedown', function () { setTimeout(function () { - cm.focus(); - }, 20); - }); + cm.focus() + }, 20) + }) // The first hint doesn't need to be scrolled to on init - var selectedHintRange = this.getSelectedHintRange(); + var selectedHintRange = this.getSelectedHintRange() if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) { - this.scrollToActive(); + this.scrollToActive() } - CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); - return true; + CodeMirror.signal(data, 'select', completions[this.selectedHint], hints.childNodes[this.selectedHint]) + return true } Widget.prototype = { close: function () { - if (this.completion.widget != this) return; - this.completion.widget = null; - if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints); - this.completion.cm.removeKeyMap(this.keyMap); + if (this.completion.widget != this) return + this.completion.widget = null + if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints) + this.completion.cm.removeKeyMap(this.keyMap) var input = this.completion.cm.getInputField() - input.removeAttribute("aria-activedescendant") - input.removeAttribute("aria-owns") + input.removeAttribute('aria-activedescendant') + input.removeAttribute('aria-owns') - var cm = this.completion.cm; + var cm = this.completion.cm if (this.completion.options.closeOnUnfocus) { - cm.off("blur", this.onBlur); - cm.off("focus", this.onFocus); + cm.off('blur', this.onBlur) + cm.off('focus', this.onFocus) } - cm.off("scroll", this.onScroll); + cm.off('scroll', this.onScroll) }, disable: function () { - this.completion.cm.removeKeyMap(this.keyMap); - var widget = this; + this.completion.cm.removeKeyMap(this.keyMap) + var widget = this this.keyMap = { Enter: function () { - widget.picked = true; + widget.picked = true } - }; - this.completion.cm.addKeyMap(this.keyMap); + } + this.completion.cm.addKeyMap(this.keyMap) }, pick: function () { - this.completion.pick(this.data, this.selectedHint); + this.completion.pick(this.data, this.selectedHint) }, changeActive: function (i, avoidWrap) { - if (i >= this.data.list.length) - i = avoidWrap ? this.data.list.length - 1 : 0; - else if (i < 0) - i = avoidWrap ? 0 : this.data.list.length - 1; - if (this.selectedHint == i) return; - var node = this.hints.childNodes[this.selectedHint]; - if (node) { - node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); - node.removeAttribute("aria-selected") + if (i >= this.data.list.length) { + i = avoidWrap ? this.data.list.length - 1 : 0 + } else if (i < 0) { + i = avoidWrap ? 0 : this.data.list.length - 1 } - node = this.hints.childNodes[this.selectedHint = i]; - node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; - node.setAttribute("aria-selected", "true") - this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id) + if (this.selectedHint == i) return + var node = this.hints.childNodes[this.selectedHint] + if (node) { + node.className = node.className.replace(' ' + ACTIVE_HINT_ELEMENT_CLASS, '') + node.removeAttribute('aria-selected') + } + node = this.hints.childNodes[this.selectedHint = i] + node.className += ' ' + ACTIVE_HINT_ELEMENT_CLASS + node.setAttribute('aria-selected', 'true') + this.completion.cm.getInputField().setAttribute('aria-activedescendant', node.id) this.scrollToActive() - CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node); + CodeMirror.signal(this.data, 'select', this.data.list[this.selectedHint], node) }, scrollToActive: function () { - var selectedHintRange = this.getSelectedHintRange(); - var node1 = this.hints.childNodes[selectedHintRange.from]; - var node2 = this.hints.childNodes[selectedHintRange.to]; - var firstNode = this.hints.firstChild; - if (node1.offsetTop < this.hints.scrollTop) - this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop; - else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) - this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop; + var selectedHintRange = this.getSelectedHintRange() + var node1 = this.hints.childNodes[selectedHintRange.from] + var node2 = this.hints.childNodes[selectedHintRange.to] + var firstNode = this.hints.firstChild + if (node1.offsetTop < this.hints.scrollTop) { + this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop + } else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) { + this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop + } }, screenAmount: function () { - return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1; + return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1 }, getSelectedHintRange: function () { - var margin = this.completion.options.scrollMargin || 0; + var margin = this.completion.options.scrollMargin || 0 return { from: Math.max(0, this.selectedHint - margin), to: Math.min(this.data.list.length - 1, this.selectedHint + margin), - }; + } } - }; + } - function applicableHelpers(cm, helpers) { + function applicableHelpers (cm, helpers) { if (!cm.somethingSelected()) return helpers var result = [] - for (var i = 0; i < helpers.length; i++) + for (var i = 0; i < helpers.length; i++) { if (helpers[i].supportsSelection) result.push(helpers[i]) + } return result } - function fetchHints(hint, cm, options, callback) { + function fetchHints (hint, cm, options, callback) { if (hint.async) { hint(cm, callback, options) } else { var result = hint(cm, options) - if (result && result.then) result.then(callback) - else callback(result) + if (result && result.then) { + result.then(callback) + } else { + callback(result) + } } } - function resolveAutoHints(cm, pos) { - var helpers = cm.getHelpers(pos, "hint"), words + function resolveAutoHints (cm, pos) { + var helpers = cm.getHelpers(pos, 'hint'), words if (helpers.length) { var resolved = function (cm, callback, options) { - var app = applicableHelpers(cm, helpers); + var app = applicableHelpers(cm, helpers) - function run(i) { + function run (i) { if (i == app.length) return callback(null) fetchHints(app[i], cm, options, function (result) { - if (result && result.list.length > 0) callback(result) - else run(i + 1) + if (result && result.list.length > 0) { + callback(result) + } else { + run(i + 1) + } }) } @@ -534,9 +576,9 @@ export default function (CodeMirror,{ resolved.async = true resolved.supportsSelection = true return resolved - } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { + } else if (words = cm.getHelper(cm.getCursor(), 'hintWords')) { return function (cm) { - return CodeMirror.hint.fromList(cm, {words: words}) + return CodeMirror.hint.fromList(cm, { words: words }) } } else if (CodeMirror.hint.anyword) { return function (cm, options) { @@ -548,28 +590,35 @@ export default function (CodeMirror,{ } } - CodeMirror.registerHelper("hint", "auto", { + CodeMirror.registerHelper('hint', 'auto', { resolve: resolveAutoHints - }); + }) - CodeMirror.registerHelper("hint", "fromList", function (cm, options) { + CodeMirror.registerHelper('hint', 'fromList', function (cm, options) { var cur = cm.getCursor(), token = cm.getTokenAt(cur) var term, from = CodeMirror.Pos(cur.line, token.start), to = cur if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) { term = token.string.substr(0, cur.ch - token.start) } else { - term = "" + term = '' from = cur } - var found = []; + var found = [] for (var i = 0; i < options.words.length; i++) { - var word = options.words[i]; - if (word.slice(0, term.length) == term) - found.push(word); + var word = options.words[i] + if (word.slice(0, term.length) == term) { + found.push(word) + } } - if (found.length) return {list: found, from: from, to: to}; - }); + if (found.length) { + return { + list: found, + from: from, + to: to + } + } + }) CodeMirror.commands.autocomplete = CodeMirror.showHint; diff --git a/src/components/advancedSearch/showhint/packages/getDataset.js b/src/components/advancedSearch/showhint/packages/getDataset.js index 1217e189..d545b41e 100644 --- a/src/components/advancedSearch/showhint/packages/getDataset.js +++ b/src/components/advancedSearch/showhint/packages/getDataset.js @@ -8,16 +8,35 @@ export class Dataset { this.sourceData = this.keepSourcedata(operatesList, funcDic, filtersList, operatesDic, operatorManual, fields, doc) // 存储格式化的数据 this.hintData = {} + this.columnList = JSON.parse(JSON.stringify(filtersList)) this.hintData.operatesList = this.formatOperates(operatesList) this.hintData.filtersList = this.formatFilters(filtersList) } getHintList (keyword, sqlKeywordsOptions = null, callback, completeFilter) { // 获取提示列表 - const operatesList = this.matchFilter(sqlKeywordsOptions || this.hintData.operatesList || [], keyword) - const filtersList = this.matchFilter(this.hintData.filtersList || [], keyword) + let operatesList = this.matchFilter(sqlKeywordsOptions || this.hintData.operatesList || [], keyword) + let filtersList = this.matchFilter(this.hintData.filtersList || [], keyword) + let fieldOperatesList = [] + if (keyword) { + const obj = this.columnList.find(d => d.label === keyword) + if (obj) { + const operatorFunctions = obj.doc && obj.doc.constraints && obj.doc.constraints.operator_functions + fieldOperatesList = this.formatFieldOperates(operatorFunctions.split(',')) + } else if (keyword === '=') { + fieldOperatesList = this.formatFieldOperates(['=']) + filtersList = [] + } else if (keyword === 'in') { + fieldOperatesList = this.formatFieldOperates(['in']) + operatesList = [] + filtersList = [] + } else if (keyword === 'like') { + fieldOperatesList = this.formatFieldOperates(['like']) + filtersList = [] + } + } - const hintList = [...operatesList, ...filtersList] + const hintList = [...operatesList, ...filtersList, ...fieldOperatesList] callback && callback(operatesList, filtersList, hintList) return hintList } @@ -110,6 +129,29 @@ export class Dataset { return results } + formatFieldOperates (list) { + // 格式化操作符,如=,in,like + const tempTitle = { + type: 'abstract', + text: '', + displayText: i18n.global.t('overall.operators'), + className: 'divider hint-title', + hint (cm, callback, options) { + } + } + + const results = list.map((item) => { + return { + text: item, + displayText: item, + className: 'filter-item el-dropdown-menu__item relative-item', + field: item + } + }) + results.unshift(tempTitle) + return results + } + keepSourcedata (operatesList, funcDic, filtersList, operatesDic, operatorManual, fields, doc) { // 初始化原始数据 方法(存放的是 全量原始数据) const sourceData = {}