global-text-processor.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import axios from 'axios'
  2. import Vue from 'vue'
  3. import { delayPerform } from 'js-perform-lock'
  4. const WindowsTranslateApi = 'https://jiasm.zfire.top/translate'
  5. // const WindowsTranslateApi = 'http://127.0.0.1:7001'
  6. // 数据过滤校验
  7. function isNumberRegex(str) {
  8. const pureNumberRegex = /^\d+$/
  9. const floatNumberRegex = /^\d*\.\d+$/
  10. const timeRegexHHMM = /^([01]\d|2[0-3]):([0-5]\d)$/
  11. const timeRegexHHMMSS = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/
  12. const timeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/
  13. const pureLetterRegex = /^[A-Za-z]+$/
  14. const letterAndDigitRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/
  15. const letterAndPunctuationRegex = /^(?=.*[A-Za-z])(?=.*[\p{P}\p{S}])[\p{L}\p{P}\p{S}]+$/u
  16. const digitAndPunctuationRegex = /^(?=.*\d)(?=.*[\p{P}\p{S}])[\d\p{P}\p{S}]+$/u
  17. if (pureNumberRegex.test(str)) {
  18. return true
  19. } else if (floatNumberRegex.test(str)) {
  20. return true
  21. } else if (timeRegexHHMM.test(str)) {
  22. return true
  23. } else if (timeRegexHHMMSS.test(str)) {
  24. return true
  25. } else if (pureLetterRegex.test(str)) {
  26. return true
  27. } else if (letterAndDigitRegex.test(str)) {
  28. return true
  29. } else if (letterAndPunctuationRegex.test(str)) {
  30. return true
  31. } else if (digitAndPunctuationRegex.test(str)) {
  32. return true
  33. } else if (timeRegex.test(str)) {
  34. return true
  35. } else {
  36. return !!window.Vue_Translation_Of_Text_Old_Data[str]
  37. }
  38. }
  39. // 文本转译请求
  40. function pushNewText(data) {
  41. return new Promise(function (r, j) {
  42. axios
  43. .post(WindowsTranslateApi + '/api/v1/common/translationOfText', data)
  44. .then(response => {
  45. if (response.data.code === 0) {
  46. var obj = {}
  47. var obj2 = {}
  48. response.data.data.map(val => {
  49. obj[val[0]] = val[1]
  50. obj2[val[1]] = true
  51. })
  52. window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 }
  53. window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj }
  54. r({ ...obj })
  55. }
  56. })
  57. .catch(j)
  58. })
  59. }
  60. var deferredReplacement = (function () {
  61. var allKeywords = []
  62. var keywords = []
  63. var zhixingfun = []
  64. var index = 0
  65. var index2 = 0
  66. const dInit = new delayPerform(250).refactor(function () {
  67. let len = index
  68. let len2 = index2
  69. let keywords_ = keywords.splice(0, len)
  70. let zhixingfun_ = zhixingfun.splice(0, len2)
  71. index -= len
  72. index2 -= len2
  73. if (keywords_.length > 0) {
  74. pushNewText({
  75. keywords: keywords_,
  76. targetLanguage: window?.Vue_Translation_Of_Text_Type
  77. }).then(data => {
  78. for (var i = 0; i < len2; i++) {
  79. zhixingfun_?.[i]?.()
  80. }
  81. })
  82. } else if (zhixingfun_.length > 0) {
  83. setTimeout(function () {
  84. for (var i = 0; i < len2; i++) {
  85. zhixingfun_?.[i]?.()
  86. }
  87. }, 250)
  88. }
  89. })
  90. return function (text, cb) {
  91. dInit()
  92. if (!allKeywords.includes(text)) {
  93. index++
  94. allKeywords.push(text)
  95. keywords.push(text)
  96. }
  97. index2++
  98. zhixingfun.push(cb)
  99. }
  100. })()
  101. export const GlobalTextProcessor = {
  102. install(Vue) {
  103. Vue.mixin({
  104. updated() {
  105. this.$nextTick(() => {
  106. this.processTextNodes(this.$el)
  107. })
  108. },
  109. methods: {
  110. processTextNodes(el) {
  111. // 遍历子节点并处理文本内容
  112. if (el.nodeType === Node.ELEMENT_NODE) {
  113. // 跳过 table-body中的td 元素
  114. if (el.nodeName.toLowerCase() === 'td') {
  115. return
  116. }
  117. Array.from(el.childNodes).forEach(child => {
  118. if (child.nodeType === Node.TEXT_NODE) {
  119. let text = child.textContent
  120. let _child = child
  121. if (text && !isNumberRegex(text.trim())) {
  122. try {
  123. if (window?.Vue_Translation_Of_Text_Data?.[text.trim()]) {
  124. child.textContent = window?.Vue_Translation_Of_Text_Data?.[text.trim()]
  125. } else if (text.trim()) {
  126. deferredReplacement(text.trim(), function () {
  127. if (window.Vue_Translation_Of_Text_Data[text.trim()]) {
  128. _child.textContent = window.Vue_Translation_Of_Text_Data[text.trim()]
  129. }
  130. })
  131. }
  132. } catch (error) {}
  133. }
  134. } else if (child.nodeName === 'INPUT' || child.nodeName === 'TEXTAREA' || child.nodeName === 'SELECT') {
  135. // 修改输入框和下拉框的 placeholder 内容
  136. let placeholder = child.getAttribute('placeholder')
  137. let _child = child
  138. if (placeholder && !isNumberRegex(placeholder.trim())) {
  139. try {
  140. if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
  141. child.setAttribute('placeholder', window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + ''])
  142. } else if (placeholder.trim() + '') {
  143. deferredReplacement(placeholder.trim() + '', function () {
  144. if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
  145. _child.setAttribute(
  146. 'placeholder',
  147. window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']
  148. )
  149. }
  150. })
  151. }
  152. } catch (error) {}
  153. }
  154. } else if (child?.classList?.contains?.('el-select')) {
  155. // 处理 class 为 el-select 的组件
  156. this.processSelect(child)
  157. } else {
  158. // 递归处理子节点
  159. this.processTextNodes(child)
  160. }
  161. })
  162. }
  163. },
  164. processSelect(el) {
  165. // 遍历子节点并处理文本内容
  166. if (el.nodeType === Node.ELEMENT_NODE) {
  167. Array.from(el.childNodes).forEach(child => {
  168. if (child.nodeName === 'INPUT') {
  169. // 修改输入框和下拉框的 placeholder 内容
  170. let value = child.value
  171. let _child = child
  172. if (value && !isNumberRegex(value.trim())) {
  173. try {
  174. if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
  175. child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
  176. } else if (value.trim() + '') {
  177. deferredReplacement(value.trim() + '', function () {
  178. if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
  179. _child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
  180. }
  181. })
  182. }
  183. } catch (error) {}
  184. }
  185. } else {
  186. // 递归处理子节点
  187. this.processSelect(child)
  188. }
  189. })
  190. }
  191. }
  192. }
  193. })
  194. }
  195. }
  196. export function translaBeforeRegistration(cb) {
  197. window.Vue_Translation_Of_Text_Type = window.localStorage.getItem('Vue_Translation_Of_Text_Type')
  198. if (window?.Vue_Translation_Of_Text_Type && ['en', 'ar', 'ru', 'ja'].includes(window?.Vue_Translation_Of_Text_Type)) {
  199. Vue.use(GlobalTextProcessor) // 注册插件
  200. axios
  201. .post(WindowsTranslateApi + '/api/v1/common/readTranslationOfText', {
  202. targetLanguage: window?.Vue_Translation_Of_Text_Type
  203. })
  204. .then(({ data }) => {
  205. var obj = {}
  206. var obj2 = {}
  207. data?.data?.map(item => {
  208. obj[item.source] = item.target
  209. obj2[item.target] = true
  210. })
  211. window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 }
  212. window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj }
  213. cb?.()
  214. })
  215. .catch(error => {
  216. cb?.()
  217. })
  218. } else {
  219. cb?.()
  220. }
  221. }