123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- /**
- * @fileoverview search 插件
- */
- function Search (vm) {
- /**
- * @description 关键词搜索
- * @param {regexp|string} key 要搜索的关键词
- * @param {boolean} anchor 是否将搜索结果设置为锚点
- * @param {string} style 搜索结果的样式
- */
- vm.search = function (key, anchor, style = 'background-color:yellow') {
- const obj = {}
- const stack = []
- const res = [];
- // 遍历搜索
- (function traversal (nodes, path) {
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i]
- if (node.type === 'text' && key) {
- const arr = node.text.split(key)
- const children = []
- if (arr.length > 1) {
- // 找到关键词
- for (let j = 0; j < arr.length; j++) {
- if (arr[j]) {
- children.push({
- type: 'text',
- text: arr[j]
- })
- }
- if (j !== arr.length - 1) {
- // 关键词转为一个 span
- res.push(`${path}[${i}].children[${children.length}].attrs.style`)
- children.push({
- name: 'span',
- attrs: {
- id: anchor ? 'search' + res.length : undefined, // 用于锚点的 id
- style
- },
- children: [{
- type: 'text',
- text: key instanceof RegExp ? key.exec(node.text)[0] : key
- }]
- })
- }
- }
- if (key instanceof RegExp) {
- key.exec(node.text)
- }
- if (anchor) {
- for (let l = stack.length; l--;) {
- // 给父组件做标记,将该标签暴露出来
- if (stack[l].c) {
- break
- } else {
- obj[stack[l].path] = 1
- }
- }
- }
- obj[`${path}[${i}]`] = {
- name: 'span',
- c: anchor ? 1 : undefined,
- s: 1,
- children
- }
- }
- } else if (node.s) {
- let text = ''
- // 复原上一次的结果
- for (let k = 0; k < node.children.length; k++) {
- const child = node.children[k]
- if (child.text) {
- text += child.text
- } else {
- text += child.children[0].text
- }
- }
- nodes[i] = {
- type: 'text',
- text
- }
- if (key && (key instanceof RegExp ? key.test(text) : text.includes(key))) {
- i--
- } else {
- obj[`${path}[${i}]`] = nodes[i]
- }
- } else if (node.children) {
- stack.push({
- path: `${path}[${i}].c`,
- c: node.c || node.name === 'table'
- })
- traversal(node.children, `${path}[${i}].children`)
- stack.pop()
- }
- }
- })(vm.data.nodes, 'nodes')
- return new Promise(function (resolve) {
- vm.setData(obj, () => {
- resolve({
- num: res.length, // 结果数量
- /**
- * @description 高亮某一个结果
- * @param {number} i 第几个
- * @param {string} hlstyle 高亮的样式
- */
- highlight (i, hlstyle = 'background-color:#FF9632') {
- if (i < 1 || i > res.length) return
- const obj = {}
- if (this.last) {
- obj[res[this.last - 1]] = style
- }
- this.last = i
- obj[res[i - 1]] = hlstyle
- vm.setData(obj)
- },
- /**
- * @description 跳转到搜索结果
- * @param {number} i 第几个
- * @param {number} offset 偏移量
- */
- jump: anchor
- ? (i, offset) => {
- if (i > 0 && i <= res.length) {
- vm.navigateTo('search' + i, offset)
- }
- }
- : undefined
- })
- })
- })
- }
- }
- module.exports = Search
|