fix: 执行lint,调整书写格式

This commit is contained in:
chenjinsong
2024-06-27 10:19:28 +08:00
parent 6df4e871cd
commit fc2115e883
31 changed files with 4285 additions and 4314 deletions

View File

@@ -92,7 +92,7 @@ export default {
username: '', username: '',
pin: '', pin: '',
language: '', language: '',
licenseStatus: -1,//-1 未获取后台数据状态0 获取后台数据且验证成功1 获取后台数据且验证失败; licenseStatus: -1, // -1 未获取后台数据状态0 获取后台数据且验证成功1 获取后台数据且验证失败;
licenseStatusErrMsg: '', licenseStatusErrMsg: '',
downloadC2vUrl: api.downloadLicenseC2v, downloadC2vUrl: api.downloadLicenseC2v,
supportID: '' supportID: ''

File diff suppressed because one or more lines are too long

View File

@@ -12,11 +12,13 @@ export default function createHint (hitType = 'default', CodeMirror, {
keyboardDown, keyboardDown,
keyboardEnter keyboardEnter
}) { }) {
hitType === 'default' ? showHint(CodeMirror) : manualShowHint(CodeMirror, { hitType === 'default'
cb: callback, ? showHint(CodeMirror)
keyboardUp, : manualShowHint(CodeMirror, {
keyboardDown, cb: callback,
keyboardEnter keyboardUp,
}) keyboardDown,
keyboardEnter
})
sqlHint(CodeMirror, { dataset, hinthook, keywordshook }) sqlHint(CodeMirror, { dataset, hinthook, keywordshook })
} }

View File

