str.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. export function isRegExp (value) {
  2. return Object.prototype.toString.call(value) === '[object RegExp]'
  3. }
  4. /**
  5. * 通用关键字高亮替换
  6. * @param {String} value 要高亮的字符串
  7. * @param {String|Array} oldChar 要被替换的字符串(或数组)
  8. * @param {String|Array} newChar 要替换成的字符串(或数组)
  9. *
  10. * 比如:要将 - `剑鱼标讯工具函数` 字符串中的 `工具` 高亮
  11. * 则此时 value -> `剑鱼标讯工具函数`
  12. * oldChar -> `工具`
  13. * newChar -> `<span class="highlight-text">工具</span>`
  14. *
  15. * 批量高亮-----
  16. * 比如:要将 - `剑鱼标讯工具函数` 字符串中的 `工具` `剑鱼` 高亮
  17. * 则此时 value -> `剑鱼标讯工具函数`批量高亮
  18. * oldChar -> ['工具', '剑鱼']
  19. * newChar -> ['<span class="highlight-text">', '</span>']
  20. *
  21. * 注意:此时newChar为一个长度为2的数组,数组中为高亮标签的起始标签和结束标签
  22. *
  23. */
  24. export function replaceKeyword(
  25. value,
  26. oldChar,
  27. newChar = ['<span class="highlight-text">', '</span>']
  28. ) {
  29. if (!oldChar || !newChar || oldChar === '略') return value
  30. // oldChar的字符串数组
  31. let oldCharArr = []
  32. if (Array.isArray(oldChar)) {
  33. oldCharArr = oldChar.concat()
  34. } else {
  35. oldCharArr.push(oldChar)
  36. }
  37. // 非字符串替换集合
  38. const notStrReplacer = []
  39. for (let i = 0; i < oldCharArr.length; i++) {
  40. if (!oldCharArr[i]) {
  41. continue
  42. } else {
  43. if (isRegExp(oldCharArr[i])) {
  44. // 正则直接替换
  45. // 注意:该正则中必须包含至少一个分组匹配,分组中的内容用来替换
  46. notStrReplacer.push(oldCharArr[i])
  47. oldCharArr[i] = ''
  48. } else {
  49. // 字符串替换
  50. oldCharArr[i] = oldCharArr[i].replace(/([\$\(\)\*\+\.\[\]\?\/\\\^\{\}\|])/g, '\\$1').replace(/\s+/g, '')
  51. // oldCharArr[i] = oldCharArr[i]
  52. // .replace(/([$()*+.[\]?/\\^{}|])/g, '\\$1')
  53. // .replace(/\s+/g, '')
  54. // oldCharArr[i] = oldCharArr[i].replace(/\$/g,"\\$");
  55. // oldCharArr[i] = oldCharArr[i].replace(/\(/g,"\\(");
  56. // oldCharArr[i] = oldCharArr[i].replace(/\)/g,"\\)");
  57. // oldCharArr[i] = oldCharArr[i].replace(/\*/g,"\\*");
  58. // oldCharArr[i] = oldCharArr[i].replace(/\+/g,"\\+");
  59. // oldCharArr[i] = oldCharArr[i].replace(/\./g,"\\.");
  60. // oldCharArr[i] = oldCharArr[i].replace(/\[/g,"\\[");
  61. // oldCharArr[i] = oldCharArr[i].replace(/\]/g,"\\]");
  62. // oldCharArr[i] = oldCharArr[i].replace(/\?/g,"\\?");
  63. // oldCharArr[i] = oldCharArr[i].replace(/\\/g,"\\");
  64. // oldCharArr[i] = oldCharArr[i].replace(/\//g,"\\/");
  65. // oldCharArr[i] = oldCharArr[i].replace(/\^/g,"\\^");
  66. // oldCharArr[i] = oldCharArr[i].replace(/\{/g,"\\{");
  67. // oldCharArr[i] = oldCharArr[i].replace(/\}/g,"\\}");
  68. // oldCharArr[i] = oldCharArr[i].replace(/\|/g,"\\|");
  69. }
  70. }
  71. }
  72. // 数组去空
  73. let lastArr = oldCharArr
  74. .filter((item) => !!item)
  75. .sort((a, b) => b.length - a.length)
  76. // 数组去重
  77. lastArr = Array.from(new Set(lastArr))
  78. if (lastArr.length === 0 && notStrReplacer.length === 0) {
  79. return value
  80. }
  81. if (notStrReplacer.length) {
  82. for (let j = 0; j < notStrReplacer.length; j++) {
  83. // 正则替换
  84. value = value.replace(notStrReplacer[j], newChar)
  85. }
  86. }
  87. const regExp = new RegExp(`(${lastArr.join('|')})`, 'gmi')
  88. if (Array.isArray(newChar)) {
  89. // 批量高亮
  90. return value.replace(regExp, newChar.join('$1'))
  91. } else {
  92. // 普通单个高亮
  93. return value.replace(regExp, newChar)
  94. }
  95. }
  96. /**
  97. * 富文本高亮专用替换,用于指定关键词包裹高亮,使用dom解析避免HTML标签被影响
  98. * @param htmlString - String
  99. * @param keyword - String
  100. * @param richChar - String $1
  101. */
  102. export function replaceKeywordWithRichText (
  103. htmlString,
  104. keyword,
  105. richChar = '<span class="highlight-text">$1</span>',
  106. skipClassName = ['highlight-text']
  107. ) {
  108. if (!keyword || !richChar || keyword === '略') return htmlString
  109. // 创建一个临时的DOM元素来解析HTML字符串
  110. const tempDiv = document.createElement('div')
  111. tempDiv.innerHTML = htmlString
  112. // 格式化需要替换的富文本
  113. const richString = richChar.replace(/\$1/g, keyword)
  114. const richTextNode = document.createElement('div')
  115. richTextNode.innerHTML = richString;
  116. function getRichNode () {
  117. return richTextNode.firstChild.cloneNode(true)
  118. }
  119. // 递归函数来遍历DOM节点并替换文本
  120. function replaceText(node) {
  121. if (node.nodeType === Node.TEXT_NODE && node.textContent.includes(keyword)) {
  122. // 创建一个文档片段来存放替换后的富文本和剩余文本
  123. const frag = document.createDocumentFragment()
  124. // 将文本分割为关键词前后的文本,以及替换的富文本
  125. const parts = node.textContent.split(keyword)
  126. for (let i = 0; i < parts.length; i++) {
  127. // 关键词替换为富文本
  128. if (parts.length > 1 && i !== 0) {
  129. frag.appendChild(getRichNode());
  130. }
  131. // 其他文本正常添加
  132. frag.appendChild(document.createTextNode(parts[i]))
  133. }
  134. // 替换原始文本节点
  135. node.parentNode.replaceChild(frag, node)
  136. } else if (node.nodeType === Node.ELEMENT_NODE) {
  137. // 如果是元素节点,递归其子节点
  138. const skip = skipClassName.some(sk => node.className.indexOf(sk) !== -1)
  139. // 跳过已经高亮的元素子节点
  140. if (!skip) {
  141. Array.from(node.childNodes).forEach(replaceText)
  142. }
  143. }
  144. }
  145. // 从临时div开始递归替换文本
  146. replaceText(tempDiv)
  147. // 返回修改后的HTML字符串
  148. return tempDiv.innerHTML
  149. }
  150. /**
  151. * 从key=value&key1=value1&key2=value2...中获取key值
  152. * @param {String} formString 目标字符串,必须为key=value&key1=value1的格式
  153. * @param {String} targetKey 要从目标字符串获取哪个key
  154. * @returns {String}
  155. */
  156. export function getFormValue(formString, targetKey) {
  157. let reg = new RegExp('(^|&)' + targetKey + '=([^&]*)(&|$)', 'i')
  158. let r = formString.match(reg) //获取url中'?'符后的字符串并正则匹配
  159. let context = ''
  160. if (r != null) context = r[2]
  161. // 释放变量
  162. reg = null
  163. r = null
  164. return context == null || context == '' || context == 'undefined' ? '' : context
  165. }
  166. /**
  167. * 从url中获取对应name的参数
  168. * @param {String} name
  169. * @returns {String}
  170. */
  171. export function getQueryParam(name) {
  172. const search = window.location.search
  173. let target = ''
  174. if (search) {
  175. const arr = search.split('?')
  176. if (arr[1]) {
  177. target = arr[1]
  178. }
  179. }
  180. const value = getFormValue(target, name)
  181. return decodeURIComponent(value)
  182. }