物管理前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
5.1 KiB

  1. let allPinyin = []
  2. let notone = {};
  3. let storage = {}
  4. function init(dict) {
  5. // https://github.com/xmflswood/pinyin-match/issues/37
  6. const handledDict = {}
  7. const uv = ['ju','jun','jue','juan','qu','qun','que','xuan','xu','xue','yu','yuan','yue','yun','nve','lve']
  8. // https://github.com/xmflswood/pinyin-match/pull/43
  9. const vList = ['lv', 'lve', 'nv', 'nve']
  10. Object.keys(dict).forEach(key => {
  11. handledDict[key] = dict[key]
  12. allPinyin.push(key)
  13. if (uv.includes(key)) {
  14. const replacedKey = replaceUv(key)
  15. handledDict[replacedKey] = dict[key]
  16. allPinyin.push(replacedKey)
  17. }
  18. if (vList.includes(key)) {
  19. const replacedKey = key.replace('v', 'ü')
  20. handledDict[replacedKey] = dict[key]
  21. allPinyin.push(replacedKey)
  22. }
  23. })
  24. notone = parseDict(handledDict)
  25. return match
  26. }
  27. function replaceUv(str) {
  28. if (str.indexOf('u') !== -1) return str.replace('u', 'v')
  29. return str.replace('v', 'u')
  30. }
  31. function parseDict(dict) {
  32. let parseDict = {}
  33. for (let i in dict) {
  34. let temp = dict[i]
  35. for (let j = 0, len = temp.length; j < len; j++) {
  36. if (!parseDict[temp[j]]) {
  37. parseDict[temp[j]] = i
  38. } else {
  39. parseDict[temp[j]] = parseDict[temp[j]] + ' ' + i
  40. }
  41. }
  42. }
  43. return parseDict
  44. }
  45. function getPinyin(cn) {
  46. let result = []
  47. for (let i = 0, len = cn.length; i < len; i++) {
  48. let temp = cn.charAt(i)
  49. result.push(notone[temp] || temp)
  50. }
  51. return result
  52. }
  53. // 对输入拼音进行切分
  54. function wordBreak(s) {
  55. let result = []
  56. let solutions = []
  57. let len = s.length
  58. let possible = []
  59. for (let i = 0; i <= len; i++) {
  60. possible.push(true)
  61. }
  62. getAllSolutions(0, s, result, solutions, possible)
  63. return solutions
  64. }
  65. function getAllSolutions(start, s, result, solutions, possible) {
  66. let len = s.length
  67. if (start === len) {
  68. solutions.push(result.join(' '))
  69. return
  70. }
  71. for (let i = start; i < len; i++) {
  72. let piece = s.substring(start, i + 1)
  73. let match = false
  74. // 最后一个音特殊处理,不需要全部打完整
  75. if (allPinyin.some(i => i.indexOf(piece) === 0) && !s[i + 1] && possible[i + 1]) {
  76. if (piece.length === 1) {
  77. result.push(piece)
  78. } else {
  79. let s = []
  80. allPinyin.forEach(i => {
  81. if (i.indexOf(piece) === 0) {
  82. s.push(i)
  83. }
  84. })
  85. result.push(s)
  86. }
  87. match = true
  88. } else {
  89. if (allPinyin.indexOf(piece) !== -1 && possible[i + 1]) {
  90. result.push(piece)
  91. match = true
  92. }
  93. }
  94. if (match) {
  95. let beforeChange = solutions.length
  96. getAllSolutions(i + 1, s, result, solutions, possible)
  97. if (solutions.length === beforeChange) {
  98. possible[i + 1] = false
  99. }
  100. result.pop()
  101. }
  102. }
  103. }
  104. // 获取输入拼音的所有组合(切分 + 首字母)
  105. function getFullKey(key) {
  106. let result = []
  107. wordBreak(key).forEach(i => {
  108. let item = i.split(' ')
  109. let last = item.length - 1
  110. if (item[last].indexOf(',')) {
  111. let keys = item[last].split(',')
  112. keys.forEach(j => {
  113. item.splice(last, 1, j)
  114. result.push(JSON.parse(JSON.stringify(item)))
  115. })
  116. } else {
  117. result.push(item)
  118. }
  119. })
  120. if (result.length === 0 || (result[0].length !== key.length)) {
  121. result.push(key.split(''))
  122. }
  123. // 缓存当前结果 避免重复计算
  124. storage = {[key]: result}
  125. return result
  126. }
  127. function point2point(test, key, last, extend) {
  128. if (!test) return false
  129. let a = test.split(' ')
  130. a.forEach(i => {
  131. if (i.length > 0 && extend) {
  132. a.push(i.charAt(0))
  133. }
  134. })
  135. if (!last) {
  136. return a.indexOf(key) !== -1
  137. }
  138. return a.some((i) => i.indexOf(key) === 0)
  139. }
  140. function match(input, keys) {
  141. if (!input || !keys) return false
  142. input = input.toLowerCase()
  143. keys = keys.replace(/\s+/g, '').toLowerCase()
  144. let indexOf = input.indexOf(keys)
  145. if (indexOf !== -1) {
  146. return [indexOf, indexOf + keys.length - 1]
  147. }
  148. // 原文匹配(带空格)
  149. let noPyIndex = getIndex(input.split(''), [keys.split('')], keys)
  150. if (noPyIndex) return noPyIndex
  151. // pinyin匹配
  152. let py = getPinyin(input)
  153. let fullString = storage[keys] || getFullKey(keys)
  154. return getIndex(py, fullString, keys)
  155. }
  156. function getIndex(py, fullString, keys) {
  157. for (let p = 0; p < py.length; p++) {
  158. for (let k = 0; k < fullString.length; k++) {
  159. let key = fullString[k]
  160. let keyLength = key.length
  161. let extend = (keyLength === keys.length)
  162. let isMatch = true
  163. let i = 0
  164. let preSpaceNum = 0
  165. let spaceNum = 0
  166. if (keyLength <= py.length) {
  167. for (; i < key.length; i++) {
  168. if (i === 0 && py[p + i + preSpaceNum] === ' ') {
  169. preSpaceNum += 1
  170. i -= 1
  171. } else {
  172. if (py[p + i + spaceNum] === ' ') {
  173. spaceNum += 1
  174. i -= 1
  175. } else {
  176. if (!point2point(py[p + i + spaceNum], key[i], (py[p + i + 1] && key[i + 1]) ? false : true, extend)) {
  177. isMatch = false
  178. break
  179. }
  180. }
  181. }
  182. }
  183. if (isMatch) {
  184. return [p + preSpaceNum, spaceNum + p + i - 1]
  185. }
  186. }
  187. }
  188. }
  189. return false
  190. }
  191. export default init