@@ -1,25 +1,25 @@
export default function (CodeMirror,{ export default function (CodeMirror, {
cb, cb,
keyboardUp, keyboardUp,
keyboardDown, keyboardDown,
keyboardEnter keyboardEnter
}) { }) {
var HINT_ELEMENT_CLASS = 'CodeMirror-hint' const HINT_ELEMENT_CLASS = 'CodeMirror-hint'
var ACTIVE_HINT_ELEMENT_CLASS = 'CodeMirror-hint-active' const ACTIVE_HINT_ELEMENT_CLASS = 'CodeMirror-hint-active'
// This is the old interface, kept around for now to stay // This is the old interface, kept around for now to stay
// backwards-compatible. // backwards-compatible.
CodeMirror.showHint = function (cm, getHints, options) { CodeMirror.showHint = function (cm, getHints, options) {
if (!getHints) return cm.showHint(options) if (!getHints) return cm.showHint(options)
if (options && options.async) getHints.async = true if (options && options.async) getHints.async = true
var newOpts = { hint: getHints } const newOpts = { hint: getHints }
if (options) for (var prop in options) newOpts[prop] = options[prop] if (options) for (const prop in options) newOpts[prop] = options[prop]
return cm.showHint(newOpts) return cm.showHint(newOpts)
} }
CodeMirror.defineExtension('showHint', function (options) { CodeMirror.defineExtension('showHint', function (options) {
options = parseOptions(this, this.getCursor('start'), options) options = parseOptions(this, this.getCursor('start'), options)
var selections = this.listSelections() const selections = this.listSelections()
if (selections.length > 1) return if (selections.length > 1) return
// By default, don't allow completion when something is selected. // By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to // A hint function can have a `supportsSelection` property to
@@ -27,7 +27,7 @@ export default function (CodeMirror,{
if (this.somethingSelected()) { if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return if (!options.hint.supportsSelection) return
// Don't try with cross-line selections // Don't try with cross-line selections
for (var i = 0; i < selections.length; i++) { for (let i = 0; i < selections.length; i++) {
if (selections[i].head.line != selections[i].anchor.line) return if (selections[i].head.line != selections[i].anchor.line) return
} }
} }
@@ -55,17 +55,17 @@ export default function (CodeMirror,{
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length
if (this.options.updateOnCursorActivity) { if (this.options.updateOnCursorActivity) {
var self = this const self = this
cm.on('cursorActivity', this.activityFunc = function () { cm.on('cursorActivity', this.activityFunc = function () {
self.cursorActivity() self.cursorActivity()
}) })
} }
} }
var requestAnimationFrame = window.requestAnimationFrame || function (fn) { const requestAnimationFrame = window.requestAnimationFrame || function (fn) {
return setTimeout(fn, 1000 / 60) return setTimeout(fn, 1000 / 60)
} }
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout const cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout
Completion.prototype = { Completion.prototype = {
close: function () { close: function () {
@@ -116,7 +116,7 @@ export default function (CodeMirror,{
this.debounce = 0 this.debounce = 0
} }
var identStart = this.startPos let identStart = this.startPos
if (this.data) { if (this.data) {
identStart = this.data.from identStart = this.data.from
} }
@@ -127,7 +127,7 @@ export default function (CodeMirror,{
(!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close() this.close()
} else { } else {
var self = this const self = this
this.debounce = requestAnimationFrame(function () { this.debounce = requestAnimationFrame(function () {
self.update() self.update()
}) })
@@ -137,7 +137,7 @@ export default function (CodeMirror,{
update: function (first) { update: function (first) {
if (this.tick == null) return if (this.tick == null) return
var self = this, myTick = ++this.tick const self = this; const myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function (data) { fetchHints(this.options.hint, this.cm, this.options, function (data) {
if (self.tick == myTick) self.finishUpdate(data, first) if (self.tick == myTick) self.finishUpdate(data, first)
}) })
@@ -189,7 +189,7 @@ export default function (CodeMirror,{
} }
function buildKeyMap (completion, handle) { function buildKeyMap (completion, handle) {
var baseMap = { const baseMap = {
Up: function () { Up: function () {
handle.moveFocus(-1) handle.moveFocus(-1)
}, },
@@ -215,7 +215,7 @@ export default function (CodeMirror,{
Esc: handle.close Esc: handle.close
} }
var mac = /Mac/.test(navigator.platform) const mac = /Mac/.test(navigator.platform)
if (mac) { if (mac) {
baseMap['Ctrl-P'] = function () { baseMap['Ctrl-P'] = function () {
@@ -226,11 +226,11 @@ export default function (CodeMirror,{
} }
} }
var custom = completion.options.customKeys const custom = completion.options.customKeys
var ourMap = custom ? {} : baseMap const ourMap = custom ? {} : baseMap
function addBinding (key, val) { function addBinding (key, val) {
var bound let bound
if (typeof val != 'string') { if (typeof val != 'string') {
bound = function (cm) { bound = function (cm) {
return val(cm, handle) return val(cm, handle)
@@ -251,7 +251,7 @@ export default function (CodeMirror,{
} }
} }
} }
var extra = completion.options.extraKeys const extra = completion.options.extraKeys
if (extra) { if (extra) {
for (var key in extra) { for (var key in extra) {
if (extra.hasOwnProperty(key)) { if (extra.hasOwnProperty(key)) {
@@ -274,25 +274,25 @@ export default function (CodeMirror,{
this.completion = completion this.completion = completion
this.data = data this.data = data
this.picked = false this.picked = false
var widget = this, cm = completion.cm const widget = this; const cm = completion.cm
var ownerDocument = cm.getInputField().ownerDocument const ownerDocument = cm.getInputField().ownerDocument
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow const parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow
var hints = this.hints = ownerDocument.createElement('ul') const hints = this.hints = ownerDocument.createElement('ul')
// $(hints).append(` // $(hints).append(`
// <h1>lalallalla</h1> // <h1>lalallalla</h1>
// `) // `)
hints.setAttribute('role', 'listbox') hints.setAttribute('role', 'listbox')
hints.setAttribute('aria-expanded', 'true') hints.setAttribute('aria-expanded', 'true')
hints.id = this.id hints.id = this.id
var theme = completion.cm.options.theme const theme = completion.cm.options.theme
hints.className = 'CodeMirror-hints ' + theme hints.className = 'CodeMirror-hints ' + theme
this.selectedHint = data.selectedHint || 0 this.selectedHint = data.selectedHint || 0
var completions = data.list const completions = data.list
for (var i = 0; i < completions.length; ++i) { for (let i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(ownerDocument.createElement('li')), cur = completions[i] const elt = hints.appendChild(ownerDocument.createElement('li')); const cur = completions[i]
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? '' : ' ' + ACTIVE_HINT_ELEMENT_CLASS) let className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? '' : ' ' + ACTIVE_HINT_ELEMENT_CLASS)
if (cur.className != null) className = cur.className + ' ' + className if (cur.className != null) className = cur.className + ' ' + className
elt.className = className elt.className = className
if (i == this.selectedHint) elt.setAttribute('aria-selected', 'true') if (i == this.selectedHint) elt.setAttribute('aria-selected', 'true')
@@ -306,16 +306,16 @@ export default function (CodeMirror,{
elt.hintId = i elt.hintId = i
} }
var container = completion.options.container || ownerDocument.body const container = completion.options.container || ownerDocument.body
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null) let pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null)
var left = pos.left, top = pos.bottom, below = true let left = pos.left; let top = pos.bottom; let below = true
var offsetLeft = 0, offsetTop = 0 let offsetLeft = 0; let offsetTop = 0
if (container !== ownerDocument.body) { if (container !== ownerDocument.body) {
// We offset the cursor position because left and top are relative to the offsetParent's top left corner. // 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 const isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1
var offsetParent = isContainerPositioned ? container : container.offsetParent const offsetParent = isContainerPositioned ? container : container.offsetParent
var offsetParentPosition = offsetParent.getBoundingClientRect() const offsetParentPosition = offsetParent.getBoundingClientRect()
var bodyPosition = ownerDocument.body.getBoundingClientRect() const bodyPosition = ownerDocument.body.getBoundingClientRect()
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft) offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft)
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop) offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop)
} }
@@ -325,10 +325,10 @@ export default function (CodeMirror,{
hints.style.display = 'none' 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. // 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) const winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth)
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight) const winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight)
//不用默认的DOM 下拉提示 // 不用默认的DOM 下拉提示
// container.appendChild(hints); // container.appendChild(hints);
hints.remove() hints.remove()
@@ -336,25 +336,25 @@ export default function (CodeMirror,{
cm.getInputField().setAttribute('aria-owns', this.id) cm.getInputField().setAttribute('aria-owns', this.id)
cm.getInputField().setAttribute('aria-activedescendant', this.id + '-' + this.selectedHint) cm.getInputField().setAttribute('aria-activedescendant', this.id + '-' + this.selectedHint)
var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect() let box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect()
var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false const scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false
// Compute in the timeout to avoid reflow on init // Compute in the timeout to avoid reflow on init
var startScroll let startScroll
setTimeout(function () { setTimeout(function () {
startScroll = cm.getScrollInfo() startScroll = cm.getScrollInfo()
}) })
var overlapY = box.bottom - winH const overlapY = box.bottom - winH
if (overlapY > 0) { if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top) const height = box.bottom - box.top; const curTop = pos.top - (pos.bottom - box.top)
if (curTop - height > 0) { // Fits above cursor if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height - offsetTop) + 'px' hints.style.top = (top = pos.top - height - offsetTop) + 'px'
below = false below = false
} else if (height > winH) { } else if (height > winH) {
hints.style.height = (winH - 5) + 'px' hints.style.height = (winH - 5) + 'px'
hints.style.top = (top = pos.bottom - box.top - offsetTop) + 'px' hints.style.top = (top = pos.bottom - box.top - offsetTop) + 'px'
var cursor = cm.getCursor() const cursor = cm.getCursor()
if (data.from.ch != cursor.ch) { if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor) pos = cm.cursorCoords(cursor)
hints.style.left = (left = pos.left - offsetLeft) + 'px' hints.style.left = (left = pos.left - offsetLeft) + 'px'
@@ -362,7 +362,7 @@ export default function (CodeMirror,{
} }
} }
} }
var overlapX = box.right - winW let overlapX = box.right - winW
if (scrolls) overlapX += cm.display.nativeBarWidth if (scrolls) overlapX += cm.display.nativeBarWidth
if (overlapX > 0) { if (overlapX > 0) {
if (box.right - box.left > winW) { if (box.right - box.left > winW) {
@@ -372,7 +372,7 @@ export default function (CodeMirror,{
hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + 'px' hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + 'px'
} }
if (scrolls) { if (scrolls) {
for (var node = hints.firstChild; node; node = node.nextSibling) { for (let node = hints.firstChild; node; node = node.nextSibling) {
node.style.paddingRight = cm.display.nativeBarWidth + 'px' node.style.paddingRight = cm.display.nativeBarWidth + 'px'
} }
} }
@@ -400,7 +400,7 @@ export default function (CodeMirror,{
})) }))
if (completion.options.closeOnUnfocus) { if (completion.options.closeOnUnfocus) {
var closingOnBlur let closingOnBlur
cm.on('blur', this.onBlur = function () { cm.on('blur', this.onBlur = function () {
closingOnBlur = setTimeout(function () { closingOnBlur = setTimeout(function () {
completion.close() completion.close()
@@ -412,10 +412,10 @@ export default function (CodeMirror,{
} }
cm.on('scroll', this.onScroll = function () { cm.on('scroll', this.onScroll = function () {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect() const curScroll = cm.getScrollInfo(); const editor = cm.getWrapperElement().getBoundingClientRect()
if (!startScroll) startScroll = cm.getScrollInfo() if (!startScroll) startScroll = cm.getScrollInfo()
var newTop = top + startScroll.top - curScroll.top const newTop = top + startScroll.top - curScroll.top
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop) let point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop)
if (!below) point += hints.offsetHeight if (!below) point += hints.offsetHeight
if (point <= editor.top || point >= editor.bottom) return completion.close() if (point <= editor.top || point >= editor.bottom) return completion.close()
hints.style.top = newTop + 'px' hints.style.top = newTop + 'px'
@@ -423,7 +423,7 @@ export default function (CodeMirror,{
}) })
CodeMirror.on(hints, 'dblclick', function (e) { CodeMirror.on(hints, 'dblclick', function (e) {
var t = getHintElement(hints, e.target || e.srcElement) const t = getHintElement(hints, e.target || e.srcElement)
if (t && t.hintId != null) { if (t && t.hintId != null) {
widget.changeActive(t.hintId) widget.changeActive(t.hintId)
widget.pick() widget.pick()
@@ -431,7 +431,7 @@ export default function (CodeMirror,{
}) })
CodeMirror.on(hints, 'click', function (e) { CodeMirror.on(hints, 'click', function (e) {
var t = getHintElement(hints, e.target || e.srcElement) const t = getHintElement(hints, e.target || e.srcElement)
if (t && t.hintId != null) { if (t && t.hintId != null) {
widget.changeActive(t.hintId) widget.changeActive(t.hintId)
if (completion.options.completeOnSingleClick) widget.pick() if (completion.options.completeOnSingleClick) widget.pick()
@@ -445,7 +445,7 @@ export default function (CodeMirror,{
}) })
// The first hint doesn't need to be scrolled to on init // The first hint doesn't need to be scrolled to on init
var selectedHintRange = this.getSelectedHintRange() const selectedHintRange = this.getSelectedHintRange()
if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) { if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
this.scrollToActive() this.scrollToActive()
} }
@@ -460,11 +460,11 @@ export default function (CodeMirror,{
this.completion.widget = null this.completion.widget = null
if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints) if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints)
this.completion.cm.removeKeyMap(this.keyMap) this.completion.cm.removeKeyMap(this.keyMap)
var input = this.completion.cm.getInputField() const input = this.completion.cm.getInputField()
input.removeAttribute('aria-activedescendant') input.removeAttribute('aria-activedescendant')
input.removeAttribute('aria-owns') input.removeAttribute('aria-owns')
var cm = this.completion.cm const cm = this.completion.cm
if (this.completion.options.closeOnUnfocus) { if (this.completion.options.closeOnUnfocus) {
cm.off('blur', this.onBlur) cm.off('blur', this.onBlur)
cm.off('focus', this.onFocus) cm.off('focus', this.onFocus)
@@ -474,7 +474,7 @@ export default function (CodeMirror,{
disable: function () { disable: function () {
this.completion.cm.removeKeyMap(this.keyMap) this.completion.cm.removeKeyMap(this.keyMap)
var widget = this const widget = this
this.keyMap = { this.keyMap = {
Enter: function () { Enter: function () {
widget.picked = true widget.picked = true
@@ -494,7 +494,7 @@ export default function (CodeMirror,{
i = avoidWrap ? 0 : this.data.list.length - 1 i = avoidWrap ? 0 : this.data.list.length - 1
} }
if (this.selectedHint == i) return if (this.selectedHint == i) return
var node = this.hints.childNodes[this.selectedHint] let node = this.hints.childNodes[this.selectedHint]
if (node) { if (node) {
node.className = node.className.replace(' ' + ACTIVE_HINT_ELEMENT_CLASS, '') node.className = node.className.replace(' ' + ACTIVE_HINT_ELEMENT_CLASS, '')
node.removeAttribute('aria-selected') node.removeAttribute('aria-selected')
@@ -508,10 +508,10 @@ export default function (CodeMirror,{
}, },
scrollToActive: function () { scrollToActive: function () {
var selectedHintRange = this.getSelectedHintRange() const selectedHintRange = this.getSelectedHintRange()
var node1 = this.hints.childNodes[selectedHintRange.from] const node1 = this.hints.childNodes[selectedHintRange.from]
var node2 = this.hints.childNodes[selectedHintRange.to] const node2 = this.hints.childNodes[selectedHintRange.to]
var firstNode = this.hints.firstChild const firstNode = this.hints.firstChild
if (node1.offsetTop < this.hints.scrollTop) { if (node1.offsetTop < this.hints.scrollTop) {
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop
} else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) { } else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) {
@@ -524,18 +524,18 @@ export default function (CodeMirror,{
}, },
getSelectedHintRange: function () { getSelectedHintRange: function () {
var margin = this.completion.options.scrollMargin || 0 const margin = this.completion.options.scrollMargin || 0
return { return {
from: Math.max(0, this.selectedHint - margin), from: Math.max(0, this.selectedHint - margin),
to: Math.min(this.data.list.length - 1, 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 if (!cm.somethingSelected()) return helpers
var result = [] const result = []
for (var i = 0; i < helpers.length; i++) { for (let i = 0; i < helpers.length; i++) {
if (helpers[i].supportsSelection) result.push(helpers[i]) if (helpers[i].supportsSelection) result.push(helpers[i])
} }
return result return result
@@ -545,7 +545,7 @@ export default function (CodeMirror,{
if (hint.async) { if (hint.async) {
hint(cm, callback, options) hint(cm, callback, options)
} else { } else {
var result = hint(cm, options) const result = hint(cm, options)
if (result && result.then) { if (result && result.then) {
result.then(callback) result.then(callback)
} else { } else {
@@ -555,10 +555,10 @@ export default function (CodeMirror,{
} }
function resolveAutoHints (cm, pos) { function resolveAutoHints (cm, pos) {
var helpers = cm.getHelpers(pos, 'hint'), words const helpers = cm.getHelpers(pos, 'hint'); let words
if (helpers.length) { if (helpers.length) {
var resolved = function (cm, callback, options) { const resolved = function (cm, callback, options) {
var app = applicableHelpers(cm, helpers) const app = applicableHelpers(cm, helpers)
function run (i) { function run (i) {
if (i == app.length) return callback(null) if (i == app.length) return callback(null)
@@ -595,17 +595,17 @@ export default function (CodeMirror,{
}) })
CodeMirror.registerHelper('hint', 'fromList', function (cm, options) { CodeMirror.registerHelper('hint', 'fromList', function (cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur) const cur = cm.getCursor(); const token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur let term; let from = CodeMirror.Pos(cur.line, token.start); const to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) { if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start) term = token.string.substr(0, cur.ch - token.start)
} else { } else {
term = '' term = ''
from = cur from = cur
} }
var found = [] const found = []
for (var i = 0; i < options.words.length; i++) { for (let i = 0; i < options.words.length; i++) {
var word = options.words[i] const word = options.words[i]
if (word.slice(0, term.length) == term) { if (word.slice(0, term.length) == term) {
found.push(word) found.push(word)
} }
@@ -620,7 +620,7 @@ export default function (CodeMirror,{
} }
}) })
CodeMirror.commands.autocomplete = CodeMirror.showHint; CodeMirror.commands.autocomplete = CodeMirror.showHint
var defaultOptions = { var defaultOptions = {
hint: CodeMirror.hint.auto, hint: CodeMirror.hint.auto,
@@ -629,7 +629,7 @@ export default function (CodeMirror,{
closeCharacters: /[\s()\[\]{};:>,]/, closeCharacters: /[\s()\[\]{};:>,]/,
closeOnPick: false, closeOnPick: false,
closeOnUnfocus: false, //阻止提示信息 失焦关闭 closeOnUnfocus: false, // 阻止提示信息 失焦关闭
// closeOnUnfocus: false, // closeOnUnfocus: false,
updateOnCursorActivity: true, updateOnCursorActivity: true,
@@ -638,8 +638,7 @@ export default function (CodeMirror,{
customKeys: null, customKeys: null,
extraKeys: null, extraKeys: null,
paddingForScrollbar: true, paddingForScrollbar: true,
moveOnOverlap: true, moveOnOverlap: true
}; }
CodeMirror.defineOption("hintOptions", null); CodeMirror.defineOption('hintOptions', null)
} }

View File

@@ -1,222 +1,216 @@
//正则 向前去找关键字 // 正则 向前去找关键字
/* 用于匹配关系数据 */ /* 用于匹配关系数据 */
function matchOperator(CodeMirror, hintParams = {}) { function matchOperator (CodeMirror, hintParams = {}) {
var editor = hintParams.editor; const editor = hintParams.editor
var Pos = CodeMirror.Pos const Pos = CodeMirror.Pos
var cur = hintParams.cur; const cur = hintParams.cur
var token = hintParams.token; let token = hintParams.token
if (!editor) { if (!editor) {
return return
} }
let start = token.start
var start = token.start; let cont = true
var cont = true; const leftTokenGroup = []
var leftTokenGroup = [];
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(token.string.match(/^[ ]*$/) || start === 0); //只用空格做终止条件 cont = !(token.string.match(/^[ ]*$/) || start === 0) // 只用空格做终止条件
} }
var cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end)) const cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end))
//判断是不是满足 运算符 表达式的正则 // 判断是不是满足 运算符 表达式的正则
//test 如果是ig 会改变正则指针: https://my.oschina.net/jamesview/blog/5460753 // test 如果是ig 会改变正则指针: https://my.oschina.net/jamesview/blog/5460753
var reg = /^(.*?)(=|!=|>|<|>=|<=)([^ ]*?)$/; const reg = /^(.*?)(=|!=|>|<|>=|<=)([^ ]*?)$/
if (reg.test(cursorLeftString)) { if (reg.test(cursorLeftString)) {
var execArr = reg.exec(cursorLeftString) || [] const execArr = reg.exec(cursorLeftString) || []
return { return {
leftTokenGroup, leftTokenGroup,
cursorLeftString, cursorLeftString,
label: execArr[1], label: execArr[1],
sign: execArr[2], sign: execArr[2],
value: execArr[3], value: execArr[3]
} }
} }
return null return null
} }
function matchCommon(CodeMirror, hintParams = {}) { function matchCommon (CodeMirror, hintParams = {}) {
//通用情况 QUANTILE(expr,level) 左括号右侧第一个就是 关键字 // 通用情况 QUANTILE(expr,level) 左括号右侧第一个就是 关键字
var editor = hintParams.editor; const editor = hintParams.editor
var Pos = CodeMirror.Pos const Pos = CodeMirror.Pos
var cur = hintParams.cur; const cur = hintParams.cur
var token = hintParams.token; let token = hintParams.token
if (!editor) { if (!editor) {
return return
} }
let start = token.start
var start = token.start; let cont = true
var cont = true; const leftTokenGroup = []
var leftTokenGroup = [];
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(token.string.match(/^[ (]*$/) || start === 0); //括号或者空格为终止条件 cont = !(token.string.match(/^[ (]*$/) || start === 0) // 括号或者空格为终止条件
//括号补上 // 括号补上
if (token.string === '(') { if (token.string === '(') {
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
} }
} }
var cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end)) const cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end))
//判断是不是满足 运算符 表达式的正则 // 判断是不是满足 运算符 表达式的正则
var reg = /^\((.*?),([^ ]*)$/; const reg = /^\((.*?),([^ ]*)$/
if (reg.test(cursorLeftString)) { if (reg.test(cursorLeftString)) {
var execArr = reg.exec(cursorLeftString) || [] const execArr = reg.exec(cursorLeftString) || []
return { return {
leftTokenGroup, leftTokenGroup,
cursorLeftString, cursorLeftString,
label: execArr[1], label: execArr[1],
sign: 'unknown', //没必要判断 sign: 'unknown', // 没必要判断
value: execArr[2], value: execArr[2]
} }
} }
return null return null
} }
function matchIn(CodeMirror, hintParams = {}) { function matchIn (CodeMirror, hintParams = {}) {
//in 的情况比较特殊 // in 的情况比较特殊
//通用情况 expr not in (values) expr in (values) // 通用情况 expr not in (values) expr in (values)
var editor = hintParams.editor; const editor = hintParams.editor
var Pos = CodeMirror.Pos const Pos = CodeMirror.Pos
var cur = hintParams.cur; const cur = hintParams.cur
var token = hintParams.token; let token = hintParams.token
if (!editor) { if (!editor) {
return return
} }
let start = token.start
let cont = true
const leftTokenGroup = []
var start = token.start; // 找到左括号
var cont = true;
var leftTokenGroup = [];
//找到左括号
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(token.string.match(/^[ (]*$/) || start === 0); //括号或者空格为终止条件 cont = !(token.string.match(/^[ (]*$/) || start === 0) // 括号或者空格为终止条件
//左括号补上 // 左括号补上
if (token.string === '(') { if (token.string === '(') {
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
} }
} }
//左括号继续向右找 // 左括号继续向右找
cont = true cont = true
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(!token.string.match(/^(in|not| )/g) || start === 0); //括号或者空格为终止条件 cont = !(!token.string.match(/^(in|not| )/g) || start === 0) // 括号或者空格为终止条件
//string-2 // string-2
if (token.type === 'string-2') { if (token.type === 'string-2') {
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
} }
} }
var cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end)) const cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end))
//判断是不是满足 运算符 表达式的正则 // 判断是不是满足 运算符 表达式的正则
var reg = /^(.*?)[ ]+((?:not[ ]+)?in)[ ]*\(([^ ]*?)$/i; const reg = /^(.*?)[ ]+((?:not[ ]+)?in)[ ]*\(([^ ]*?)$/i
if (reg.test(cursorLeftString)) { if (reg.test(cursorLeftString)) {
var execArr = reg.exec(cursorLeftString) || [] const execArr = reg.exec(cursorLeftString) || []
return { return {
leftTokenGroup, leftTokenGroup,
cursorLeftString, cursorLeftString,
label: execArr[1], label: execArr[1],
sign: execArr[2], sign: execArr[2],
value: execArr[3], value: execArr[3]
} }
} }
return null return null
} }
function matchLike(CodeMirror, hintParams = {}) { function matchLike (CodeMirror, hintParams = {}) {
//like 的情况比较特殊 expr like value , expr not like value // like 的情况比较特殊 expr like value , expr not like value
var editor = hintParams.editor; const editor = hintParams.editor
var Pos = CodeMirror.Pos const Pos = CodeMirror.Pos
var cur = hintParams.cur; const cur = hintParams.cur
var token = hintParams.token; let token = hintParams.token
if (!editor) { if (!editor) {
return return
} }
let start = token.start
let cont = true
const leftTokenGroup = []
var start = token.start; // 找到左括号
var cont = true;
var leftTokenGroup = [];
//找到左括号
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(token.string.match(/^[ ]*$/) || start === 0); //括号或者空格为终止条件 cont = !(token.string.match(/^[ ]*$/) || start === 0) // 括号或者空格为终止条件
} }
//左括号继续向右找 // 左括号继续向右找
cont = true cont = true
while (cont) { while (cont) {
start = token.start; start = token.start
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
cont = !(!token.string.match(/^(like|not| )/g) || start === 0); //括号或者空格为终止条件 cont = !(!token.string.match(/^(like|not| )/g) || start === 0) // 括号或者空格为终止条件
//string-2 // string-2
if (token.type === 'string-2') { if (token.type === 'string-2') {
leftTokenGroup.unshift(token); leftTokenGroup.unshift(token)
} }
} }
var cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end)) const cursorLeftString = editor.getRange(Pos(cur.line, leftTokenGroup[0].start), Pos(cur.line, leftTokenGroup[leftTokenGroup.length - 1].end))
//判断是不是满足 运算符 表达式的正则 // 判断是不是满足 运算符 表达式的正则
var reg = /^(.*?)[ ]+((?:not[ ]+)?like)[ ]*([^ ]*?)$/i; const reg = /^(.*?)[ ]+((?:not[ ]+)?like)[ ]*([^ ]*?)$/i
if (reg.test(cursorLeftString)) { if (reg.test(cursorLeftString)) {
var execArr = reg.exec(cursorLeftString) || [] const execArr = reg.exec(cursorLeftString) || []
return { return {
leftTokenGroup, leftTokenGroup,
cursorLeftString, cursorLeftString,
label: execArr[1], label: execArr[1],
sign: execArr[2], sign: execArr[2],
value: execArr[3], value: execArr[3]
} }
} }
return null return null
} }
export const matchMain = (CodeMirror, params, manualParams = {}) => { export const matchMain = (CodeMirror, params, manualParams = {}) => {
var matchRes = null let matchRes = null
//匹配 运算符表达式 // 匹配 运算符表达式
matchRes = matchOperator(CodeMirror, manualParams) matchRes = matchOperator(CodeMirror, manualParams)
if (matchRes) { if (matchRes) {
return matchRes return matchRes
} }
//匹配 in表达式 // 匹配 in表达式
matchRes = matchIn(CodeMirror, manualParams) matchRes = matchIn(CodeMirror, manualParams)
if (matchRes) { if (matchRes) {
return matchRes return matchRes
} }
//匹配 like表达式 // 匹配 like表达式
matchRes = matchLike(CodeMirror, manualParams) matchRes = matchLike(CodeMirror, manualParams)
if (matchRes) { if (matchRes) {
return matchRes return matchRes
} }
//这里缺少一个对 count(distinct expr) 模式的匹配, 感觉大数据涉及存在缺陷, 先暂时不写 // 这里缺少一个对 count(distinct expr) 模式的匹配, 感觉大数据涉及存在缺陷, 先暂时不写
// 匹配 其他表达式 (expr,value1,value2....) 模式的匹配
//匹配 其他表达式 (expr,value1,value2....) 模式的匹配
matchRes = matchCommon(CodeMirror, manualParams) matchRes = matchCommon(CodeMirror, manualParams)
if (matchRes) { if (matchRes) {
// 说明这是一个 运算符表达式 // 说明这是一个 运算符表达式

View File

@@ -1,525 +1,521 @@
export default function showHint(CodeMirror) { export default function showHint (CodeMirror) {
"use strict"; 'use strict'
var HINT_ELEMENT_CLASS = "CodeMirror-hint"; const HINT_ELEMENT_CLASS = 'CodeMirror-hint'
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active"; const ACTIVE_HINT_ELEMENT_CLASS = 'CodeMirror-hint-active'
// This is the old interface, kept around for now to stay // This is the old interface, kept around for now to stay
// backwards-compatible. // backwards-compatible.
CodeMirror.showHint = function (cm, getHints, options) { CodeMirror.showHint = function (cm, getHints, options) {
if (!getHints) return cm.showHint(options); if (!getHints) return cm.showHint(options)
if (options && options.async) getHints.async = true; if (options && options.async) getHints.async = true
var newOpts = {hint: getHints}; const newOpts = { hint: getHints }
if (options) for (var prop in options) newOpts[prop] = options[prop]; if (options) for (const prop in options) newOpts[prop] = options[prop]
return cm.showHint(newOpts); return cm.showHint(newOpts)
}; }
CodeMirror.defineExtension("showHint", function (options) { CodeMirror.defineExtension('showHint', function (options) {
options = parseOptions(this, this.getCursor("start"), options); options = parseOptions(this, this.getCursor('start'), options)
var selections = this.listSelections() const selections = this.listSelections()
if (selections.length > 1) return; if (selections.length > 1) return
// By default, don't allow completion when something is selected. // By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to // A hint function can have a `supportsSelection` property to
// indicate that it can handle selections. // indicate that it can handle selections.
if (this.somethingSelected()) { if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return; if (!options.hint.supportsSelection) return
// Don't try with cross-line selections // Don't try with cross-line selections
for (var i = 0; i < selections.length; i++) for (let i = 0; i < selections.length; i++) { if (selections[i].head.line != selections[i].anchor.line) return }
if (selections[i].head.line != selections[i].anchor.line) return;
} }
if (this.state.completionActive) this.state.completionActive.close(); if (this.state.completionActive) this.state.completionActive.close()
var completion = this.state.completionActive = new Completion(this, options); const completion = this.state.completionActive = new Completion(this, options)
if (!completion.options.hint) return; if (!completion.options.hint) return
CodeMirror.signal(this, "startCompletion", this); CodeMirror.signal(this, 'startCompletion', this)
completion.update(true); completion.update(true)
}); })
CodeMirror.defineExtension("closeHint", function () { CodeMirror.defineExtension('closeHint', function () {
if (this.state.completionActive) this.state.completionActive.close() if (this.state.completionActive) this.state.completionActive.close()
}) })
function Completion(cm, options) { function Completion (cm, options) {
this.cm = cm; this.cm = cm
this.options = options; this.options = options
this.widget = null; this.widget = null
this.debounce = 0; this.debounce = 0
this.tick = 0; this.tick = 0
this.startPos = this.cm.getCursor("start"); this.startPos = this.cm.getCursor('start')
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length; this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length
if (this.options.updateOnCursorActivity) { if (this.options.updateOnCursorActivity) {
var self = this; const self = this
cm.on("cursorActivity", this.activityFunc = function () { cm.on('cursorActivity', this.activityFunc = function () {
self.cursorActivity(); self.cursorActivity()
}); })
} }
} }
var requestAnimationFrame = window.requestAnimationFrame || function (fn) { const requestAnimationFrame = window.requestAnimationFrame || function (fn) {
return setTimeout(fn, 1000 / 60); return setTimeout(fn, 1000 / 60)
}; }
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout; const cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout
Completion.prototype = { Completion.prototype = {
close: function () { close: function () {
if (!this.active()) return; if (!this.active()) return
this.cm.state.completionActive = null; this.cm.state.completionActive = null
this.tick = null; this.tick = null
if (this.options.updateOnCursorActivity) { 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.data) CodeMirror.signal(this.data, 'close')
if (this.widget) this.widget.close(); if (this.widget) this.widget.close()
CodeMirror.signal(this.cm, "endCompletion", this.cm); CodeMirror.signal(this.cm, 'endCompletion', this.cm)
}, },
active: function () { active: function () {
return this.cm.state.completionActive == this; return this.cm.state.completionActive == this
}, },
pick: function (data, i) { pick: function (data, i) {
var completion = data.list[i], self = this; const completion = data.list[i]; const self = this
this.cm.operation(function () { this.cm.operation(function () {
if (completion.hint) if (completion.hint) { completion.hint(self.cm, data, completion) } else {
completion.hint(self.cm, data, completion);
else
self.cm.replaceRange(getText(completion), completion.from || data.from, self.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete"); completion.to || data.to, 'complete')
CodeMirror.signal(data, "pick", completion); }
self.cm.scrollIntoView(); CodeMirror.signal(data, 'pick', completion)
}); self.cm.scrollIntoView()
})
if (this.options.closeOnPick) { if (this.options.closeOnPick) {
this.close(); this.close()
} }
}, },
cursorActivity: function () { cursorActivity: function () {
if (this.debounce) { if (this.debounce) {
cancelAnimationFrame(this.debounce); cancelAnimationFrame(this.debounce)
this.debounce = 0; this.debounce = 0
} }
var identStart = this.startPos; let identStart = this.startPos
if (this.data) { 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 || if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < identStart.ch || this.cm.somethingSelected() || pos.ch < identStart.ch || this.cm.somethingSelected() ||
(!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close(); this.close()
} else { } else {
var self = this; const self = this
this.debounce = requestAnimationFrame(function () { this.debounce = requestAnimationFrame(function () {
self.update(); self.update()
}); })
if (this.widget) this.widget.disable(); if (this.widget) this.widget.disable()
} }
}, },
update: function (first) { update: function (first) {
if (this.tick == null) return if (this.tick == null) return
var self = this, myTick = ++this.tick const self = this; const myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function (data) { fetchHints(this.options.hint, this.cm, this.options, function (data) {
if (self.tick == myTick) self.finishUpdate(data, first) if (self.tick == myTick) self.finishUpdate(data, first)
}) })
}, },
finishUpdate: function (data, first) { 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); const picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle)
if (this.widget) this.widget.close(); if (this.widget) this.widget.close()
this.data = data; this.data = data
if (data && data.list.length) { if (data && data.list.length) {
if (picked && data.list.length == 1) { if (picked && data.list.length == 1) {
this.pick(data, 0); this.pick(data, 0)
} else { } else {
this.widget = new Widget(this, data); this.widget = new Widget(this, data)
CodeMirror.signal(data, "shown"); CodeMirror.signal(data, 'shown')
} }
} }
} }
}; }
function parseOptions(cm, pos, options) { function parseOptions (cm, pos, options) {
var editor = cm.options.hintOptions; const editor = cm.options.hintOptions
var out = {}; const out = {}
for (var prop in defaultOptions) out[prop] = defaultOptions[prop]; for (var prop in defaultOptions) out[prop] = defaultOptions[prop]
if (editor) for (var prop in editor) if (editor) {
if (editor[prop] !== undefined) out[prop] = editor[prop]; 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 (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) if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out; return out
} }
function getText(completion) { function getText (completion) {
if (typeof completion == "string") return completion; if (typeof completion == 'string') return completion
else return completion.text; else return completion.text
} }
function buildKeyMap(completion, handle) { function buildKeyMap (completion, handle) {
var baseMap = { const baseMap = {
Up: function () { Up: function () {
handle.moveFocus(-1); handle.moveFocus(-1)
}, },
Down: function () { Down: function () {
handle.moveFocus(1); handle.moveFocus(1)
}, },
PageUp: function () { PageUp: function () {
handle.moveFocus(-handle.menuSize() + 1, true); handle.moveFocus(-handle.menuSize() + 1, true)
}, },
PageDown: function () { PageDown: function () {
handle.moveFocus(handle.menuSize() - 1, true); handle.moveFocus(handle.menuSize() - 1, true)
}, },
Home: function () { Home: function () {
handle.setFocus(0); handle.setFocus(0)
}, },
End: function () { End: function () {
handle.setFocus(handle.length - 1); handle.setFocus(handle.length - 1)
}, },
Enter: handle.pick, Enter: handle.pick,
Tab: handle.pick, Tab: handle.pick,
Esc: handle.close Esc: handle.close
}; }
var mac = /Mac/.test(navigator.platform); const mac = /Mac/.test(navigator.platform)
if (mac) { if (mac) {
baseMap["Ctrl-P"] = function () { baseMap['Ctrl-P'] = function () {
handle.moveFocus(-1); handle.moveFocus(-1)
}; }
baseMap["Ctrl-N"] = function () { baseMap['Ctrl-N'] = function () {
handle.moveFocus(1); handle.moveFocus(1)
}; }
} }
var custom = completion.options.customKeys; const custom = completion.options.customKeys
var ourMap = custom ? {} : baseMap; const ourMap = custom ? {} : baseMap
function addBinding(key, val) { function addBinding (key, val) {
var bound; let bound
if (typeof val != "string") if (typeof val != 'string') {
bound = function (cm) { bound = function (cm) {
return val(cm, handle); return val(cm, handle)
}; }
}
// This mechanism is deprecated // This mechanism is deprecated
else if (baseMap.hasOwnProperty(val)) else if (baseMap.hasOwnProperty(val)) { bound = baseMap[val] } else { bound = val }
bound = baseMap[val]; ourMap[key] = bound
else
bound = val;
ourMap[key] = bound;
} }
if (custom) if (custom) {
for (var key in custom) if (custom.hasOwnProperty(key)) for (var key in custom) {
addBinding(key, custom[key]); if (custom.hasOwnProperty(key)) { addBinding(key, custom[key]) }
var extra = completion.options.extraKeys; }
if (extra) }
for (var key in extra) if (extra.hasOwnProperty(key)) const extra = completion.options.extraKeys
addBinding(key, extra[key]); if (extra) {
return ourMap; 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) { while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el; if (el.nodeName.toUpperCase() === 'LI' && el.parentNode == hintsElement) return el
el = el.parentNode; el = el.parentNode
} }
} }
function Widget(completion, data) { function Widget (completion, data) {
this.id = "cm-complete-" + Math.floor(Math.random(1e6)) this.id = 'cm-complete-' + Math.floor(Math.random(1e6))
this.completion = completion; this.completion = completion
this.data = data; this.data = data
this.picked = false; this.picked = false
var widget = this, cm = completion.cm; const widget = this; const cm = completion.cm
var ownerDocument = cm.getInputField().ownerDocument; const ownerDocument = cm.getInputField().ownerDocument
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow; const parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow
var hints = this.hints = ownerDocument.createElement("ul"); const hints = this.hints = ownerDocument.createElement('ul')
// $(hints).append(` // $(hints).append(`
// <h1>lalallalla</h1> // <h1>lalallalla</h1>
// `) // `)
hints.setAttribute("role", "listbox") hints.setAttribute('role', 'listbox')
hints.setAttribute("aria-expanded", "true") hints.setAttribute('aria-expanded', 'true')
hints.id = this.id hints.id = this.id
var theme = completion.cm.options.theme; const theme = completion.cm.options.theme
hints.className = "CodeMirror-hints " + theme; hints.className = 'CodeMirror-hints ' + theme
this.selectedHint = data.selectedHint || 0; this.selectedHint = data.selectedHint || 0
var completions = data.list; const completions = data.list
for (var i = 0; i < completions.length; ++i) { for (let i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i]; const elt = hints.appendChild(ownerDocument.createElement('li')); const cur = completions[i]
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS); let className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? '' : ' ' + ACTIVE_HINT_ELEMENT_CLASS)
if (cur.className != null) className = cur.className + " " + className; if (cur.className != null) className = cur.className + ' ' + className
elt.className = className; elt.className = className
if (i == this.selectedHint) elt.setAttribute("aria-selected", "true") if (i == this.selectedHint) elt.setAttribute('aria-selected', 'true')
elt.id = this.id + "-" + i elt.id = this.id + '-' + i
elt.setAttribute("role", "option") elt.setAttribute('role', 'option')
if (cur.render) cur.render(elt, data, cur); if (cur.render) cur.render(elt, data, cur)
else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur))); else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)))
elt.hintId = i; elt.hintId = i
} }
var container = completion.options.container || ownerDocument.body; const container = completion.options.container || ownerDocument.body
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); let pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null)
var left = pos.left, top = pos.bottom, below = true; let left = pos.left; let top = pos.bottom; let below = true
var offsetLeft = 0, offsetTop = 0; let offsetLeft = 0; let offsetTop = 0
if (container !== ownerDocument.body) { if (container !== ownerDocument.body) {
// We offset the cursor position because left and top are relative to the offsetParent's top left corner. // 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; const isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1
var offsetParent = isContainerPositioned ? container : container.offsetParent; const offsetParent = isContainerPositioned ? container : container.offsetParent
var offsetParentPosition = offsetParent.getBoundingClientRect(); const offsetParentPosition = offsetParent.getBoundingClientRect()
var bodyPosition = ownerDocument.body.getBoundingClientRect(); const bodyPosition = ownerDocument.body.getBoundingClientRect()
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft); offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft)
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop); offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop)
} }
hints.style.left = (left - offsetLeft) + "px"; hints.style.left = (left - offsetLeft) + 'px'
hints.style.top = (top - offsetTop) + "px"; hints.style.top = (top - offsetTop) + 'px'
// todo 隐藏codemirror自带的提示 // todo 隐藏codemirror自带的提示
hints.style.display = 'none' 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. // 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); const winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth)
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight); const winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight)
//在这里 添加的DOM 元素 -- 该方案 实现复杂算了吧 // 在这里 添加的DOM 元素 -- 该方案 实现复杂算了吧
container.appendChild(hints); container.appendChild(hints)
// debugger // debugger
// $(container).append( // $(container).append(
// ` // `
// <div> // <div>
// <h1>hahah</h1> // <h1>hahah</h1>
// ${ hints } // ${ hints }
// </div> // </div>
// ` // `
// ) // )
cm.getInputField().setAttribute("aria-autocomplete", "list") cm.getInputField().setAttribute('aria-autocomplete', 'list')
cm.getInputField().setAttribute("aria-owns", this.id) cm.getInputField().setAttribute('aria-owns', this.id)
cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint) cm.getInputField().setAttribute('aria-activedescendant', this.id + '-' + this.selectedHint)
var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect(); let box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect()
var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false; const scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false
// Compute in the timeout to avoid reflow on init // Compute in the timeout to avoid reflow on init
var startScroll; let startScroll
setTimeout(function () { setTimeout(function () {
startScroll = cm.getScrollInfo(); startScroll = cm.getScrollInfo()
}); })
var overlapY = box.bottom - winH; const overlapY = box.bottom - winH
if (overlapY > 0) { if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); const height = box.bottom - box.top; const curTop = pos.top - (pos.bottom - box.top)
if (curTop - height > 0) { // Fits above cursor if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height - offsetTop) + "px"; hints.style.top = (top = pos.top - height - offsetTop) + 'px'
below = false; below = false
} else if (height > winH) { } else if (height > winH) {
hints.style.height = (winH - 5) + "px"; hints.style.height = (winH - 5) + 'px'
hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px"; hints.style.top = (top = pos.bottom - box.top - offsetTop) + 'px'
var cursor = cm.getCursor(); const cursor = cm.getCursor()
if (data.from.ch != cursor.ch) { if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor); pos = cm.cursorCoords(cursor)
hints.style.left = (left = pos.left - offsetLeft) + "px"; hints.style.left = (left = pos.left - offsetLeft) + 'px'
box = hints.getBoundingClientRect(); box = hints.getBoundingClientRect()
} }
} }
} }
var overlapX = box.right - winW; let overlapX = box.right - winW
if (scrolls) overlapX += cm.display.nativeBarWidth; if (scrolls) overlapX += cm.display.nativeBarWidth
if (overlapX > 0) { if (overlapX > 0) {
if (box.right - box.left > winW) { if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px"; hints.style.width = (winW - 5) + 'px'
overlapX -= (box.right - box.left) - winW; overlapX -= (box.right - box.left) - winW
} }
hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + "px"; hints.style.left = (left = Math.max(pos.left - overlapX - offsetLeft, 0)) + 'px'
}
if (scrolls) {
for (let node = hints.firstChild; node; node = node.nextSibling) { node.style.paddingRight = cm.display.nativeBarWidth + 'px' }
} }
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
// debugger // debugger
cm.addKeyMap(this.keyMap = buildKeyMap(completion, { cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function (n, avoidWrap) { moveFocus: function (n, avoidWrap) {
widget.changeActive(widget.selectedHint + n, avoidWrap); widget.changeActive(widget.selectedHint + n, avoidWrap)
}, },
setFocus: function (n) { setFocus: function (n) {
widget.changeActive(n); widget.changeActive(n)
}, },
menuSize: function () { menuSize: function () {
return widget.screenAmount(); return widget.screenAmount()
}, },
length: completions.length, length: completions.length,
close: function () { close: function () {
completion.close(); completion.close()
}, },
pick: function () { pick: function () {
widget.pick(); widget.pick()
}, },
data: data data: data
})); }))
if (completion.options.closeOnUnfocus) { if (completion.options.closeOnUnfocus) {
var closingOnBlur; let closingOnBlur
cm.on("blur", this.onBlur = function () { cm.on('blur', this.onBlur = function () {
closingOnBlur = setTimeout(function () { closingOnBlur = setTimeout(function () {
completion.close(); completion.close()
}, 100); }, 100)
}); })
cm.on("focus", this.onFocus = function () { cm.on('focus', this.onFocus = function () {
clearTimeout(closingOnBlur); clearTimeout(closingOnBlur)
}); })
} }
cm.on("scroll", this.onScroll = function () { cm.on('scroll', this.onScroll = function () {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); const curScroll = cm.getScrollInfo(); const editor = cm.getWrapperElement().getBoundingClientRect()
if (!startScroll) startScroll = cm.getScrollInfo(); if (!startScroll) startScroll = cm.getScrollInfo()
var newTop = top + startScroll.top - curScroll.top; const newTop = top + startScroll.top - curScroll.top
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop); let point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop)
if (!below) point += hints.offsetHeight; if (!below) point += hints.offsetHeight
if (point <= editor.top || point >= editor.bottom) return completion.close(); if (point <= editor.top || point >= editor.bottom) return completion.close()
hints.style.top = newTop + "px"; hints.style.top = newTop + 'px'
hints.style.left = (left + startScroll.left - curScroll.left) + "px"; hints.style.left = (left + startScroll.left - curScroll.left) + 'px'
}); })
CodeMirror.on(hints, "dblclick", function (e) { CodeMirror.on(hints, 'dblclick', function (e) {
var t = getHintElement(hints, e.target || e.srcElement); const t = getHintElement(hints, e.target || e.srcElement)
if (t && t.hintId != null) { if (t && t.hintId != null) {
widget.changeActive(t.hintId); widget.changeActive(t.hintId)
widget.pick(); widget.pick()
} }
}); })
CodeMirror.on(hints, "click", function (e) { CodeMirror.on(hints, 'click', function (e) {
var t = getHintElement(hints, e.target || e.srcElement); const t = getHintElement(hints, e.target || e.srcElement)
if (t && t.hintId != null) { if (t && t.hintId != null) {
widget.changeActive(t.hintId); widget.changeActive(t.hintId)
if (completion.options.completeOnSingleClick) widget.pick(); if (completion.options.completeOnSingleClick) widget.pick()
} }
}); })
CodeMirror.on(hints, "mousedown", function () { CodeMirror.on(hints, 'mousedown', function () {
setTimeout(function () { setTimeout(function () {
cm.focus(); cm.focus()
}, 20); }, 20)
}); })
// The first hint doesn't need to be scrolled to on init // The first hint doesn't need to be scrolled to on init
var selectedHintRange = this.getSelectedHintRange(); const selectedHintRange = this.getSelectedHintRange()
if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) { if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
this.scrollToActive(); this.scrollToActive()
} }
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); CodeMirror.signal(data, 'select', completions[this.selectedHint], hints.childNodes[this.selectedHint])
return true; return true
} }
Widget.prototype = { Widget.prototype = {
close: function () { close: function () {
if (this.completion.widget != this) return; if (this.completion.widget != this) return
this.completion.widget = null; this.completion.widget = null
if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints); if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints)
this.completion.cm.removeKeyMap(this.keyMap); this.completion.cm.removeKeyMap(this.keyMap)
var input = this.completion.cm.getInputField() const input = this.completion.cm.getInputField()
input.removeAttribute("aria-activedescendant") input.removeAttribute('aria-activedescendant')
input.removeAttribute("aria-owns") input.removeAttribute('aria-owns')
var cm = this.completion.cm; const cm = this.completion.cm
if (this.completion.options.closeOnUnfocus) { if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur); cm.off('blur', this.onBlur)
cm.off("focus", this.onFocus); cm.off('focus', this.onFocus)
} }
cm.off("scroll", this.onScroll); cm.off('scroll', this.onScroll)
}, },
disable: function () { disable: function () {
this.completion.cm.removeKeyMap(this.keyMap); this.completion.cm.removeKeyMap(this.keyMap)
var widget = this; const widget = this
this.keyMap = { this.keyMap = {
Enter: function () { Enter: function () {
widget.picked = true; widget.picked = true
} }
}; }
this.completion.cm.addKeyMap(this.keyMap); this.completion.cm.addKeyMap(this.keyMap)
}, },
pick: function () { pick: function () {
this.completion.pick(this.data, this.selectedHint); this.completion.pick(this.data, this.selectedHint)
}, },
changeActive: function (i, avoidWrap) { changeActive: function (i, avoidWrap) {
if (i >= this.data.list.length) 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 }
i = avoidWrap ? this.data.list.length - 1 : 0; if (this.selectedHint == i) return
else if (i < 0) let node = this.hints.childNodes[this.selectedHint]
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
if (node) { if (node) {
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); node.className = node.className.replace(' ' + ACTIVE_HINT_ELEMENT_CLASS, '')
node.removeAttribute("aria-selected") node.removeAttribute('aria-selected')
} }
node = this.hints.childNodes[this.selectedHint = i]; node = this.hints.childNodes[this.selectedHint = i]
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; node.className += ' ' + ACTIVE_HINT_ELEMENT_CLASS
node.setAttribute("aria-selected", "true") node.setAttribute('aria-selected', 'true')
this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id) this.completion.cm.getInputField().setAttribute('aria-activedescendant', node.id)
this.scrollToActive() 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 () { scrollToActive: function () {
var selectedHintRange = this.getSelectedHintRange(); const selectedHintRange = this.getSelectedHintRange()
var node1 = this.hints.childNodes[selectedHintRange.from]; const node1 = this.hints.childNodes[selectedHintRange.from]
var node2 = this.hints.childNodes[selectedHintRange.to]; const node2 = this.hints.childNodes[selectedHintRange.to]
var firstNode = this.hints.firstChild; const firstNode = this.hints.firstChild
if (node1.offsetTop < this.hints.scrollTop) 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 }
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 () { 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 () { getSelectedHintRange: function () {
var margin = this.completion.options.scrollMargin || 0; const margin = this.completion.options.scrollMargin || 0
return { return {
from: Math.max(0, this.selectedHint - margin), from: Math.max(0, this.selectedHint - margin),
to: Math.min(this.data.list.length - 1, 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 if (!cm.somethingSelected()) return helpers
var result = [] const result = []
for (var i = 0; i < helpers.length; i++) for (let i = 0; i < helpers.length; i++) { if (helpers[i].supportsSelection) result.push(helpers[i]) }
if (helpers[i].supportsSelection) result.push(helpers[i])
return result return result
} }
function fetchHints(hint, cm, options, callback) { function fetchHints (hint, cm, options, callback) {
if (hint.async) { if (hint.async) {
hint(cm, callback, options) hint(cm, callback, options)
} else { } else {
var result = hint(cm, options) const result = hint(cm, options)
if (result && result.then) result.then(callback) if (result && result.then) result.then(callback)
else callback(result) else callback(result)
} }
} }
function resolveAutoHints(cm, pos) { function resolveAutoHints (cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words const helpers = cm.getHelpers(pos, 'hint'); let words
if (helpers.length) { if (helpers.length) {
var resolved = function (cm, callback, options) { const resolved = function (cm, callback, options) {
var app = applicableHelpers(cm, helpers); const app = applicableHelpers(cm, helpers)
function run(i) { function run (i) {
if (i == app.length) return callback(null) if (i == app.length) return callback(null)
fetchHints(app[i], cm, options, function (result) { fetchHints(app[i], cm, options, function (result) {
if (result && result.list.length > 0) callback(result) if (result && result.list.length > 0) callback(result)
@@ -532,9 +528,9 @@ export default function showHint(CodeMirror) {
resolved.async = true resolved.async = true
resolved.supportsSelection = true resolved.supportsSelection = true
return resolved return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { } else if (words = cm.getHelper(cm.getCursor(), 'hintWords')) {
return function (cm) { return function (cm) {
return CodeMirror.hint.fromList(cm, {words: words}) return CodeMirror.hint.fromList(cm, { words: words })
} }
} else if (CodeMirror.hint.anyword) { } else if (CodeMirror.hint.anyword) {
return function (cm, options) { return function (cm, options) {
@@ -546,30 +542,29 @@ export default function showHint(CodeMirror) {
} }
} }
CodeMirror.registerHelper("hint", "auto", { CodeMirror.registerHelper('hint', 'auto', {
resolve: resolveAutoHints resolve: resolveAutoHints
}); })
CodeMirror.registerHelper("hint", "fromList", function (cm, options) { CodeMirror.registerHelper('hint', 'fromList', function (cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur) const cur = cm.getCursor(); const token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur let term; let from = CodeMirror.Pos(cur.line, token.start); const to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) { if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start) term = token.string.substr(0, cur.ch - token.start)
} else { } else {
term = "" term = ''
from = cur from = cur
} }
var found = []; const found = []
for (var i = 0; i < options.words.length; i++) { for (let i = 0; i < options.words.length; i++) {
var word = options.words[i]; const word = options.words[i]
if (word.slice(0, term.length) == term) if (word.slice(0, term.length) == term) { found.push(word) }
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; CodeMirror.commands.autocomplete = CodeMirror.showHint
var defaultOptions = { var defaultOptions = {
hint: CodeMirror.hint.auto, hint: CodeMirror.hint.auto,
@@ -584,8 +579,8 @@ export default function showHint(CodeMirror) {
customKeys: null, customKeys: null,
extraKeys: null, extraKeys: null,
paddingForScrollbar: true, paddingForScrollbar: true,
moveOnOverlap: true, moveOnOverlap: true
}; }
CodeMirror.defineOption("hintOptions", null); CodeMirror.defineOption('hintOptions', null)
} }

View File

@@ -1,343 +1,336 @@
import {cloneDeep} from 'lodash' import { cloneDeep } from 'lodash'
import {matchMain} from './matchRelatedInfo' import { matchMain } from './matchRelatedInfo'
export default function (CodeMirror, export default function (CodeMirror,
{ {
dataset, dataset,
hinthook, //生成提示的hook 拦截 hinthook, // 生成提示的hook 拦截
keywordshook //关键字hook 在关键字里面 keywordshook // 关键字hook 在关键字里面
} }
) { ) {
// "use strict"; // "use strict";
var tables; let tables
var defaultTable; let defaultTable
var keywords; let keywords
var identifierQuote; let identifierQuote
var CONS = { const CONS = {
QUERY_DIV: ";", QUERY_DIV: ';',
ALIAS_KEYWORD: "AS" ALIAS_KEYWORD: 'AS'
}; }
var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos; const Pos = CodeMirror.Pos; const cmpPos = CodeMirror.cmpPos
function isArray(val) { function isArray (val) {
return Object.prototype.toString.call(val) == "[object Array]" return Object.prototype.toString.call(val) == '[object Array]'
} }
function getKeywords(editor) { function getKeywords (editor) {
var mode = editor.doc.modeOption; let mode = editor.doc.modeOption
if (mode === "sql") mode = "text/x-sql"; if (mode === 'sql') mode = 'text/x-sql'
keywords = CodeMirror.resolveMode(mode).keywords; keywords = CodeMirror.resolveMode(mode).keywords
if (keywordshook) { if (keywordshook) {
keywords = keywordshook(keywords, CodeMirror.resolveMode(mode)) || keywords keywords = keywordshook(keywords, CodeMirror.resolveMode(mode)) || keywords
} }
return keywords return keywords
} }
function getIdentifierQuote(editor) { function getIdentifierQuote (editor) {
var mode = editor.doc.modeOption; let mode = editor.doc.modeOption
if (mode === "sql") mode = "text/x-sql"; if (mode === 'sql') mode = 'text/x-sql'
return CodeMirror.resolveMode(mode).identifierQuote || "`"; return CodeMirror.resolveMode(mode).identifierQuote || '`'
} }
function getText(item) { function getText (item) {
return typeof item == "string" ? item : item.text; return typeof item == 'string' ? item : item.text
} }
function wrapTable(name, value) { function wrapTable (name, value) {
if (isArray(value)) value = {columns: value} if (isArray(value)) value = { columns: value }
if (!value.text) value.text = name if (!value.text) value.text = name
return value return value
} }
function parseTables(input) { function parseTables (input) {
//table 名称变大写 统一变成对象格式 columns text // table 名称变大写 统一变成对象格式 columns text
var result = {} const result = {}
if (isArray(input)) { if (isArray(input)) {
for (var i = input.length - 1; i >= 0; i--) { for (let i = input.length - 1; i >= 0; i--) {
var item = input[i] const item = input[i]
result[getText(item).toUpperCase()] = wrapTable(getText(item), item) result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
} }
} else if (input) { } else if (input) {
for (var name in input) for (const name in input) { result[name.toUpperCase()] = wrapTable(name, input[name]) }
result[name.toUpperCase()] = wrapTable(name, input[name])
} }
return result return result
} }
function getTable(name) { function getTable (name) {
return tables[name.toUpperCase()] return tables[name.toUpperCase()]
} }
function shallowClone(object) { function shallowClone (object) {
var result = {}; const result = {}
for (var key in object) if (object.hasOwnProperty(key)) for (const key in object) {
result[key] = object[key]; if (object.hasOwnProperty(key)) { result[key] = object[key] }
return result; }
return result
} }
function match(string, word) { function match (string, word) {
var len = string.length; const len = string.length
var sub = getText(word).substr(0, len); const sub = getText(word).substr(0, len)
return string.toUpperCase() === sub.toUpperCase(); return string.toUpperCase() === sub.toUpperCase()
} }
function addMatches(result, search, wordlist, formatter) { function addMatches (result, search, wordlist, formatter) {
if (isArray(wordlist)) { if (isArray(wordlist)) {
for (var i = 0; i < wordlist.length; i++) for (let i = 0; i < wordlist.length; i++) { if (match(search, wordlist[i])) result.push(formatter(wordlist[i])) }
if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
} else { } else {
for (var word in wordlist) if (wordlist.hasOwnProperty(word)) { for (const word in wordlist) {
var val = wordlist[word] if (wordlist.hasOwnProperty(word)) {
if (!val || val === true) let val = wordlist[word]
val = word if (!val || val === true) { val = word } else { val = val.displayText ? { text: val.text, displayText: val.displayText } : val.text }
else if (match(search, val)) result.push(formatter(val))
val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text }
if (match(search, val)) result.push(formatter(val))
} }
} }
} }
function cleanName(name) { function cleanName (name) {
// Get rid name from identifierQuote and preceding dot(.) // Get rid name from identifierQuote and preceding dot(.)
if (name.charAt(0) == ".") { if (name.charAt(0) == '.') {
name = name.substr(1); name = name.substr(1)
} }
// replace duplicated identifierQuotes with single identifierQuotes // replace duplicated identifierQuotes with single identifierQuotes
// and remove single identifierQuotes // and remove single identifierQuotes
var nameParts = name.split(identifierQuote + identifierQuote); const nameParts = name.split(identifierQuote + identifierQuote)
for (var i = 0; i < nameParts.length; i++) for (let i = 0; i < nameParts.length; i++) { nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote, 'g'), '') }
nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote, "g"), ""); return nameParts.join(identifierQuote)
return nameParts.join(identifierQuote);
} }
function insertIdentifierQuotes(name) { function insertIdentifierQuotes (name) {
var nameParts = getText(name).split("."); const nameParts = getText(name).split('.')
for (var i = 0; i < nameParts.length; i++) for (let i = 0; i < nameParts.length; i++) {
nameParts[i] = identifierQuote + nameParts[i] = identifierQuote +
// duplicate identifierQuotes // duplicate identifierQuotes
nameParts[i].replace(new RegExp(identifierQuote, "g"), identifierQuote + identifierQuote) + nameParts[i].replace(new RegExp(identifierQuote, 'g'), identifierQuote + identifierQuote) +
identifierQuote; identifierQuote
var escaped = nameParts.join("."); }
if (typeof name == "string") return escaped; const escaped = nameParts.join('.')
name = shallowClone(name); if (typeof name == 'string') return escaped
name.text = escaped; name = shallowClone(name)
return name; name.text = escaped
return name
} }
function getLeftpart(cur, token, result, editor) { function getLeftpart (cur, token, result, editor) {
var nameParts = []; const nameParts = []
var start = token.start; let start = token.start
var cont = true; let cont = true
while (cont) { while (cont) {
//全是空格 或者 是操作符 就接着往前找 // 全是空格 或者 是操作符 就接着往前找
cont = ((token.type === 'operator' || token.string.match(/^[ ]*$/)) && start !== 0); cont = ((token.type === 'operator' || token.string.match(/^[ ]*$/)) && start !== 0)
start = token.start; start = token.start
nameParts.unshift(token.string); nameParts.unshift(token.string)
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
if (token.type === 'operator') { if (token.type === 'operator') {
cont = true; cont = true
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
} }
} }
return nameParts[0] return nameParts[0]
} }
function isRightpart(cur, token, result, editor) { function isRightpart (cur, token, result, editor) {
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
return token.type === 'operator' return token.type === 'operator'
} }
function nameCompletion(cur, token, result, editor) { function nameCompletion (cur, token, result, editor) {
// Try to complete table, column names and return start position of completion // Try to complete table, column names and return start position of completion
var useIdentifierQuotes = false; let useIdentifierQuotes = false
var nameParts = []; const nameParts = []
var start = token.start; let start = token.start
var cont = true; let cont = true
while (cont) { while (cont) {
cont = (token.string.charAt(0) == "."); cont = (token.string.charAt(0) == '.')
useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote); useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote)
start = token.start; start = token.start
nameParts.unshift(cleanName(token.string)); nameParts.unshift(cleanName(token.string))
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
if (token.string == ".") { if (token.string == '.') {
cont = true; cont = true
token = editor.getTokenAt(Pos(cur.line, token.start)); token = editor.getTokenAt(Pos(cur.line, token.start))
} }
} }
// Try to complete table names // Try to complete table names
var string = nameParts.join("."); let string = nameParts.join('.')
addMatches(result, string, tables, function (w) { addMatches(result, string, tables, function (w) {
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w
}); })
// Try to complete columns from defaultTable // Try to complete columns from defaultTable
addMatches(result, string, defaultTable, function (w) { addMatches(result, string, defaultTable, function (w) {
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w
}); })
// Try to complete columns // Try to complete columns
string = nameParts.pop(); string = nameParts.pop()
var table = nameParts.join("."); let table = nameParts.join('.')
var alias = false; let alias = false
var aliasTable = table; const aliasTable = table
// Check if table is available. If not, find table by Alias // Check if table is available. If not, find table by Alias
if (!getTable(table)) { if (!getTable(table)) {
var oldTable = table; const oldTable = table
table = findTableByAlias(table, editor); table = findTableByAlias(table, editor)
if (table !== oldTable) alias = true; if (table !== oldTable) alias = true
} }
var columns = getTable(table); let columns = getTable(table)
if (columns && columns.columns) if (columns && columns.columns) { columns = columns.columns }
columns = columns.columns;
if (columns) { if (columns) {
addMatches(result, string, columns, function (w) { addMatches(result, string, columns, function (w) {
var tableInsert = table; let tableInsert = table
if (alias == true) tableInsert = aliasTable; if (alias == true) tableInsert = aliasTable
if (typeof w == "string") { if (typeof w == 'string') {
w = tableInsert + "." + w; w = tableInsert + '.' + w
} else { } else {
w = shallowClone(w); w = shallowClone(w)
w.text = tableInsert + "." + w.text; w.text = tableInsert + '.' + w.text
} }
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w
}); })
} }
return start; return start
} }
function eachWord(lineText, f) { function eachWord (lineText, f) {
var words = lineText.split(/\s+/) const words = lineText.split(/\s+/)
for (var i = 0; i < words.length; i++) for (let i = 0; i < words.length; i++) { if (words[i]) f(words[i].replace(/[`,;]/g, '')) }
if (words[i]) f(words[i].replace(/[`,;]/g, ''))
} }
function findTableByAlias(alias, editor) { function findTableByAlias (alias, editor) {
var doc = editor.doc; const doc = editor.doc
var fullQuery = doc.getValue(); const fullQuery = doc.getValue()
var aliasUpperCase = alias.toUpperCase(); const aliasUpperCase = alias.toUpperCase()
var previousWord = ""; let previousWord = ''
var table = ""; let table = ''
var separator = []; const separator = []
var validRange = { let validRange = {
start: Pos(0, 0), start: Pos(0, 0),
end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length) end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
};
//add separator
var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
while (indexOfSeparator != -1) {
separator.push(doc.posFromIndex(indexOfSeparator));
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator + 1);
} }
separator.unshift(Pos(0, 0));
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
//find valid range // add separator
var prevItem = null; let indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV)
var current = editor.getCursor() while (indexOfSeparator != -1) {
separator.push(doc.posFromIndex(indexOfSeparator))
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator + 1)
}
separator.unshift(Pos(0, 0))
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length))
// find valid range
let prevItem = null
const current = editor.getCursor()
for (var i = 0; i < separator.length; i++) { for (var i = 0; i < separator.length; i++) {
if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) { if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
validRange = {start: prevItem, end: separator[i]}; validRange = { start: prevItem, end: separator[i] }
break; break
} }
prevItem = separator[i]; prevItem = separator[i]
} }
if (validRange.start) { if (validRange.start) {
var query = doc.getRange(validRange.start, validRange.end, false); const query = doc.getRange(validRange.start, validRange.end, false)
for (var i = 0; i < query.length; i++) { for (var i = 0; i < query.length; i++) {
var lineText = query[i]; const lineText = query[i]
eachWord(lineText, function (word) { eachWord(lineText, function (word) {
var wordUpperCase = word.toUpperCase(); const wordUpperCase = word.toUpperCase()
if (wordUpperCase === aliasUpperCase && getTable(previousWord)) if (wordUpperCase === aliasUpperCase && getTable(previousWord)) { table = previousWord }
table = previousWord; if (wordUpperCase !== CONS.ALIAS_KEYWORD) { previousWord = word }
if (wordUpperCase !== CONS.ALIAS_KEYWORD) })
previousWord = word; if (table) break
});
if (table) break;
} }
} }
return table; return table
} }
CodeMirror.registerHelper("hint", "sql", function (editor, options) { CodeMirror.registerHelper('hint', 'sql', function (editor, options) {
tables = parseTables(options && options.tables); tables = parseTables(options && options.tables)
var defaultTableName = options && options.defaultTable; //默认table 名称 const defaultTableName = options && options.defaultTable // 默认table 名称
var disableKeywords = options && options.disableKeywords; //禁用的keyword const disableKeywords = options && options.disableKeywords // 禁用的keyword
defaultTable = defaultTableName && getTable(defaultTableName); defaultTable = defaultTableName && getTable(defaultTableName)
keywords = getKeywords(editor); //获取 定义defineMIME 时候的关键字参数 keywords = getKeywords(editor) // 获取 定义defineMIME 时候的关键字参数
identifierQuote = getIdentifierQuote(editor); //获取 引用标识符 identifierQuote = getIdentifierQuote(editor) // 获取 引用标识符
if (defaultTableName && !defaultTable) if (defaultTableName && !defaultTable) { defaultTable = findTableByAlias(defaultTableName, editor) }
defaultTable = findTableByAlias(defaultTableName, editor);
defaultTable = defaultTable || []; defaultTable = defaultTable || []
if (defaultTable.columns) if (defaultTable.columns) { defaultTable = defaultTable.columns }
defaultTable = defaultTable.columns;
var cur = editor.getCursor(); //line 当前行 ch 索引 sticky ?? const cur = editor.getCursor() // line 当前行 ch 索引 sticky ??
var result = []; let result = []
var token = editor.getTokenAt(cur), start, end, search; const token = editor.getTokenAt(cur); let start; let end; let search
if (token.end > cur.ch) { if (token.end > cur.ch) {
token.end = cur.ch; token.end = cur.ch
token.string = token.string.slice(0, cur.ch - token.start); token.string = token.string.slice(0, cur.ch - token.start)
} }
//start end search 赋值 // start end search 赋值
// todo 此处允许字符串包含 . // todo 此处允许字符串包含 .
// if (token.string.match(/^[.`"'\w@][\w$#]*/g)) { // if (token.string.match(/^[.`"'\w@][\w$#]*/g)) {
if (token.string.match(/^[.`"'\w@][\w#]*/g)) { if (token.string.match(/^[.`"'\w@][\w#]*/g)) {
search = token.string; search = token.string
start = token.start; start = token.start
end = token.end; end = token.end
} else { } else {
start = end = cur.ch; start = end = cur.ch
search = ""; search = ''
} }
//对引用标识符 . 的使用,关联table 列 // 对引用标识符 . 的使用,关联table 列
if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) { if (search.charAt(0) == '.' || search.charAt(0) == identifierQuote) {
start = nameCompletion(cur, token, result, editor); start = nameCompletion(cur, token, result, editor)
} else { } else {
var objectOrClass = function (w, className) { const objectOrClass = function (w, className) {
if (typeof w === "object") { if (typeof w === 'object') {
w.className = className; w.className = className
} else { } else {
w = {text: w, className: className}; w = { text: w, className: className }
} }
return w; return w
}; }
addMatches(result, search, defaultTable, function (w) { addMatches(result, search, defaultTable, function (w) {
return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table"); return objectOrClass(w, 'CodeMirror-hint-table CodeMirror-hint-default-table')
}); })
addMatches( addMatches(
result, result,
search, search,
tables, function (w) { tables, function (w) {
return objectOrClass(w, "CodeMirror-hint-table"); return objectOrClass(w, 'CodeMirror-hint-table')
} }
); )
if (!disableKeywords) if (!disableKeywords) {
addMatches(result, search, keywords, function (w) { addMatches(result, search, keywords, function (w) {
return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword"); return objectOrClass(w.toUpperCase(), 'CodeMirror-hint-keyword')
}); })
}
} }
//写入一个 钩子,在这里决定提示的内容 // 写入一个 钩子,在这里决定提示的内容
if (hinthook) { if (hinthook) {
var params = { const params = {
search, //搜索 关键字 search, // 搜索 关键字
keywords, //关键字列表 keywords // 关键字列表
}; }
if (token.type === 'operator') { if (token.type === 'operator') {
params.leftpart = getLeftpart(cur, token, result, editor) || '' params.leftpart = getLeftpart(cur, token, result, editor) || ''
} }
@@ -347,8 +340,8 @@ export default function (CodeMirror,
/* 之后的参数 是为manualHinthook 预备的 */ /* 之后的参数 是为manualHinthook 预备的 */
var manualParams = { const manualParams = {
search, //搜索 关键字 search, // 搜索 关键字
// keywords, //关键字列表 没啥用 // keywords, //关键字列表 没啥用
from: Pos(cur.line, start), from: Pos(cur.line, start),
to: Pos(cur.line, end), to: Pos(cur.line, end),
@@ -360,13 +353,13 @@ export default function (CodeMirror,
cur cur
} }
var refField = matchMain(CodeMirror, params, manualParams); const refField = matchMain(CodeMirror, params, manualParams)
manualParams.refField = refField manualParams.refField = refField
manualParams.leftpart = refField?.label || manualParams.leftpart; manualParams.leftpart = refField?.label || manualParams.leftpart
params.leftpart = refField?.label || params.leftpart; params.leftpart = refField?.label || params.leftpart
result = hinthook(result, params, manualParams) || result result = hinthook(result, params, manualParams) || result
} }
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)}; return { list: result, from: Pos(cur.line, start), to: Pos(cur.line, end) }
}); })
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
var renderData = [ const renderData = [
{ {
name: 'COUNT', name: 'COUNT',
syntax: 'count(expr)', syntax: 'count(expr)',
@@ -34,7 +34,7 @@ var renderData = [
code: 'count(distinct client_ip)' code: 'count(distinct client_ip)'
}, },
{ {
purpose: `Counts the number of different "Server IP" and "Server port" :`, purpose: 'Counts the number of different "Server IP" and "Server port" :',
code: 'count(distinct server_ip, server_port)' code: 'count(distinct server_ip, server_port)'
} }
], ],
@@ -50,11 +50,11 @@ var renderData = [
description: 'Aggregate function is used to calculate the arithmetic mean in the specified field. EXPR must be Integer,Float or Decimal and returned value as Float.', description: 'Aggregate function is used to calculate the arithmetic mean in the specified field. EXPR must be Integer,Float or Decimal and returned value as Float.',
example: [ example: [
{ {
purpose: `Calculates the average(mean) "Byte sent (sent_bytes)" field:`, purpose: 'Calculates the average(mean) "Byte sent (sent_bytes)" field:',
code: 'avg(sent_bytes)' code: 'avg(sent_bytes)'
}, },
{ {
purpose: `Calculates the average(mean) "Bytes" , rounded to 2 decimal points:`, purpose: 'Calculates the average(mean) "Bytes" , rounded to 2 decimal points:',
code: 'round(avg(sent_bytes+received_bytes),2)' code: 'round(avg(sent_bytes+received_bytes),2)'
} }
], ],
@@ -70,11 +70,11 @@ var renderData = [
description: 'Aggregate function is used to sum of the values of the specified field. EXPR must be Integer,Float or Decimal.', description: 'Aggregate function is used to sum of the values of the specified field. EXPR must be Integer,Float or Decimal.',
example: [ example: [
{ {
purpose: `The sum of the "Byte sent (sent_bytes)" field:`, purpose: 'The sum of the "Byte sent (sent_bytes)" field:',
code: 'sum(sent_bytes)' code: 'sum(sent_bytes)'
}, },
{ {
purpose: `The sum of the "sent_bytes" and "received_bytes" fields , and rename as "Bytes ":`, purpose: 'The sum of the "sent_bytes" and "received_bytes" fields , and rename as "Bytes ":',
code: 'sum(sent_bytes+received_bytes) as Bytes' code: 'sum(sent_bytes+received_bytes) as Bytes'
} }
], ],
@@ -89,7 +89,7 @@ var renderData = [
description: 'Aggregate function is used to return the maximum value of the specified field.', description: 'Aggregate function is used to return the maximum value of the specified field.',
example: [ example: [
{ {
purpose: `Returns the maximum value of the "Byte sent (sent_bytes)" field:`, purpose: 'Returns the maximum value of the "Byte sent (sent_bytes)" field:',
code: 'max(sent_bytes)' code: 'max(sent_bytes)'
} }
], ],
@@ -105,7 +105,7 @@ var renderData = [
description: 'Aggregate function is used to return the minimum value of the specified field.', description: 'Aggregate function is used to return the minimum value of the specified field.',
example: [ example: [
{ {
purpose: `Returns the minimum value of the "Byte sent (sent_bytes)" field:`, purpose: 'Returns the minimum value of the "Byte sent (sent_bytes)" field:',
code: 'min(sent_bytes)' code: 'min(sent_bytes)'
} }
], ],
@@ -121,7 +121,7 @@ var renderData = [
description: 'Rounds down a timestamp, returning it as a new timestamp,optionally from some reference fill, and fills time gaps and impute missing values.', description: 'Rounds down a timestamp, returning it as a new timestamp,optionally from some reference fill, and fills time gaps and impute missing values.',
example: [ example: [
{ {
purpose: `Round the recv_time down to a 5 minutes increment and fill time gaps and impute zero value.`, purpose: 'Round the recv_time down to a 5 minutes increment and fill time gaps and impute zero value.',
code: 'TIME_FLOOR_WITH_FILL(recv_time,\'PT5M\',\'zero\')' code: 'TIME_FLOOR_WITH_FILL(recv_time,\'PT5M\',\'zero\')'
} }
], ],
@@ -148,21 +148,21 @@ var renderData = [
}, },
{ {
name: 'UNIX_TIMESTAMP', name: 'UNIX_TIMESTAMP',
syntax: `UNIX_TIMESTAMP(date)`, syntax: 'UNIX_TIMESTAMP(date)',
description: `Returns a Unix timestamp the value of the argument as seconds since '1970-01-01 00:00:00' UTC.`, description: 'Returns a Unix timestamp the value of the argument as seconds since \'1970-01-01 00:00:00\' UTC.',
example: [ example: [
{ {
purpose: `Specify a datetime string "2019-06-06 19:11:12", calculate the Unix timestamp:`, purpose: 'Specify a datetime string "2019-06-06 19:11:12", calculate the Unix timestamp:',
code: 'UNIX_TIMESTAMP(\'2019-06-06 19:11:12\')' code: 'UNIX_TIMESTAMP(\'2019-06-06 19:11:12\')'
}, },
{ {
purpose: `Specify a ISO8601 datetime string with time zone information "2019-10-12T14:20:50+08:00", calculate the Unix timestamp:`, purpose: 'Specify a ISO8601 datetime string with time zone information "2019-10-12T14:20:50+08:00", calculate the Unix timestamp:',
code: 'UNIX_TIMESTAMP(\'2019-10-12T14:20:50+08:00\')' code: 'UNIX_TIMESTAMP(\'2019-10-12T14:20:50+08:00\')'
}, },
{ {
purpose: `Specify a ISO8601 datetime string with UTC+0 time zone information "2019-10-12T14:20:50Z", calculate the Unix timestamp:`, purpose: 'Specify a ISO8601 datetime string with UTC+0 time zone information "2019-10-12T14:20:50Z", calculate the Unix timestamp:',
code: 'UNIX_TIMESTAMP(\'2019-10-12T14:20:50Z\')' code: 'UNIX_TIMESTAMP(\'2019-10-12T14:20:50Z\')'
}, }
], ],
details () { details () {
// 支持jsx 嵌套写法,万一测试要关键字加重呢 // 支持jsx 嵌套写法,万一测试要关键字加重呢
@@ -181,13 +181,13 @@ var renderData = [
}, },
{ {
name: 'FROM_UNIXTIME', name: 'FROM_UNIXTIME',
syntax: `FROM_UNIXTIME(unix_timestamp)`, syntax: 'FROM_UNIXTIME(unix_timestamp)',
description: `Returns a representation of unix_timestamp as a datetime or character string value. The value returned is expressed using the UTC+0 time zone.`, description: 'Returns a representation of unix_timestamp as a datetime or character string value. The value returned is expressed using the UTC+0 time zone.',
example: [ example: [
{ {
purpose: `Specify a Unix Timestamp "1570881546", calculate the datetime string:`, purpose: 'Specify a Unix Timestamp "1570881546", calculate the datetime string:',
code: 'FROM_UNIXTIME(1570881546)' code: 'FROM_UNIXTIME(1570881546)'
}, }
], ],
details () { details () {
// 支持jsx 嵌套写法,万一测试要关键字加重呢 // 支持jsx 嵌套写法,万一测试要关键字加重呢
@@ -198,10 +198,10 @@ var renderData = [
{ {
name: 'DATE_FORMAT', name: 'DATE_FORMAT',
syntax: 'DATE_FORMAT(date, format)', syntax: 'DATE_FORMAT(date, format)',
description: `Formats the date value according to the format string.`, description: 'Formats the date value according to the format string.',
example: [ example: [
{ {
purpose: `Specify a Unix Timestamp "1570881546", calculate the datetime string with format "%Y-%m-%d %H:%i:%s":`, purpose: 'Specify a Unix Timestamp "1570881546", calculate the datetime string with format "%Y-%m-%d %H:%i:%s":',
code: 'DATE_FORMAT(FROM_UNIXTIME(1570881546), \'%Y-%m-%d %H:%i:%s\')' code: 'DATE_FORMAT(FROM_UNIXTIME(1570881546), \'%Y-%m-%d %H:%i:%s\')'
} }
], ],
@@ -233,21 +233,21 @@ var renderData = [
}, },
{ {
name: 'CONVERT_TZ', name: 'CONVERT_TZ',
syntax: `CONVERT_TZ(dt, from_tz, to_tz)`, syntax: 'CONVERT_TZ(dt, from_tz, to_tz)',
description: `Converts a datetime value dt from the time zone given by from_tz to the time zone given by to_tz and returns the resulting value.`, description: 'Converts a datetime value dt from the time zone given by from_tz to the time zone given by to_tz and returns the resulting value.',
example: [ example: [
{ {
purpose: `Specify a datetime string "2021-11-11 00:00:00", converted from GMT(Greenwich Mean Time) to Asia/Shanghai time zone:`, purpose: 'Specify a datetime string "2021-11-11 00:00:00", converted from GMT(Greenwich Mean Time) to Asia/Shanghai time zone:',
code: 'CONVERT_TZ(\'2021-11-11 00:00:00\',\'GMT\',\'Asia/Shanghai\')' code: 'CONVERT_TZ(\'2021-11-11 00:00:00\',\'GMT\',\'Asia/Shanghai\')'
}, },
{ {
purpose: `Specify a Unix timestamp "1636588800", converted from GMT(Greenwich Mean Time) to Asia/Shanghai time zone:`, purpose: 'Specify a Unix timestamp "1636588800", converted from GMT(Greenwich Mean Time) to Asia/Shanghai time zone:',
code: 'CONVERT_TZ(FROM_UNIXTIME(1636588800),\'GMT\',\'Asia/Shanghai\')' code: 'CONVERT_TZ(FROM_UNIXTIME(1636588800),\'GMT\',\'Asia/Shanghai\')'
}, },
{ {
purpose: `Specify a Unix timestamp "1636588800", converted from Europe/London to America/New_York time zone:`, purpose: 'Specify a Unix timestamp "1636588800", converted from Europe/London to America/New_York time zone:',
code: 'CONVERT_TZ(DATE_FORMAT(FROM_UNIXTIME(1636588800), \'%Y-%m-%d %H:%i:%s\'),\'Europe/London\',\'America/New_York\')' code: 'CONVERT_TZ(DATE_FORMAT(FROM_UNIXTIME(1636588800), \'%Y-%m-%d %H:%i:%s\'),\'Europe/London\',\'America/New_York\')'
}, }
], ],
details () { details () {
// 支持jsx 嵌套写法,万一测试要关键字加重呢 // 支持jsx 嵌套写法,万一测试要关键字加重呢
@@ -263,11 +263,11 @@ var renderData = [
}, },
{ {
name: 'MEDIAN', name: 'MEDIAN',
syntax: `MEDIAN(<expr>)`, syntax: 'MEDIAN(<expr>)',
description: `Aggregate function is used to calculate median value. expr must be Integer, Float or Decimal.`, description: 'Aggregate function is used to calculate median value. expr must be Integer, Float or Decimal.',
example: [ example: [
{ {
purpose: `Calculates the median "TCP Handshake Latency (tcp_handshake_latency_ms)" field:`, purpose: 'Calculates the median "TCP Handshake Latency (tcp_handshake_latency_ms)" field:',
code: 'MEDIAN(tcp_handshake_latency_ms)' code: 'MEDIAN(tcp_handshake_latency_ms)'
} }
], ],
@@ -279,11 +279,11 @@ var renderData = [
}, },
{ {
name: 'QUANTILE', name: 'QUANTILE',
syntax: `QUANTILE(<expr>[, <level>])`, syntax: 'QUANTILE(<expr>[, <level>])',
description: `Aggregate function is used to calculate an approximate quantile of a numeric data sequence.`, description: 'Aggregate function is used to calculate an approximate quantile of a numeric data sequence.',
example: [ example: [
{ {
purpose: `Calculates the 90th percentile "TCP Handshake Latency (tcp_handshake_latency_ms)" field:`, purpose: 'Calculates the 90th percentile "TCP Handshake Latency (tcp_handshake_latency_ms)" field:',
code: 'QUANTILE(tcp_handshake_latency_ms, 0.9)' code: 'QUANTILE(tcp_handshake_latency_ms, 0.9)'
} }
], ],
@@ -300,13 +300,13 @@ var renderData = [
</ul> </ul>
</div> </div>
} }
}, }
] ]
function main () { function main () {
var functionTips = {} const functionTips = {}
renderData.forEach((item, index) => { renderData.forEach((item, index) => {
var data = item // 这是个闭包 const data = item // 这是个闭包
functionTips[item.name] = { functionTips[item.name] = {
name: item.name, name: item.name,
syntax: item.syntax, syntax: item.syntax,
@@ -327,8 +327,9 @@ function main () {
})} })}
</ul> </ul>
<h3> Details: </h3> <h3> Details: </h3>
{Object.prototype.toString.call(data.details) === '[object Function]' ? {Object.prototype.toString.call(data.details) === '[object Function]'
<renderer renderFun={data.details}></renderer> : <p>{data.details} </p>} ? <renderer renderFun={data.details}></renderer>
: <p>{data.details} </p>}
</div>) </div>)
} }
} }
@@ -337,5 +338,5 @@ function main () {
} }
export const functionList = renderData export const functionList = renderData
var functionTips = main() const functionTips = main()
export default functionTips export default functionTips

View File

@@ -1,37 +1,37 @@
var renderData = [ const renderData = [
{ {
name: 'FROM', name: 'FROM',
syntax: `FROM [db.]table |$log_type`, syntax: 'FROM [db.]table |$log_type',
description: { description: {
title: `The table name of logs. If you type $log_type, the variable value is the current table name of logs.` title: 'The table name of logs. If you type $log_type, the variable value is the current table name of logs.'
} }
}, },
{ {
name: 'SELECT', name: 'SELECT',
syntax: `Optional. The selected columns(also known as dimensions and metrics).`, syntax: 'Optional. The selected columns(also known as dimensions and metrics).',
description: { description: {
title: '可选,获取列', title: '可选,获取列',
list: [ list: [
`aggregate_function(field) - Aggregate functions, default is count.`, 'aggregate_function(field) - Aggregate functions, default is count.',
`as field - Use as to specify a aliases for a field or expression.` 'as field - Use as to specify a aliases for a field or expression.'
] ]
} }
}, },
{ {
name: 'GROUP BY', name: 'GROUP BY',
syntax: `GROUP BY <field-list>`, syntax: 'GROUP BY <field-list>',
description: { description: {
title: 'Aggregate data. GROUP BY clause switches the SELECT query into an aggregation mode', title: 'Aggregate data. GROUP BY clause switches the SELECT query into an aggregation mode',
list: [ list: [
`The list of fields known as "grouping key", while each individual expression be referred to as a "key expression".`, 'The list of fields known as "grouping key", while each individual expression be referred to as a "key expression".',
`All the expressions in the SELECT, HAVING and ORDER BY , must be "key expression" or on aggregate functions.`, 'All the expressions in the SELECT, HAVING and ORDER BY , must be "key expression" or on aggregate functions.',
`The result of aggregating SELECT query will return unique values of "grouping key" in log type.` 'The result of aggregating SELECT query will return unique values of "grouping key" in log type.'
] ]
} }
}, },
{ {
name: 'HAVING', name: 'HAVING',
syntax: `HAVING <expression-list>`, syntax: 'HAVING <expression-list>',
description: { description: {
title: `Optional. HAVING clause filtering the aggregation results retrieved by GROUP BY. It is difference is that WHERE is performed before aggregation, while HAVING is performed after it. title: `Optional. HAVING clause filtering the aggregation results retrieved by GROUP BY. It is difference is that WHERE is performed before aggregation, while HAVING is performed after it.
Note: HAVING can't be performed if GROUP BY is not performed.` Note: HAVING can't be performed if GROUP BY is not performed.`
@@ -39,26 +39,26 @@ var renderData = [
}, },
{ {
name: 'LIMIT', name: 'LIMIT',
syntax: `LIMIT [n, ]m`, syntax: 'LIMIT [n, ]m',
description: { description: {
title: `Select the m rows from the aggregate results after skipping the first n rows. Default is 10 rows.` title: 'Select the m rows from the aggregate results after skipping the first n rows. Default is 10 rows.'
} }
}, },
{ {
name: 'ORDER BY', name: 'ORDER BY',
syntax: `ORDER BY <sort-field> [ASC|DESC]`, syntax: 'ORDER BY <sort-field> [ASC|DESC]',
description: { description: {
title: `Sort all of the results by the specified fields.` title: 'Sort all of the results by the specified fields.'
} }
}, },
{ {
name: 'WHERE', name: 'WHERE',
syntax: `where $filter [and <expression-list>]`, syntax: 'where $filter [and <expression-list>]',
description: { description: {
title: `Filter the data.`, title: 'Filter the data.',
list: [ list: [
`$filter - Default global filter clause. Include Time period, Vsys ID, and other expressions, etc`, '$filter - Default global filter clause. Include Time period, Vsys ID, and other expressions, etc',
`and <expression-list> - filter clauses` 'and <expression-list> - filter clauses'
] ]
} }
} }
@@ -66,9 +66,9 @@ var renderData = [
export const sqlList = renderData export const sqlList = renderData
function main () { function main () {
var sqlTips = {} const sqlTips = {}
renderData.forEach((item, index) => { renderData.forEach((item, index) => {
var data = item // 这是个闭包 const data = item // 这是个闭包
sqlTips[item.name] = { sqlTips[item.name] = {
name: item.name, name: item.name,
syntax: item.syntax, syntax: item.syntax,
@@ -93,5 +93,5 @@ function main () {
return sqlTips return sqlTips
} }
var sqlTips = main() const sqlTips = main()
export default sqlTips export default sqlTips

View File

@@ -1,4 +1,4 @@
var renderData = [ const renderData = [
{ {
name: '$LOG_TYPE', name: '$LOG_TYPE',
description: 'A variable is a symbolic representation of data that enables you to access a value without having to enter it manually wherever you need it. You can use $ to reference variables throughout Advanced Search. ', description: 'A variable is a symbolic representation of data that enables you to access a value without having to enter it manually wherever you need it. You can use $ to reference variables throughout Advanced Search. ',
@@ -34,8 +34,9 @@ function main () {
<h3> Description: </h3> <h3> Description: </h3>
<p> {data.description}</p> <p> {data.description}</p>
<h3> Details: </h3> <h3> Details: </h3>
{Object.prototype.toString.call(data.details) === '[object Function]' ? {Object.prototype.toString.call(data.details) === '[object Function]'
<renderer renderFun={data.details}></renderer> : <p>{data.details} </p>} ? <renderer renderFun={data.details}></renderer>
: <p>{data.details} </p>}
</div>) </div>)
} }
} }

View File

@@ -1,22 +1,22 @@
import {dataTemplate, fieldTemplate} from './template' import { dataTemplate, fieldTemplate } from './template'
export class DeviceTag { export class DeviceTag {
constructor(context, params) { constructor (context, params) {
//先从缓存获取数据 // 先从缓存获取数据
this.queryparams = params this.queryparams = params
this.context = context this.context = context
} }
filterQueryData(list) { filterQueryData (list) {
return list return list
} }
getDataFromRemote() { getDataFromRemote () {
//从 远程,也就是请求接口获取数据 // 从 远程,也就是请求接口获取数据
return this.context.$get('/deviceTag', this.queryparams).then((res) => { return this.context.$get('/deviceTag', this.queryparams).then((res) => {
this.context.initDataReadyCb && this.context.initDataReadyCb(res.data || null); //组件 请求 文件成功回调 this.context.initDataReadyCb && this.context.initDataReadyCb(res.data || null) // 组件 请求 文件成功回调
if (res.code === 200) { if (res.code === 200) {
var data = res.data && res.data.list; const data = res.data && res.data.list
return data return data
} else { } else {
// this.context.$message({ // this.context.$message({
@@ -31,40 +31,40 @@ export class DeviceTag {
}) })
} }
formatData(data) { formatData (data) {
//格式化 获取的数据 // 格式化 获取的数据
const resultData = { const resultData = {
operatesList: [ operatesList: [
{ {
"name": "AND", name: 'AND',
"function": "A AND B", function: 'A AND B',
type: "abstract", type: 'abstract',
label: "AND" label: 'AND'
} }
], ],
filtersList: data ? this.filterQueryData(data.fields || []) : [], filtersList: data ? this.filterQueryData(data.fields || []) : [],
//操作符仓库 用于记录 类型 和 操作符之间的映射关系 // 操作符仓库 用于记录 类型 和 操作符之间的映射关系
operatesDic: data ? data.doc.schema_query.references.operator || [] : [], operatesDic: data ? data.doc.schema_query.references.operator || [] : [],
//operator 记录运算符的label 和 value 映射 以及操作符的使用方法 // operator 记录运算符的label 和 value 映射 以及操作符的使用方法
operatorManual: data ? data.doc.functions.operator || [] : [] operatorManual: data ? data.doc.functions.operator || [] : []
} }
return resultData return resultData
} }
organizeData(data=[]) { organizeData (data = []) {
var fields = [] const fields = []
var res = JSON.parse(JSON.stringify(dataTemplate)); const res = JSON.parse(JSON.stringify(dataTemplate))
if (!data ) { if (!data) {
return return
} }
data.forEach((item, index) => { data.forEach((item, index) => {
var fieldItem = JSON.parse(JSON.stringify(fieldTemplate)); const fieldItem = JSON.parse(JSON.stringify(fieldTemplate))
fieldItem.name = item.tagValue fieldItem.name = item.tagValue
fieldItem.type = "Array" fieldItem.type = 'Array'
fieldItem.label = item.tagName fieldItem.label = item.tagName
fieldItem.doc.data = (item.subTags || []).map(tagItem => { fieldItem.doc.data = (item.subTags || []).map(tagItem => {
return { return {
code: `'${tagItem.tagValue}'`, //匹配SQL 的时候,这个Code 要加 '' code: `'${tagItem.tagValue}'`, // 匹配SQL 的时候,这个Code 要加 ''
value: tagItem.tagName, value: tagItem.tagName,
type: tagItem.tagType type: tagItem.tagType
} }
@@ -75,20 +75,20 @@ export class DeviceTag {
return res return res
} }
getFormatedData(callback) { getFormatedData (callback) {
this.getDataFromRemote().then(data => { this.getDataFromRemote().then(data => {
//组织数据 模拟scama // 组织数据 模拟scama
var organizedData = this.organizeData(data); const organizedData = this.organizeData(data)
//格式化数据 // 格式化数据
this.data = this.formatData(organizedData) this.data = this.formatData(organizedData)
//获取scameData的时候 查询映射字段 // 获取scameData的时候 查询映射字段
callback && callback(this.data) callback && callback(this.data)
}) })
} }
dispose(){ dispose () {
this.context=null this.context = null
this.queryparams=null this.queryparams = null
this.data=null this.data = null
} }
} }

View File

@@ -1,156 +1,156 @@
export const dataTemplate = { export const dataTemplate = {
"doc": { doc: {
"functions": { functions: {
"aggregation": [ aggregation: [
{ {
"name": "COUNT", name: 'COUNT',
"function": "count(expr)", function: 'count(expr)',
"label": "COUNT" label: 'COUNT'
}, { }, {
"name": "COUNT_DISTINCT", name: 'COUNT_DISTINCT',
"function": "count(distinct expr)", function: 'count(distinct expr)',
"label": "COUNT_DISTINCT" label: 'COUNT_DISTINCT'
}, { }, {
"name": "AVG", name: 'AVG',
"function": "avg(expr)", function: 'avg(expr)',
"label": "AVG" label: 'AVG'
}, { }, {
"name": "SUM", name: 'SUM',
"function": "sum(expr)", function: 'sum(expr)',
"label": "SUM" label: 'SUM'
}, { }, {
"name": "MAX", name: 'MAX',
"function": "max(expr)", function: 'max(expr)',
"label": "MAX" label: 'MAX'
}, { }, {
"name": "MIN", name: 'MIN',
"function": "min(expr)", function: 'min(expr)',
"label": "MIN" label: 'MIN'
}], }],
"operator": [ operator: [
{ {
"name": "=", name: '=',
"function": "expr = value", function: 'expr = value',
"label": "=" label: '='
}, { }, {
"name": "!=", name: '!=',
"function": "expr != value", function: 'expr != value',
"label": "!=" label: '!='
}, { }, {
"name": ">", name: '>',
"function": "expr > value", function: 'expr > value',
"label": ">" label: '>'
}, { }, {
"name": "<", name: '<',
"function": "expr < value", function: 'expr < value',
"label": "<" label: '<'
}, { }, {
"name": ">=", name: '>=',
"function": "expr >= value", function: 'expr >= value',
"label": ">=" label: '>='
}, { }, {
"name": "<=", name: '<=',
"function": "expr <= value", function: 'expr <= value',
"label": "<=" label: '<='
}, { }, {
"name": "has", name: 'has',
"function": "has(expr, value)", function: 'has(expr, value)',
"label": "HAS" label: 'HAS'
}, { }, {
"name": "in", name: 'in',
"function": "expr in (values)", function: 'expr in (values)',
"label": "IN" label: 'IN'
}, { }, {
"name": "not in", name: 'not in',
"function": "expr not in (values)", function: 'expr not in (values)',
"label": "NOT IN" label: 'NOT IN'
}, { }, {
"name": "like", name: 'like',
"function": "expr like value", function: 'expr like value',
"label": "LIKE" label: 'LIKE'
}, { }, {
"name": "not like", name: 'not like',
"function": "expr not like value", function: 'expr not like value',
"label": "NOT LIKE" label: 'NOT LIKE'
}, { }, {
"name": "notEmpty", name: 'notEmpty',
"function": "notEmpty(expr)", function: 'notEmpty(expr)',
"label": "NOT EMPTY" label: 'NOT EMPTY'
}, { }, {
"name": "empty", name: 'empty',
"function": "empty(expr)", function: 'empty(expr)',
"label": "EMPTY" label: 'EMPTY'
}] }]
}, },
"schema_query": { schema_query: {
"references": { references: {
"aggregation": [ aggregation: [
{ {
"type": "int", type: 'int',
"functions": "COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN'
}, { }, {
"type": "long", type: 'long',
"functions": "COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN'
}, { }, {
"type": "float", type: 'float',
"functions": "COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN'
}, { }, {
"type": "double", type: 'double',
"functions": "COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,AVG,SUM,MAX,MIN'
}, { }, {
"type": "string", type: 'string',
"functions": "COUNT,COUNT_DISTINCT" functions: 'COUNT,COUNT_DISTINCT'
}, { }, {
"type": "date", type: 'date',
"functions": "COUNT,COUNT_DISTINCT,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,MAX,MIN'
}, { }, {
"type": "timestamp", type: 'timestamp',
"functions": "COUNT,COUNT_DISTINCT,MAX,MIN" functions: 'COUNT,COUNT_DISTINCT,MAX,MIN'
} }
], ],
"operator": [ operator: [
{ {
"type": "int", type: 'int',
"functions": "=,!=,>,<,>=,<=,in,not in" functions: '=,!=,>,<,>=,<=,in,not in'
}, { }, {
"type": "long", type: 'long',
"functions": "=,!=,>,<,>=,<=,in,not in" functions: '=,!=,>,<,>=,<=,in,not in'
}, { }, {
"type": "float", type: 'float',
"functions": "=,!=,>,<,>=,<=" functions: '=,!=,>,<,>=,<='
}, { }, {
"type": "double", type: 'double',
"functions": "=,!=,>,<,>=,<=" functions: '=,!=,>,<,>=,<='
}, { }, {
"type": "string", type: 'string',
"functions": "=,!=,in,not in,like,not like,notEmpty,empty" functions: '=,!=,in,not in,like,not like,notEmpty,empty'
}, { }, {
"type": "date", type: 'date',
"functions": "=,!=,>,<,>=,<=" functions: '=,!=,>,<,>=,<='
}, { }, {
"type": "timestamp", type: 'timestamp',
"functions": "=,!=,>,<,>=,<=" functions: '=,!=,>,<,>=,<='
}, { }, {
"type": "array", type: 'array',
"functions": "has" functions: 'has'
}] }]
} }
} }
}, },
"fields": [] fields: []
} }
export const fieldTemplate = { export const fieldTemplate = {
"name": "", name: '',
"label": "", label: '',
"doc": { doc: {
"allow_query": "true", allow_query: 'true',
"visibility": null, visibility: null,
"constraints": { constraints: {
"type": "tag", type: 'tag',
"operator_functions": "in,not in" operator_functions: 'in,not in'
}, },
"data": [] data: []
}, },
"type": "Array" type: 'Array'
} }

View File

@@ -250,7 +250,7 @@ import {
import { getNowTime, getSecond } from '@/utils/date-util' import { getNowTime, getSecond } from '@/utils/date-util'
import _ from 'lodash' import _ from 'lodash'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useDark, useToggle } from '@vueuse/core' import { useToggle } from '@vueuse/core'
export default { export default {
name: 'Header', name: 'Header',
@@ -336,8 +336,7 @@ export default {
wholeScreenRouterMapping, wholeScreenRouterMapping,
logo: 'images/logo-header.svg', logo: 'images/logo-header.svg',
ZH, ZH,
EN, EN
// isDark: useDark()
} }
}, },
computed: { computed: {

View File

@@ -59,7 +59,7 @@
<script> <script>
import indexedDBUtils from '@/indexedDB' import indexedDBUtils from '@/indexedDB'
import { storageKey, dbTableColumnCustomizeConfigPre,dbTableColumnCustomizeConfig } from '@/utils/constants' import { storageKey, dbTableColumnCustomizeConfigPre, dbTableColumnCustomizeConfig } from '@/utils/constants'
export default { export default {
props: { props: {
customTableTitle: Array, // 自定义的title customTableTitle: Array, // 自定义的title
@@ -153,7 +153,7 @@ export default {
this.$emit('update', this.custom) this.$emit('update', this.custom)
const userId = localStorage.getItem(storageKey.userId) const userId = localStorage.getItem(storageKey.userId)
const tableName = dbTableColumnCustomizeConfigPre + '-' + this.tableId const tableName = dbTableColumnCustomizeConfigPre + '-' + this.tableId
/* /*
const defaultConfigInDb = await indexedDBUtils.selectTable(tableName).get({ id: userId }) const defaultConfigInDb = await indexedDBUtils.selectTable(tableName).get({ id: userId })
let fullVersion = '' let fullVersion = ''
if (defaultConfigInDb && defaultConfigInDb.version) { if (defaultConfigInDb && defaultConfigInDb.version) {
@@ -168,8 +168,8 @@ export default {
fullVersion = BASE_CONFIG.version + '.1' fullVersion = BASE_CONFIG.version + '.1'
} }
*/ */
let curTableConfig = dbTableColumnCustomizeConfig.find(item => item.tableName === tableName) const curTableConfig = dbTableColumnCustomizeConfig.find(item => item.tableName === tableName)
if(curTableConfig) { if (curTableConfig) {
await indexedDBUtils.selectTable(tableName).put({ await indexedDBUtils.selectTable(tableName).put({
id: userId, id: userId,
version: curTableConfig.version, version: curTableConfig.version,

View File

@@ -464,222 +464,222 @@ export default {
axios.get(url, { params: params }).then(response => { axios.get(url, { params: params }).then(response => {
const res = response.data const res = response.data
if (response.status === 200) { if (response.status === 200) {
this.isNoDataForPsiphon3 = res.data.result.length === 0 this.isNoDataForPsiphon3 = res.data.result.length === 0
this.showErrorForPsiphon3 = false this.showErrorForPsiphon3 = false
if (!this.isNoDataForPsiphon3) { if (!this.isNoDataForPsiphon3) {
const chartsData = res.data.result.map(item => { const chartsData = res.data.result.map(item => {
return [getMillisecond(item.statTime), item.count] return [getMillisecond(item.statTime), item.count]
}) })
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.echartsInit(chartsData) this.echartsInit(chartsData)
}
}
} else {
this.httpError(res)
}
}).catch(e => {
console.error(e)
this.httpError(e)
}).finally(() => {
this.psiphon3Loading = false
})
},
httpError (e) {
this.isNoDataForPsiphon3 = false
this.showErrorForPsiphon3 = true
this.errorMsgForPsiphon3 = this.errorMsgHandler(e)
},
handleActiveBar () {
if (document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')) {
const {
offsetLeft,
clientWidth,
clientLeft
} = document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')
const activeBar = document.querySelector('.psiphon3-bar .bar-value-active')
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
}
},
resize () {
if (this.myChart) {
this.myChart.resize()
}
},
dispatchSelectAction (type, name) {
this.myChart && this.myChart.dispatchAction({
type: type,
name: name
})
},
legendSelectChange (item) {
this.dispatchSelectAction('legendSelect', item.name)
this.tabs.forEach((t) => {
if (t.name !== item.name) {
this.dispatchSelectAction('legendUnSelect', t.name)
}
})
},
timeChange () {
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
activeChange (item) { // isClick:代表是通过点击操作来的
if (item) {
this.tabType = item.class
}
this.legendSelectChange(item)
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
},
mouseenterTab (item) {
if (this.isNoDataForPsiphon3) return
this.mousemoveCursor = item.class
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
mouseleaveTab () {
this.mousemoveCursor = ''
},
fileChange (file, fileList) {
// 判断后缀,仅支持.csv
if (!_.endsWith(file.name, '.csv')) {
this.fileList = []
this.$message.error(this.$t('validate.fileTypeLimit', { types: this.fileTypeLimit }))
} else if (file.size > this.uploadFileSizeLimit) { // 判断文件大小
this.$message.error(this.$t('validate.fileSizeLimit', { size: unitConvert(this.uploadFileSizeLimit, unitTypes.byte).join('') }))
this.fileList = []
} else {
this.fileList = fileList.slice(-1)
}
},
uploadError (error) {
let errorMsg
if (error.message) {
errorMsg = JSON.parse(error.message).message
} else {
errorMsg = 'error'
}
this.uploadLoading = false
this.$message.error(this.$t('tip.uploadFailed', { msg: errorMsg }))
},
uploadSuccess (response) {
this.uploadLoading = false
this.uploaded = true
this.$message.success(this.$t('tip.success'))
this.showAddUpdateDialog = false
this.getCurTabData()
},
beforeUpload (file) {
this.uploadLoading = true
this.showConfirmDialog = false
},
submitConfirm () {
this.showConfirmDialog = true
},
submit () {
this.$refs.knowledgeUpload.submit()
},
cancle () {
this.showAddUpdateDialog = false
},
clickCard (data, event) {
if (data.isSelected) { // 原来为选中,当前点击后未选中
const index = this.checkList.indexOf(data)
if (index > -1) {
this.checkList.splice(index, 1)
}
} else {
const index = this.checkList.indexOf(data)
if (index === -1) {
this.checkList.push(data)
}
}
const val = !data.isSelected
data.isSelected = val
this.$emit('checkboxStatusChange', val, data)
},
checkboxStatusChange (val, data) {
data.isSelected = val
this.$emit('checkboxStatusChange', val, data)
},
beforeClose (done) {
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
done()
},
handleClose () {
this.showUpdateDialog = false
this.showAddUpdateDialog = false
this.uploadLoading = false
},
handleConfirmClose () {
this.showConfirmDialog = false
},
handleUpdateClose () {
this.showAddUpdateDialog = false
},
showUpdate () {
this.showUpdateDialog = true
this.showAddUpdateDialog = false
},
async jumpToUpdatePage (data, showEnable) {
this.updateKnowledge = data
this.showEnable = showEnable
await this.getCurTabData()
if (data.source === 'cn_psiphon3_ip') {
await this.init()
}
this.showUpdate()
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
uploadRecord () {
this.showAddUpdateDialog = true
this.updateObject.name = this.updateKnowledge.name
this.updateObject.label = this.$t(this.updateKnowledge.label)
this.updateObject.description = ''
},
getCurTabData () { // showEnable:true 为psiphon3的知识库false为其它知识库
let params = {
pageSize: -1
}
if (this.showEnable) {
if (this.activeTab === knowledgeCardUpdateRecordType.updateRecord) {
params = {
...params,
opUser: -1
}
} else if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
params = {
...params,
opUser: 0
} }
} }
} else {
this.httpError(res)
} }
this.updateLogLoading = true }).catch(e => {
this.updateHistoryList = [] console.error(e)
axios.get(api.knowledgeBaseLog + '/' + this.updateKnowledge.knowledgeId, { params: params }).then(res => { this.httpError(e)
this.updateHistoryList = res.data.data.list }).finally(() => {
if (this.updateHistoryList[0]) { this.psiphon3Loading = false
this.currentVersion = this.updateHistoryList[0].commitVersion + 1 })
},
httpError (e) {
this.isNoDataForPsiphon3 = false
this.showErrorForPsiphon3 = true
this.errorMsgForPsiphon3 = this.errorMsgHandler(e)
},
handleActiveBar () {
if (document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')) {
const {
offsetLeft,
clientWidth,
clientLeft
} = document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')
const activeBar = document.querySelector('.psiphon3-bar .bar-value-active')
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
}
},
resize () {
if (this.myChart) {
this.myChart.resize()
}
},
dispatchSelectAction (type, name) {
this.myChart && this.myChart.dispatchAction({
type: type,
name: name
})
},
legendSelectChange (item) {
this.dispatchSelectAction('legendSelect', item.name)
this.tabs.forEach((t) => {
if (t.name !== item.name) {
this.dispatchSelectAction('legendUnSelect', t.name)
}
})
},
timeChange () {
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
activeChange (item) { // isClick:代表是通过点击操作来的
if (item) {
this.tabType = item.class
}
this.legendSelectChange(item)
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
},
mouseenterTab (item) {
if (this.isNoDataForPsiphon3) return
this.mousemoveCursor = item.class
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
mouseleaveTab () {
this.mousemoveCursor = ''
},
fileChange (file, fileList) {
// 判断后缀,仅支持.csv
if (!_.endsWith(file.name, '.csv')) {
this.fileList = []
this.$message.error(this.$t('validate.fileTypeLimit', { types: this.fileTypeLimit }))
} else if (file.size > this.uploadFileSizeLimit) { // 判断文件大小
this.$message.error(this.$t('validate.fileSizeLimit', { size: unitConvert(this.uploadFileSizeLimit, unitTypes.byte).join('') }))
this.fileList = []
} else {
this.fileList = fileList.slice(-1)
}
},
uploadError (error) {
let errorMsg
if (error.message) {
errorMsg = JSON.parse(error.message).message
} else {
errorMsg = 'error'
}
this.uploadLoading = false
this.$message.error(this.$t('tip.uploadFailed', { msg: errorMsg }))
},
uploadSuccess (response) {
this.uploadLoading = false
this.uploaded = true
this.$message.success(this.$t('tip.success'))
this.showAddUpdateDialog = false
this.getCurTabData()
},
beforeUpload (file) {
this.uploadLoading = true
this.showConfirmDialog = false
},
submitConfirm () {
this.showConfirmDialog = true
},
submit () {
this.$refs.knowledgeUpload.submit()
},
cancle () {
this.showAddUpdateDialog = false
},
clickCard (data, event) {
if (data.isSelected) { // 原来为选中,当前点击后未选中
const index = this.checkList.indexOf(data)
if (index > -1) {
this.checkList.splice(index, 1)
}
} else {
const index = this.checkList.indexOf(data)
if (index === -1) {
this.checkList.push(data)
}
}
const val = !data.isSelected
data.isSelected = val
this.$emit('checkboxStatusChange', val, data)
},
checkboxStatusChange (val, data) {
data.isSelected = val
this.$emit('checkboxStatusChange', val, data)
},
beforeClose (done) {
if (this.myChart) {
this.myChart.dispose()
this.myChart = null
}
done()
},
handleClose () {
this.showUpdateDialog = false
this.showAddUpdateDialog = false
this.uploadLoading = false
},
handleConfirmClose () {
this.showConfirmDialog = false
},
handleUpdateClose () {
this.showAddUpdateDialog = false
},
showUpdate () {
this.showUpdateDialog = true
this.showAddUpdateDialog = false
},
async jumpToUpdatePage (data, showEnable) {
this.updateKnowledge = data
this.showEnable = showEnable
await this.getCurTabData()
if (data.source === 'cn_psiphon3_ip') {
await this.init()
}
this.showUpdate()
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
this.$nextTick(() => {
this.handleActiveBar()
})
}
},
uploadRecord () {
this.showAddUpdateDialog = true
this.updateObject.name = this.updateKnowledge.name
this.updateObject.label = this.$t(this.updateKnowledge.label)
this.updateObject.description = ''
},
getCurTabData () { // showEnable:true 为psiphon3的知识库false为其它知识库
let params = {
pageSize: -1
}
if (this.showEnable) {
if (this.activeTab === knowledgeCardUpdateRecordType.updateRecord) {
params = {
...params,
opUser: -1
} }
/* } else if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
params = {
...params,
opUser: 0
}
}
}
this.updateLogLoading = true
this.updateHistoryList = []
axios.get(api.knowledgeBaseLog + '/' + this.updateKnowledge.knowledgeId, { params: params }).then(res => {
this.updateHistoryList = res.data.data.list
if (this.updateHistoryList[0]) {
this.currentVersion = this.updateHistoryList[0].commitVersion + 1
}
/*
this.hasUpdatingRecord = false this.hasUpdatingRecord = false
this.updateHistoryList.forEach(item => { this.updateHistoryList.forEach(item => {
if (item.isUpdating) { // if(item.isUpdating){//???????? if (item.isUpdating) { // if(item.isUpdating){//????????

View File

@@ -111,7 +111,7 @@ export default {
}, },
methods: { methods: {
statusChange (plugin) { statusChange (plugin) {
let triggerStatus = plugin.triggerStatus const triggerStatus = plugin.triggerStatus
let statusUrl = triggerStatus === '1' ? api.pluginStatusEnable : api.pluginStatusDisable let statusUrl = triggerStatus === '1' ? api.pluginStatusEnable : api.pluginStatusDisable
statusUrl = statusUrl.replace('{{id}}', plugin.id) statusUrl = statusUrl.replace('{{id}}', plugin.id)
axios.post(statusUrl).then(response => { axios.post(statusUrl).then(response => {

View File

@@ -233,7 +233,7 @@ export default {
*/ */
setup () { setup () {
const { query } = useRoute() const { query } = useRoute()
/*// 获取url携带的range、startTime、endTime /* // 获取url携带的range、startTime、endTime
const rangeParam = query.range const rangeParam = query.range
const startTimeParam = query.startTime const startTimeParam = query.startTime
const endTimeParam = query.endTime const endTimeParam = query.endTime
@@ -250,7 +250,7 @@ export default {
} else { } else {
timeFilter.value.startTime = parseInt(startTimeParam) timeFilter.value.startTime = parseInt(startTimeParam)
timeFilter.value.endTime = parseInt(endTimeParam) timeFilter.value.endTime = parseInt(endTimeParam)
}*/ } */
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.tag.activeEntity || 60 const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.tag.activeEntity || 60
const timeFilter = ref({ dateRangeValue }) const timeFilter = ref({ dateRangeValue })
@@ -472,9 +472,9 @@ export default {
desc = this.$t('tag.observedEntities2') desc = this.$t('tag.observedEntities2')
} }
} }
/*if (this.observedCount > 0) { /* if (this.observedCount > 0) {
desc += `, IP ${this.observedIpCount}, ${this.$t('overall.domain2')} ${this.observedDomainCount}` desc += `, IP ${this.observedIpCount}, ${this.$t('overall.domain2')} ${this.observedDomainCount}`
}*/ } */
} else { } else {
// 只有单种实体时,单个描述 // 只有单种实体时,单个描述
if (this.disableToEntity) { if (this.disableToEntity) {

View File

@@ -1,5 +1,5 @@
import { tableSort } from '@/utils/tools' import { tableSort } from '@/utils/tools'
import { defaultPageSize, fromRoute, position, storageKey, dbTableColumnCustomizeConfigPre,dbTableColumnCustomizeConfig } from '@/utils/constants' import { defaultPageSize, fromRoute, position, storageKey, dbTableColumnCustomizeConfigPre, dbTableColumnCustomizeConfig } from '@/utils/constants'
import _ from 'lodash' import _ from 'lodash'
import { ref } from 'vue' import { ref } from 'vue'
import pagination from '@/components/common/Pagination' import pagination from '@/components/common/Pagination'
@@ -428,11 +428,11 @@ export default {
localStorageTableTitle = await indexedDBUtils.selectTable(tableName).get({ id: userId }) localStorageTableTitle = await indexedDBUtils.selectTable(tableName).get({ id: userId })
} }
let curTableTitles = this.$refs.dataTable && this.$refs.dataTable.tableTitle ? this.$refs.dataTable.tableTitle : [] const curTableTitles = this.$refs.dataTable && this.$refs.dataTable.tableTitle ? this.$refs.dataTable.tableTitle : []
let curTableConfig = dbTableColumnCustomizeConfig.find(item => item.tableName === tableName) const curTableConfig = dbTableColumnCustomizeConfig.find(item => item.tableName === tableName)
if(localStorageTableTitle && curTableConfig && if (localStorageTableTitle && curTableConfig &&
localStorageTableTitle.version !== curTableConfig.version && curTableTitles) { localStorageTableTitle.version !== curTableConfig.version && curTableTitles) {
if(this.$refs.dataList) { if (this.$refs.dataList) {
this.$refs.dataList.updateCustomTableTitle(curTableTitles) this.$refs.dataList.updateCustomTableTitle(curTableTitles)
} }
await indexedDBUtils.selectTable(tableName).put({ await indexedDBUtils.selectTable(tableName).put({

View File

@@ -337,43 +337,43 @@ if (openMock) {
data: { data: {
list: [ list: [
{ {
"subscriberId":111, subscriberId: 111,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 1 active: 1
}, },
{ {
"subscriberId":444, subscriberId: 444,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 1 active: 1
}, },
{ {
"subscriberId":555, subscriberId: 555,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 0 active: 0
},{ }, {
"subscriberId":666, subscriberId: 666,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 1 active: 1
},{ }, {
"subscriberId":777, subscriberId: 777,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 0 active: 0
},{ }, {
"subscriberId":888, subscriberId: 888,
"group": "terrorist", group: 'terrorist',
"info": "terrorist leader", info: 'terrorist leader',
"location": "china", location: 'china',
"active": 1 active: 1
} }
] ]
} }
@@ -384,53 +384,53 @@ if (openMock) {
msg: 'success', msg: 'success',
code: 200, code: 200,
data: { data: {
total:1, total: 1,
pageSize:20, pageSize: 20,
pageNo:1, pageNo: 1,
pages:1, pages: 1,
list: [ list: [
{ {
"subscriberId":111, subscriberId: 111,
"active": 1, active: 1,
"phone_number": 18601680302, phone_number: 18601680302,
"follow": 1 follow: 1
}, },
{ {
"subscriberId":222, subscriberId: 222,
"active": 1, active: 1,
"phone_number": 18601680303, phone_number: 18601680303,
"follow": 0 follow: 0
}, },
{ {
"subscriberId":333, subscriberId: 333,
"active": 0, active: 0,
"phone_number": 18601680304, phone_number: 18601680304,
"follow": 0 follow: 0
},{ }, {
"subscriberId":444, subscriberId: 444,
"active": 1, active: 1,
"phone_number": 18601680305, phone_number: 18601680305,
"follow": 1 follow: 1
},{ }, {
"subscriberId":555, subscriberId: 555,
"active": 0, active: 0,
"phone_number": 18601680306, phone_number: 18601680306,
"follow": 1 follow: 1
},{ }, {
"subscriberId":666, subscriberId: 666,
"active": 1, active: 1,
"phone_number": 18601680307, phone_number: 18601680307,
"follow": 1 follow: 1
},{ }, {
"subscriberId":777, subscriberId: 777,
"active": 1, active: 1,
"phone_number": 18601680308, phone_number: 18601680308,
"follow": 1 follow: 1
},{ }, {
"subscriberId":888, subscriberId: 888,
"active": 1, active: 1,
"phone_number": 18601680300, phone_number: 18601680300,
"follow": 1 follow: 1
} }
] ]
} }

View File

@@ -56,22 +56,22 @@ export const dbTableColumnCustomizeConfig = [
{ {
version: '24.04.06', version: '24.04.06',
tableName: dbUserTableColumnCustomizeConfig tableName: dbUserTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbRoleTableColumnCustomizeConfig tableName: dbRoleTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbOperationLogTableColumnCustomizeConfig tableName: dbOperationLogTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbChartTableColumnCustomizeConfig tableName: dbChartTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbI18nTableColumnCustomizeConfig tableName: dbI18nTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbReportTableColumnCustomizeConfig tableName: dbReportTableColumnCustomizeConfig
},{ }, {
version: '24.04.01', version: '24.04.01',
tableName: dbGalaxySettingTableColumnCustomizeConfig tableName: dbGalaxySettingTableColumnCustomizeConfig
} }

View File

@@ -2,34 +2,34 @@ import vue from '@/main.js'
// import Moment from "moment/moment"; // import Moment from "moment/moment";
// import {transformToUTCTime} from './TimeZone.js' // import {transformToUTCTime} from './TimeZone.js'
//默认Schema 延时15s ,时间粒度 1s // 默认Schema 延时15s ,时间粒度 1s
const defaultSchema = { const defaultSchema = {
"doc": { doc: {
"measurements": { measurements: {
"granularity": 1, granularity: 1,
"ingestion_delay": 15 ingestion_delay: 15
} }
} }
} }
let schemaDict=null; let schemaDict = null
function getSchemaFromLocal(schemaType) { function getSchemaFromLocal (schemaType) {
let schemaData=null let schemaData = null
// if(schemaDict?.[schemaType]){ // if(schemaDict?.[schemaType]){
// schemaData=schemaDict // schemaData=schemaDict
// }else{ // }else{
schemaData = localStorage.getItem('TSGSchema') schemaData = localStorage.getItem('TSGSchema')
// } // }
if (!schemaData) { if (!schemaData) {
return null; return null
} }
const storeData = JSON.parse(schemaData)[schemaType]; const storeData = JSON.parse(schemaData)[schemaType]
// 如果根据key没有找到数据直接返回空 // 如果根据key没有找到数据直接返回空
if (!storeData) { if (!storeData) {
return null; return null
} }
const parsedData = storeData; const parsedData = storeData
const currentTimestamp = new Date().getTime(); const currentTimestamp = new Date().getTime()
// 将当前的时间戳和保存在storage中的timestamp进行比较 // 将当前的时间戳和保存在storage中的timestamp进行比较
// 如果时间差小于等于过期时间说明没有过期,直接返回数据 // 如果时间差小于等于过期时间说明没有过期,直接返回数据
@@ -37,9 +37,9 @@ function getSchemaFromLocal(schemaType) {
if (currentTimestamp - parsedData.timestamp <= parsedData.expire) { if (currentTimestamp - parsedData.timestamp <= parsedData.expire) {
return parsedData.value ? JSON.parse(parsedData.value) : parsedData.value return parsedData.value ? JSON.parse(parsedData.value) : parsedData.value
} else { } else {
setDashboardSchema(schemaType,'') setDashboardSchema(schemaType, '')
} }
return null; return null
} }
/** /**
@@ -48,37 +48,36 @@ function getSchemaFromLocal(schemaType) {
* @param {*} value 保存的数据 * @param {*} value 保存的数据
* @param {*} expire 过期时间默认为1分钟 * @param {*} expire 过期时间默认为1分钟
*/ */
function setDashboardSchema(schemaType, value, expire = 60000) { function setDashboardSchema (schemaType, value, expire = 60000) {
let schemaData = localStorage.getItem('TSGSchema'); const schemaData = localStorage.getItem('TSGSchema')
if (!schemaData) { if (!schemaData) {
localStorage.setItem('TSGSchema', '{}') localStorage.setItem('TSGSchema', '{}')
} }
let TSGSchema = JSON.parse(localStorage.getItem('TSGSchema')) const TSGSchema = JSON.parse(localStorage.getItem('TSGSchema'))
TSGSchema[schemaType] = { TSGSchema[schemaType] = {
value: value, value: value,
expire: expire, expire: expire,
timestamp: new Date().getTime() timestamp: new Date().getTime()
} }
const stringfiedData = JSON.stringify(TSGSchema); const stringfiedData = JSON.stringify(TSGSchema)
localStorage.setItem('TSGSchema', stringfiedData); localStorage.setItem('TSGSchema', stringfiedData)
schemaDict=TSGSchema; schemaDict = TSGSchema
} }
// 获取过期时间毫秒数 // 获取过期时间毫秒数
function getExpireTime(data){ function getExpireTime (data) {
let expireDate=data.expireDate const expireDate = data.expireDate
if(!expireDate){ if (!expireDate) {
return 24 * 60 * 60 * 1000 return 24 * 60 * 60 * 1000
} }
let expireTime=new Date().getTime()-expireDate const expireTime = new Date().getTime() - expireDate
return expireTime return expireTime
} }
function getSchemaFromRemote (schemaType) {
function getSchemaFromRemote(schemaType) {
return vue.$get(`/interface/gateway/api/galaxy/v1/metadata/schema/${schemaType}`).then(res => { return vue.$get(`/interface/gateway/api/galaxy/v1/metadata/schema/${schemaType}`).then(res => {
if (res.status === 200) { if (res.status === 200) {
let expireTime=getExpireTime(res.data) const expireTime = getExpireTime(res.data)
setDashboardSchema(schemaType, JSON.stringify(res.data), expireTime) setDashboardSchema(schemaType, JSON.stringify(res.data), expireTime)
return res.data return res.data
} }
@@ -89,14 +88,13 @@ function getSchemaFromRemote(schemaType) {
}) })
} }
// async 延时时间 // async 延时时间
// 转换时间 start end schmaType 相对时间 绝对时间 // 转换时间 start end schmaType 相对时间 绝对时间
// 时间粒度 // 时间粒度
//获取Schema数据,存在于local 直接取,不存在 直接请求,存本地 // 获取Schema数据,存在于local 直接取,不存在 直接请求,存本地
async function getSchemaInfo(schemaType = '') { async function getSchemaInfo (schemaType = '') {
var schemaInfo = getSchemaFromLocal(schemaType) let schemaInfo = getSchemaFromLocal(schemaType)
if (!schemaInfo) { if (!schemaInfo) {
schemaInfo = await getSchemaFromRemote(schemaType) schemaInfo = await getSchemaFromRemote(schemaType)
} }
@@ -110,26 +108,26 @@ async function getSchemaInfo(schemaType = '') {
* *
* granularity 单位必须是S 秒 * granularity 单位必须是S 秒
* */ * */
async function getTimeQueryParams({start, end, schemaType = '', granularity = 1, toUtc = false, delay = false}) { async function getTimeQueryParams ({ start, end, schemaType = '', granularity = 1, toUtc = false, delay = false }) {
let schemaData = await getSchemaInfo(schemaType); const schemaData = await getSchemaInfo(schemaType)
const schema_ingestion_delay = schemaData?.doc?.measurements?.ingestion_delay || 0; const schema_ingestion_delay = schemaData?.doc?.measurements?.ingestion_delay || 0
const schema_granularity = schemaData?.doc?.measurements?.granularity || 1; const schema_granularity = schemaData?.doc?.measurements?.granularity || 1
//这里需要考虑 传入的是UTC 时间,Moment 可以正常处理吗 // 这里需要考虑 传入的是UTC 时间,Moment 可以正常处理吗
var delayTime = delay ? schema_ingestion_delay : 0; const delayTime = delay ? schema_ingestion_delay : 0
// let startDate = Moment(start).subtract(delayTime, 'seconds') // let startDate = Moment(start).subtract(delayTime, 'seconds')
// let endDate = Moment(end).subtract(delayTime, 'seconds') // let endDate = Moment(end).subtract(delayTime, 'seconds')
let startDate = '1' const startDate = '1'
let endDate = '2' const endDate = '2'
var startStr = startDate.format('YYYY-MM-DD HH:mm:ss') let startStr = startDate.format('YYYY-MM-DD HH:mm:ss')
var endStr = endDate.format('YYYY-MM-DD HH:mm:ss') let endStr = endDate.format('YYYY-MM-DD HH:mm:ss')
//前端计算时间粒度,不能比Schema 支持的最小时间粒度 小 // 前端计算时间粒度,不能比Schema 支持的最小时间粒度 小
var alignmentPeriod = schema_granularity > granularity ? schema_granularity : granularity const alignmentPeriod = schema_granularity > granularity ? schema_granularity : granularity
//UTC 转换 // UTC 转换
if (toUtc) { if (toUtc) {
// startStr = transformToUTCTime(startStr) // startStr = transformToUTCTime(startStr)
// endStr = transformToUTCTime(endStr) // endStr = transformToUTCTime(endStr)
@@ -139,8 +137,8 @@ async function getTimeQueryParams({start, end, schemaType = '', granularity = 1,
return { return {
start: startStr, start: startStr,
end: endStr, end: endStr,
granularity: 'PT'+schema_granularity+'S', granularity: 'PT' + schema_granularity + 'S',
alignmentPeriod: 'PT'+alignmentPeriod+'S', alignmentPeriod: 'PT' + alignmentPeriod + 'S'
} }
} }
@@ -148,4 +146,4 @@ export default {
getTimeQueryParams, getTimeQueryParams,
getSchemaInfo getSchemaInfo
} }
export {getSchemaFromLocal, getSchemaInfo, setDashboardSchema, getSchemaFromRemote, getTimeQueryParams}; export { getSchemaFromLocal, getSchemaInfo, setDashboardSchema, getSchemaFromRemote, getTimeQueryParams }

View File

@@ -140,8 +140,8 @@ export function getUnitType (column) {
} }
/* 单位转换,返回转换后的[value, unit]type=time时若value<1ms返回<1mstype=percent时若value<0.01%,返回<0.01% */ /* 单位转换,返回转换后的[value, unit]type=time时若value<1ms返回<1mstype=percent时若value<0.01%,返回<0.01% */
export function valueToRangeValue (value, unitType,sourceUnit, targetUnit, dot) { export function valueToRangeValue (value, unitType, sourceUnit, targetUnit, dot) {
const values = unitConvert(value, unitType,sourceUnit, targetUnit, dot) const values = unitConvert(value, unitType, sourceUnit, targetUnit, dot)
if (values[0] === '-') { if (values[0] === '-') {
return values return values
} }

View File

@@ -67,7 +67,7 @@ export default {
dateIssued: '', dateIssued: '',
dateExpires: '' dateExpires: ''
}, },
loading:false loading: false
} }
}, },
components: { components: {

View File

@@ -167,10 +167,10 @@ export default {
}) })
}, },
resize () { resize () {
if(this.myChart) { if (this.myChart) {
this.myChart.resize() this.myChart.resize()
} }
if(this.myChart2) { if (this.myChart2) {
this.myChart2.resize() this.myChart2.resize()
} }
} }

View File

@@ -838,7 +838,7 @@ export const tagLineChartOption = {
// return unitConvert(value, unitTypes.number).join('') // return unitConvert(value, unitTypes.number).join('')
// } // }
}, },
minInterval:1 minInterval: 1
} }
], ],
series: [] series: []

View File

@@ -89,7 +89,7 @@ export default {
const initialData = await this.generateInitialData() const initialData = await this.generateInitialData()
this.initialData = _.cloneDeep(initialData) // 初始化数据 this.initialData = _.cloneDeep(initialData) // 初始化数据
let hoverNode = null let hoverNode = null
let canvasHeight = document.body.clientHeight - 100 const canvasHeight = document.body.clientHeight - 100
this.graph = ForceGraph()(document.getElementById('entityGraph')) this.graph = ForceGraph()(document.getElementById('entityGraph'))
.height(canvasHeight) .height(canvasHeight)
.graphData(initialData) .graphData(initialData)
@@ -113,9 +113,9 @@ export default {
ctx.beginPath() ctx.beginPath()
ctx.arc(node.x, node.y, nodeStyle.shadowR, 0, 2 * Math.PI, false) ctx.arc(node.x, node.y, nodeStyle.shadowR, 0, 2 * Math.PI, false)
ctx.closePath() ctx.closePath()
ctx.fillStyle = node === this.clickNode || node === hoverNode ? ctx.fillStyle = node === this.clickNode || node === hoverNode
nodeStyle.hoveredShadowColor : ? nodeStyle.hoveredShadowColor
nodeStyle.shadowColor : nodeStyle.shadowColor
ctx.fill() ctx.fill()
// 内部挖空 // 内部挖空
ctx.beginPath() ctx.beginPath()
@@ -132,7 +132,7 @@ export default {
ctx.strokeStyle = nodeStyle.borderColor ctx.strokeStyle = nodeStyle.borderColor
ctx.stroke() ctx.stroke()
// 图片 // 图片
ctx.drawImage(node.img, node.x - nodeStyle.iconWidth / 2, node.y - nodeStyle.iconHeight / 2, nodeStyle.iconWidth, nodeStyle.iconHeight); ctx.drawImage(node.img, node.x - nodeStyle.iconWidth / 2, node.y - nodeStyle.iconHeight / 2, nodeStyle.iconWidth, nodeStyle.iconHeight)
// 文字 // 文字
ctx.font = nodeStyle.font ctx.font = nodeStyle.font
const textWidth = ctx.measureText(node.label).width const textWidth = ctx.measureText(node.label).width
@@ -275,7 +275,7 @@ export default {
ctx.fillStyle = color ctx.fillStyle = color
ctx.fill() ctx.fill()
ctx.restore() // 恢复之前保存的状态 ctx.restore() // 恢复之前保存的状态
/*if (link.source.x !== undefined && link.source.y !== undefined && link.target.x !== undefined && link.target.y !== undefined) { /* if (link.source.x !== undefined && link.source.y !== undefined && link.target.x !== undefined && link.target.y !== undefined) {
const nodeStyle = this.getNodeStyle(link.target.type, link.target.data.entityType) const nodeStyle = this.getNodeStyle(link.target.type, link.target.data.entityType)
ctx.lineWidth = 0.5 ctx.lineWidth = 0.5
@@ -303,7 +303,7 @@ export default {
ctx.fill() ctx.fill()
ctx.closePath() ctx.closePath()
ctx.stroke() ctx.stroke()
}*/ } */
}) })
.autoPauseRedraw(false) // keep redrawing after engine has stopped如果您有依赖于画布的不断重绘的自定义动态对象建议关闭此选项。 .autoPauseRedraw(false) // keep redrawing after engine has stopped如果您有依赖于画布的不断重绘的自定义动态对象建议关闭此选项。
.onNodeHover(node => { .onNodeHover(node => {
@@ -332,8 +332,8 @@ export default {
} }
const toAddNodes = [] const toAddNodes = []
const toAddLinks = [] const toAddLinks = []
let keyCount = Object.keys(node.data.relatedEntities).length const keyCount = Object.keys(node.data.relatedEntities).length
Object.keys(node.data.relatedEntities).forEach((k,i) => { Object.keys(node.data.relatedEntities).forEach((k, i) => {
if (node.data.relatedEntities[k].total) { if (node.data.relatedEntities[k].total) {
// 若已有同级同类型的listNode不生成此tempNode // 若已有同级同类型的listNode不生成此tempNode
const neighbors = node.getNeighbors(this.graph.graphData()) const neighbors = node.getNeighbors(this.graph.graphData())
@@ -349,12 +349,12 @@ export default {
node, node,
this.getIconUrl(k, false, false) this.getIconUrl(k, false, false)
) )
//临时节点的初始固定坐标为其对应的entity节点坐标展示直线动画 // 临时节点的初始固定坐标为其对应的entity节点坐标展示直线动画
//tempNode.fx = node.x // tempNode.fx = node.x
//tempNode.fy = node.y // tempNode.fy = node.y
let tempNodePoint = this.pointOfRotate({x:node.sourceNode.x,y:node.sourceNode.y},{x:node.x,y:node.y},this.getTempNodeAngle(keyCount,i))//临时节点固定角度为以entity节点为centerlist节点为from旋转到临时节点的角度 const tempNodePoint = this.pointOfRotate({ x: node.sourceNode.x, y: node.sourceNode.y }, { x: node.x, y: node.y }, this.getTempNodeAngle(keyCount, i))// 临时节点固定角度为以entity节点为centerlist节点为from旋转到临时节点的角度
let finalTempNodePoint = this.pointOfLine({x:node.x,y:node.y},tempNodePoint,this.defaultLinkDistance)//start,end,lineLength const finalTempNodePoint = this.pointOfLine({ x: node.x, y: node.y }, tempNodePoint, this.defaultLinkDistance)// start,end,lineLength
if(tempNodePoint.x && tempNodePoint.y) { if (tempNodePoint.x && tempNodePoint.y) {
tempNode.fx = (node.x + finalTempNodePoint.x) / 2 tempNode.fx = (node.x + finalTempNodePoint.x) / 2
tempNode.fy = (node.y + finalTempNodePoint.y) / 2 tempNode.fy = (node.y + finalTempNodePoint.y) / 2
} }
@@ -388,18 +388,18 @@ export default {
// 若已达第六层则只生成listNode不再展开entityNode // 若已达第六层则只生成listNode不再展开entityNode
const nodes = [] const nodes = []
const links = [] const links = []
let stackNodes = [] const stackNodes = []
const stackLinks = [] const stackLinks = []
const sourceNode = node.getSourceNode(this.graph.graphData()) const sourceNode = node.getSourceNode(this.graph.graphData())
const k1 = (node.x - sourceNode.x) / linkDistance.normal const k1 = (node.x - sourceNode.x) / linkDistance.normal
const k2 = (node.y - sourceNode.y) / linkDistance.normal const k2 = (node.y - sourceNode.y) / linkDistance.normal
const listNode = new Node( const listNode = new Node(
nodeType.listNode, nodeType.listNode,
`${sourceNode.realId}__${node.data.entityType}-list`, `${sourceNode.realId}__${node.data.entityType}-list`,
{ {
entityType: node.data.entityType, entityType: node.data.entityType,
fx: sourceNode.x + k1 * linkDistance.entityToList, fx: sourceNode.x + k1 * linkDistance.entityToList,
fy: sourceNode.y + k2 * linkDistance.entityToList, fy: sourceNode.y + k2 * linkDistance.entityToList
}, },
sourceNode, sourceNode,
this.getIconUrl(node.data.entityType, false, false) this.getIconUrl(node.data.entityType, false, false)
@@ -423,7 +423,7 @@ export default {
try { try {
const entities = await sourceNode.queryRelatedEntities(listNode.data.entityType) const entities = await sourceNode.queryRelatedEntities(listNode.data.entityType)
sourceNode.data.relatedEntities[listNode.data.entityType].list.push(...entities.list) sourceNode.data.relatedEntities[listNode.data.entityType].list.push(...entities.list)
let curNodes = this.graph.graphData().nodes const curNodes = this.graph.graphData().nodes
entities.list.forEach(entity => { entities.list.forEach(entity => {
const entityNode = new Node(nodeType.entityNode, entity.vertex, { const entityNode = new Node(nodeType.entityNode, entity.vertex, {
entityType: listNode.data.entityType, entityType: listNode.data.entityType,
@@ -432,16 +432,16 @@ export default {
y: listNode.y + Math.random() * 10 - 5 y: listNode.y + Math.random() * 10 - 5
}, listNode, this.getIconUrl(listNode.data.entityType, false, false)) }, listNode, this.getIconUrl(listNode.data.entityType, false, false))
nodes.push(entityNode) nodes.push(entityNode)
let link = new Link(listNode, entityNode) const link = new Link(listNode, entityNode)
links.push(link) links.push(link)
if(curNodes.findIndex(node => node.id === entityNode.id) === -1) {//过滤掉已有的节点 if (curNodes.findIndex(node => node.id === entityNode.id) === -1) { // 过滤掉已有的节点
stackNodes.push(_.cloneDeep(entityNode)) stackNodes.push(_.cloneDeep(entityNode))
} }
stackLinks.push(_.cloneDeep(link)) stackLinks.push(_.cloneDeep(link))
}) })
this.addItems(nodes, links, false) this.addItems(nodes, links, false)
//由于点击临时节点后增加节点分为了2步所以需要将2步的所有节点一起缓存 // 由于点击临时节点后增加节点分为了2步所以需要将2步的所有节点一起缓存
this.stackData.undo.push({nodes:stackNodes, links:stackLinks}) this.stackData.undo.push({ nodes: stackNodes, links: stackLinks })
setTimeout(() => { setTimeout(() => {
listNode.fx = null listNode.fx = null
@@ -485,65 +485,65 @@ export default {
.d3Force('charge', d3.forceManyBody().strength(this.defaultChargeStrength)) .d3Force('charge', d3.forceManyBody().strength(this.defaultChargeStrength))
.onNodeDrag((node, translate) => { .onNodeDrag((node, translate) => {
const { nodes, links } = this.graph.graphData() const { nodes, links } = this.graph.graphData()
//拖动entity节点时如果此entity节点有临时节点则同时移动临时节点 // 拖动entity节点时如果此entity节点有临时节点则同时移动临时节点
if(node.type === nodeType.entityNode) { if (node.type === nodeType.entityNode) {
//查询点击entity节点对应的list节点 // 查询点击entity节点对应的list节点
let fromX = node.sourceNode.preDragX ? node.sourceNode.preDragX : node.sourceNode.x const fromX = node.sourceNode.preDragX ? node.sourceNode.preDragX : node.sourceNode.x
let fromY = node.sourceNode.preDragY ? node.sourceNode.preDragY : node.sourceNode.y const fromY = node.sourceNode.preDragY ? node.sourceNode.preDragY : node.sourceNode.y
let from = {x:fromX,y:fromY} const from = { x: fromX, y: fromY }
let centerX = node.preDragX ? node.preDragX : node.x const centerX = node.preDragX ? node.preDragX : node.x
let centerY = node.preDragY ? node.preDragY : node.y const centerY = node.preDragY ? node.preDragY : node.y
let center = {x:centerX,y:centerY} const center = { x: centerX, y: centerY }
const tempLinks = links.filter(link => link.source.id === node.id && link.type === linkType.temp) const tempLinks = links.filter(link => link.source.id === node.id && link.type === linkType.temp)
tempLinks.forEach(link => { tempLinks.forEach(link => {
const tempNodeGroup = nodes.filter(node => node.id === link.target.id) const tempNodeGroup = nodes.filter(node => node.id === link.target.id)
tempNodeGroup.forEach(tempNode => { tempNodeGroup.forEach(tempNode => {
let toX = tempNode.fx ? tempNode.fx : tempNode.x const toX = tempNode.fx ? tempNode.fx : tempNode.x
let toY = tempNode.fy ? tempNode.fy : tempNode.y const toY = tempNode.fy ? tempNode.fy : tempNode.y
let to = {x:toX,y:toY} const to = { x: toX, y: toY }
if(!tempNode.angle) {//每次拖拽,每个临时节点计算一次角度即可,因为角度不会发生改变 if (!tempNode.angle) { // 每次拖拽,每个临时节点计算一次角度即可,因为角度不会发生改变
tempNode.angle = this.angleOfRotate(from,to,center) tempNode.angle = this.angleOfRotate(from, to, center)
} }
let toPoint = this.pointOfRotate({x: node.sourceNode.x, y: node.sourceNode.y}, {x:node.x + translate.x ,y:node.y + translate.y}, tempNode.angle) const toPoint = this.pointOfRotate({ x: node.sourceNode.x, y: node.sourceNode.y }, { x: node.x + translate.x, y: node.y + translate.y }, tempNode.angle)
//因为在拖拽的过长中list节点到entity节点之间的距离是变化的且我们要求的是临时节点到entity节点之间的距离不发生变化所以此处需要再次进行计算转换得到最终的坐标 // 因为在拖拽的过长中list节点到entity节点之间的距离是变化的且我们要求的是临时节点到entity节点之间的距离不发生变化所以此处需要再次进行计算转换得到最终的坐标
//已知2个点的坐标求从起点开始指定长度线段的终点坐标 // 已知2个点的坐标求从起点开始指定长度线段的终点坐标
if(!tempNode.lineLength) {//每次拖拽,每个临时节点计算一次与实体节点的距离即可,因为距离在当前拖拽中不会发生改变 if (!tempNode.lineLength) { // 每次拖拽,每个临时节点计算一次与实体节点的距离即可,因为距离在当前拖拽中不会发生改变
tempNode.lineLength = Math.sqrt(Math.pow(node.x - tempNode.fx,2) + Math.pow(node.y - tempNode.fy,2)) tempNode.lineLength = Math.sqrt(Math.pow(node.x - tempNode.fx, 2) + Math.pow(node.y - tempNode.fy, 2))
} }
let finalTo = this.pointOfLine({x:node.x + translate.x ,y:node.y + translate.y},toPoint,tempNode.lineLength) const finalTo = this.pointOfLine({ x: node.x + translate.x, y: node.y + translate.y }, toPoint, tempNode.lineLength)
tempNode.fx = finalTo.x tempNode.fx = finalTo.x
tempNode.fy = finalTo.y tempNode.fy = finalTo.y
}) })
}) })
} }
//拖动list节点时如果此list节点对应的entity节点有临时节点则同时移动临时节点 // 拖动list节点时如果此list节点对应的entity节点有临时节点则同时移动临时节点
if(node.type === nodeType.listNode) { if (node.type === nodeType.listNode) {
//根据list节点找到list节点连接的线 // 根据list节点找到list节点连接的线
const listLinks = links.filter(link => link.source.id === node.id) const listLinks = links.filter(link => link.source.id === node.id)
let fromX = node.preDragX ? node.preDragX : node.x const fromX = node.preDragX ? node.preDragX : node.x
let fromY = node.preDragY ? node.preDragY : node.y const fromY = node.preDragY ? node.preDragY : node.y
listLinks.forEach(link => { listLinks.forEach(link => {
//找到连接临时节点的虚线 // 找到连接临时节点的虚线
const tempLinks = links.filter(entityLink => entityLink.source.id === link.target.id && entityLink.type === linkType.temp) const tempLinks = links.filter(entityLink => entityLink.source.id === link.target.id && entityLink.type === linkType.temp)
if(tempLinks && tempLinks.length > 0) { if (tempLinks && tempLinks.length > 0) {
tempLinks.forEach(tempLink => { tempLinks.forEach(tempLink => {
//找到entity节点 // 找到entity节点
const entityNode = nodes.find(normalNode => normalNode.id === tempLink.source.id && normalNode.type === nodeType.entityNode) const entityNode = nodes.find(normalNode => normalNode.id === tempLink.source.id && normalNode.type === nodeType.entityNode)
if(entityNode) { if (entityNode) {
let entityNodeX = entityNode.fx ? entityNode.fx : entityNode.x const entityNodeX = entityNode.fx ? entityNode.fx : entityNode.x
let entityNodeY = entityNode.fy ? entityNode.fy : entityNode.y const entityNodeY = entityNode.fy ? entityNode.fy : entityNode.y
let angle = this.angleOfRotate({x:fromX,y:fromY},{x:node.x + translate.x,y:node.y + translate.y},{x:entityNodeX,y:entityNodeY}) const angle = this.angleOfRotate({ x: fromX, y: fromY }, { x: node.x + translate.x, y: node.y + translate.y }, { x: entityNodeX, y: entityNodeY })
const tempNodes = nodes.filter(normalNode => normalNode.id === tempLink.target.id && normalNode.type === nodeType.tempNode)//找到临时节点 const tempNodes = nodes.filter(normalNode => normalNode.id === tempLink.target.id && normalNode.type === nodeType.tempNode)// 找到临时节点
tempNodes.forEach(tempNode => { tempNodes.forEach(tempNode => {
let tempNodeX = tempNode.fx ? tempNode.fx : tempNode.x const tempNodeX = tempNode.fx ? tempNode.fx : tempNode.x
let tempNodeY = tempNode.fy ? tempNode.fy : tempNode.y const tempNodeY = tempNode.fy ? tempNode.fy : tempNode.y
let sourceNodeX = tempLink.source.fx ? tempLink.source.fx : tempLink.source.x const sourceNodeX = tempLink.source.fx ? tempLink.source.fx : tempLink.source.x
let sourceNodeY = tempLink.source.fy ? tempLink.source.fy : tempLink.source.y const sourceNodeY = tempLink.source.fy ? tempLink.source.fy : tempLink.source.y
//rotate为list节点旋转的角度根据旋转角度及临时节点的位置及entity节点的坐标得到临时节点旋转后的坐标 // rotate为list节点旋转的角度根据旋转角度及临时节点的位置及entity节点的坐标得到临时节点旋转后的坐标
let to = this.pointOfRotate({x:tempNodeX, y:tempNodeY}, {x:sourceNodeX,y:sourceNodeY}, angle) const to = this.pointOfRotate({ x: tempNodeX, y: tempNodeY }, { x: sourceNodeX, y: sourceNodeY }, angle)
tempNode.fx = to.x tempNode.fx = to.x
tempNode.fy = to.y tempNode.fy = to.y
}) })
@@ -552,33 +552,33 @@ export default {
} }
}) })
} }
//记录上次拖拽时节点的坐标,否则计算时出现误差。 // 记录上次拖拽时节点的坐标,否则计算时出现误差。
node.preDragX = node.x + translate.x node.preDragX = node.x + translate.x
node.preDragY = node.y + translate.y node.preDragY = node.y + translate.y
}) })
.cooldownTime(2000)//到时间后才执行onEngineStop .cooldownTime(2000)// 到时间后才执行onEngineStop
.onNodeDragEnd((node, translate) => { // 修复拖动节点 .onNodeDragEnd((node, translate) => { // 修复拖动节点
node.fx = node.x node.fx = node.x
node.fy = node.y node.fy = node.y
//拖拽结束时把所有临时节点的的angle置为null,便于拖动其它节点时的计算 // 拖拽结束时把所有临时节点的的angle置为null,便于拖动其它节点时的计算
this.graph.graphData().nodes.forEach(node => { this.graph.graphData().nodes.forEach(node => {
if(node.type === nodeType.tempNode) { if (node.type === nodeType.tempNode) {
node.angle = null node.angle = null
node.lineLength = null node.lineLength = null
} }
}) })
}) })
.onEngineTick(() => { .onEngineTick(() => {
if(this.isClicking) { if (this.isClicking) {
const tempNodeGroup = this.graph.graphData().nodes.filter(node => node.type === nodeType.tempNode) const tempNodeGroup = this.graph.graphData().nodes.filter(node => node.type === nodeType.tempNode)
if(tempNodeGroup.length > 0) { if (tempNodeGroup.length > 0) {
let keyCount = tempNodeGroup.length const keyCount = tempNodeGroup.length
tempNodeGroup.forEach((tempNode,i) => { tempNodeGroup.forEach((tempNode, i) => {
let tempNodeSource = tempNode.sourceNode const tempNodeSource = tempNode.sourceNode
if(tempNodeSource) { if (tempNodeSource) {
let tempNodePoint = this.pointOfRotate({x:tempNodeSource.sourceNode.x,y:tempNodeSource.sourceNode.y},{x:tempNodeSource.x,y:tempNodeSource.y},this.getTempNodeAngle(keyCount,i))//临时节点固定角度为以entity节点为centerlist节点为from旋转到临时节点的角度 const tempNodePoint = this.pointOfRotate({ x: tempNodeSource.sourceNode.x, y: tempNodeSource.sourceNode.y }, { x: tempNodeSource.x, y: tempNodeSource.y }, this.getTempNodeAngle(keyCount, i))// 临时节点固定角度为以entity节点为centerlist节点为from旋转到临时节点的角度
let finalTempNodePoint = this.pointOfLine({x:tempNodeSource.x,y:tempNodeSource.y},tempNodePoint,this.defaultLinkDistance)//start,end,lineLength const finalTempNodePoint = this.pointOfLine({ x: tempNodeSource.x, y: tempNodeSource.y }, tempNodePoint, this.defaultLinkDistance)// start,end,lineLength
if(tempNodePoint.x && tempNodePoint.y) { if (tempNodePoint.x && tempNodePoint.y) {
tempNode.fx = finalTempNodePoint.x tempNode.fx = finalTempNodePoint.x
tempNode.fy = finalTempNodePoint.y tempNode.fy = finalTempNodePoint.y
} }
@@ -595,31 +595,31 @@ export default {
this.rightBox.loading = false this.rightBox.loading = false
} }
}, },
getTempNodeAngle(nodeCount,i) { getTempNodeAngle (nodeCount, i) {
switch (nodeCount) { switch (nodeCount) {
case 1: case 1:
return 180 return 180
case 2: case 2:
return 150 + i*60 return 150 + i * 60
case 3: case 3:
return 150 + i*30 return 150 + i * 30
} }
}, },
//根据3个点坐标计算节点旋转的角度 // 根据3个点坐标计算节点旋转的角度
angleOfRotate(from, to, center) { angleOfRotate (from, to, center) {
let ab = {} const ab = {}
let ac = {} const ac = {}
ab.x = from.x - center.x ab.x = from.x - center.x
ab.y = from.y - center.y ab.y = from.y - center.y
ac.x = to.x - center.x ac.x = to.x - center.x
ac.y = to.y - center.y ac.y = to.y - center.y
let direct = (ab.x * ac.y) - (ab.y * ac.x)//求节点是顺时针还是逆时针旋转 const direct = (ab.x * ac.y) - (ab.y * ac.x)// 求节点是顺时针还是逆时针旋转
let lengthAb = Math.sqrt(Math.pow(center.x - from.x,2) + Math.pow(center.y - from.y,2)), const lengthAb = Math.sqrt(Math.pow(center.x - from.x, 2) + Math.pow(center.y - from.y, 2))
lengthAc = Math.sqrt(Math.pow(center.x - to.x,2) + Math.pow(center.y - to.y,2)), const lengthAc = Math.sqrt(Math.pow(center.x - to.x, 2) + Math.pow(center.y - to.y, 2))
lengthBc = Math.sqrt(Math.pow(from.x - to.x,2) + Math.pow(from.y - to.y,2)) const lengthBc = Math.sqrt(Math.pow(from.x - to.x, 2) + Math.pow(from.y - to.y, 2))
let cosA = (Math.pow(lengthAb,2) + Math.pow(lengthAc,2) - Math.pow(lengthBc,2)) / (2 * lengthAb * lengthAc)//余弦定理求出旋转角 const cosA = (Math.pow(lengthAb, 2) + Math.pow(lengthAc, 2) - Math.pow(lengthBc, 2)) / (2 * lengthAb * lengthAc)// 余弦定理求出旋转角
let angleA = Math.acos(cosA) * 180 / Math.PI let angleA = Math.acos(cosA) * 180 / Math.PI
if(direct < 0) {//负数表示逆时针旋转,正数表示顺时针旋转 if (direct < 0) { // 负数表示逆时针旋转,正数表示顺时针旋转
angleA = -angleA angleA = -angleA
} }
return angleA return angleA
@@ -628,46 +628,46 @@ export default {
// center: 圆心点; // center: 圆心点;
// angle: 旋转角度° -- [angle * M_PI / 180]:将角度换算为弧度 // angle: 旋转角度° -- [angle * M_PI / 180]:将角度换算为弧度
// 【注意】angle 逆时针为正,顺时针为负 // 【注意】angle 逆时针为正,顺时针为负
pointOfRotate(from,center,angle){ pointOfRotate (from, center, angle) {
var a = center.x const a = center.x
var b = center.y const b = center.y
var x0 = from.x const x0 = from.x
var y0 = from.y const y0 = from.y
var rx = a + (x0-a) * Math.cos(angle * Math.PI / 180) - (y0-b) * Math.sin(angle * Math.PI / 180) const rx = a + (x0 - a) * Math.cos(angle * Math.PI / 180) - (y0 - b) * Math.sin(angle * Math.PI / 180)
var ry = b + (x0-a) * Math.sin(angle * Math.PI / 180) + (y0-b) * Math.cos(angle * Math.PI / 180) const ry = b + (x0 - a) * Math.sin(angle * Math.PI / 180) + (y0 - b) * Math.cos(angle * Math.PI / 180)
if(rx && ry) { if (rx && ry) {
return {x:rx,y:ry} return { x: rx, y: ry }
} else { } else {
return from return from
} }
}, },
//已知2个点的坐标求从起点开始指定长度线段的终点坐标 // 已知2个点的坐标求从起点开始指定长度线段的终点坐标
pointOfLine(start, end, lineLength) { pointOfLine (start, end, lineLength) {
// 计算总距离 // 计算总距离
let totalDistance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)) const totalDistance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2))
let cosA = (end.x - start.x)/totalDistance const cosA = (end.x - start.x) / totalDistance
let sinA = (end.y - start.y) / totalDistance const sinA = (end.y - start.y) / totalDistance
let finalX = start.x + cosA * lineLength const finalX = start.x + cosA * lineLength
let finalY = start.y + sinA * lineLength const finalY = start.y + sinA * lineLength
return {x:finalX, y:finalY} return { x: finalX, y: finalY }
}, },
handleToolsbarClick (code) { handleToolsbarClick (code) {
if (code === 'undo') {//上一步 if (code === 'undo') { // 上一步
const data = this.stackData.undo.pop() const data = this.stackData.undo.pop()
this.stackData.justUndo = true this.stackData.justUndo = true
if(data) { if (data) {
const { nodes, links } = this.graph.graphData() const { nodes, links } = this.graph.graphData()
data.nodes.forEach(popNode => { data.nodes.forEach(popNode => {
const popNodeIndex = nodes.findIndex(item => item.id === popNode.id) const popNodeIndex = nodes.findIndex(item => item.id === popNode.id)
if (popNodeIndex > -1) { if (popNodeIndex > -1) {
nodes.splice(popNodeIndex,1) nodes.splice(popNodeIndex, 1)
} }
}) })
data.links.forEach(link => { data.links.forEach(link => {
const linksIndex = links.findIndex(item => item.source.id === link.source && item.target.id === link.target) const linksIndex = links.findIndex(item => item.source.id === link.source && item.target.id === link.target)
if (linksIndex > -1) { if (linksIndex > -1) {
links.splice(linksIndex,1) links.splice(linksIndex, 1)
} }
}) })
this.cleanTempItems() this.cleanTempItems()
@@ -677,9 +677,9 @@ export default {
} }
this.onCloseBlock() this.onCloseBlock()
} }
} else if (code === 'redo') {//下一步 } else if (code === 'redo') { // 下一步
const data = this.stackData.redo.pop() const data = this.stackData.redo.pop()
if(data) { if (data) {
this.stackData.justRedo = true this.stackData.justRedo = true
this.addItems(data.nodes, data.links) this.addItems(data.nodes, data.links)
this.cleanTempItems() this.cleanTempItems()
@@ -689,7 +689,7 @@ export default {
this.onCloseBlock() this.onCloseBlock()
} }
} else if (code === 'autoZoom') { } else if (code === 'autoZoom') {
this.graph.zoomToFit(100,100) this.graph.zoomToFit(100, 100)
} else if (code === 'zoomOut') { } else if (code === 'zoomOut') {
this.graph.zoom(this.graph.zoom() + 0.2) this.graph.zoom(this.graph.zoom() + 0.2)
} else if (code === 'zoomIn') { } else if (code === 'zoomIn') {
@@ -930,7 +930,7 @@ export default {
y: cy + cy - sy + Math.random() * 30 - 15 y: cy + cy - sy + Math.random() * 30 - 15
} }
}, },
addItems (toAddNodes, toAddLinks,stack = true) { addItems (toAddNodes, toAddLinks, stack = true) {
if (toAddNodes.length || toAddLinks.length) { if (toAddNodes.length || toAddLinks.length) {
const { nodes, links } = this.graph.graphData() const { nodes, links } = this.graph.graphData()
const nodes2 = toAddNodes.filter(n => !nodes.some(n2 => n.id === n2.id)) const nodes2 = toAddNodes.filter(n => !nodes.some(n2 => n.id === n2.id))
@@ -938,8 +938,8 @@ export default {
links.push(...toAddLinks) links.push(...toAddLinks)
this.graph.graphData({ nodes, links }) this.graph.graphData({ nodes, links })
if(stack) { if (stack) {
this.stackData.undo.push(_.cloneDeep({nodes:nodes2, links:toAddLinks})) this.stackData.undo.push(_.cloneDeep({ nodes: nodes2, links: toAddLinks }))
} }
} }
}, },
@@ -950,20 +950,20 @@ export default {
if (newNodes.length !== nodes.length || newLinks.length !== links.length) { if (newNodes.length !== nodes.length || newLinks.length !== links.length) {
this.graph.graphData({ nodes: newNodes, links: newLinks }) this.graph.graphData({ nodes: newNodes, links: newLinks })
} }
//清理临时节点时同时释放临时节点对应的entity节点,不再固定位置 // 清理临时节点时同时释放临时节点对应的entity节点,不再固定位置
const tempNodes = nodes.filter(n => n.type === nodeType.tempNode) const tempNodes = nodes.filter(n => n.type === nodeType.tempNode)
tempNodes.forEach(n => { tempNodes.forEach(n => {
if(n.sourceNode) { if (n.sourceNode) {
n.sourceNode.fx = null n.sourceNode.fx = null
n.sourceNode.fy = null n.sourceNode.fy = null
} }
}) })
//点击节点的时候把所有list节点的的preDragX和preDragY置为null,便于拖动其它节点时的计算 // 点击节点的时候把所有list节点的的preDragX和preDragY置为null,便于拖动其它节点时的计算
nodes.forEach(node => { nodes.forEach(node => {
//if(node.type === nodeType.listNode) { // if(node.type === nodeType.listNode) {
node.preDragX = null node.preDragX = null
node.preDragY = null node.preDragY = null
//} // }
}) })
}, },
async generateInitialData (clickNode) { async generateInitialData (clickNode) {
@@ -1033,7 +1033,7 @@ export default {
return return
} }
if (sourceNode.data.relatedEntities[expandType].list.length < 50) { if (sourceNode.data.relatedEntities[expandType].list.length < 50) {
//this.rightBox.loading = true // this.rightBox.loading = true
try { try {
const entities = await sourceNode.queryRelatedEntities(expandType) const entities = await sourceNode.queryRelatedEntities(expandType)
sourceNode.data.relatedEntities[expandType].list.push(...entities.list) sourceNode.data.relatedEntities[expandType].list.push(...entities.list)
@@ -1072,7 +1072,7 @@ export default {
const toAddNodes = [] const toAddNodes = []
const toAddLinks = [] const toAddLinks = []
//this.rightBox.loading = true // this.rightBox.loading = true
try { try {
const entities = await node.queryRelatedEntities(expandType) const entities = await node.queryRelatedEntities(expandType)
node.data.relatedEntities[expandType].list.push(...entities.list) node.data.relatedEntities[expandType].list.push(...entities.list)

View File

@@ -1228,11 +1228,11 @@ export default {
async scrollList (e) { async scrollList (e) {
if (!this.isChecked) { if (!this.isChecked) {
const obj = document.getElementById('locationMap-subscriber-scroll') const obj = document.getElementById('locationMap-subscriber-scroll')
let scrollTop = obj.scrollTop const scrollTop = obj.scrollTop
let scroll = scrollTop - this.preScrollTop; const scroll = scrollTop - this.preScrollTop
this.preScrollTop = scrollTop; this.preScrollTop = scrollTop
//向下滚动才进行加载数据 // 向下滚动才进行加载数据
if(scroll >= 0 && (obj.scrollHeight - obj.scrollTop - obj.clientHeight <= 10) && if (scroll >= 0 && (obj.scrollHeight - obj.scrollTop - obj.clientHeight <= 10) &&
(obj.scrollHeight - obj.scrollTop - obj.clientHeight > 1) && (obj.scrollHeight - obj.scrollTop - obj.clientHeight > 1) &&
obj.scrollHeight !== 0 && obj.scrollHeight !== 0 &&
!this.loading.subscriberLoading) { !this.loading.subscriberLoading) {

View File

@@ -1,7 +1,7 @@
export const pieOption = { export const pieOption = {
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
appendToBody: true//解决提示框被遮挡的问题 appendToBody: true// 解决提示框被遮挡的问题
}, },
legend: { legend: {
show: false, show: false,

View File

@@ -1173,11 +1173,11 @@ export default {
this.editTagErrorTip = '' this.editTagErrorTip = ''
this.showImportedData[index].isValid = 1 this.showImportedData[index].isValid = 1
this.showImportedData[index].msg = this.$t('overall.success') this.showImportedData[index].msg = this.$t('overall.success')
/*if (this.hasErrorImportedData()) { /* if (this.hasErrorImportedData()) {
this.previewErrorTip = this.$t('validate.pleaseCheckForErrorItem') this.previewErrorTip = this.$t('validate.pleaseCheckForErrorItem')
} else { } else {
this.previewErrorTip = '' this.previewErrorTip = ''
}*/ } */
} else { } else {
this.showImportedData[index].isValid = 0 this.showImportedData[index].isValid = 0
} }