global-text-processor.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. this.autoSelect('operation-btns')
  108. this.autoSelect('list-display-control-view')
  109. })
  110. },
  111. methods: {
  112. autoSelect(name) {
  113. document.querySelectorAll(`.${name}`).forEach(element => {
  114. this.processAbsolutely(element)
  115. })
  116. },
  117. processTextNodes(el) {
  118. // 遍历子节点并处理文本内容
  119. if (el.nodeType === Node.ELEMENT_NODE) {
  120. // 跳过 table-body中的td 元素
  121. if (el.nodeName.toLowerCase() === 'td') {
  122. return
  123. }
  124. Array.from(el.childNodes).forEach(child => {
  125. if (child.nodeType === Node.TEXT_NODE) {
  126. let text = child.textContent
  127. let _child = child
  128. if (text && !isNumberRegex(text.trim())) {
  129. try {
  130. if (window?.Vue_Translation_Of_Text_Data?.[text.trim()]) {
  131. child.textContent = window?.Vue_Translation_Of_Text_Data?.[text.trim()]
  132. } else if (text.trim()) {
  133. deferredReplacement(text.trim(), function () {
  134. if (window.Vue_Translation_Of_Text_Data[text.trim()]) {
  135. _child.textContent = window.Vue_Translation_Of_Text_Data[text.trim()]
  136. }
  137. })
  138. }
  139. } catch (error) {}
  140. }
  141. } else if (child.nodeName === 'INPUT' || child.nodeName === 'TEXTAREA' || child.nodeName === 'SELECT') {
  142. // 修改输入框和下拉框的 placeholder 内容
  143. let placeholder = child.getAttribute('placeholder')
  144. let _child = child
  145. if (placeholder && !isNumberRegex(placeholder.trim())) {
  146. try {
  147. if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
  148. child.setAttribute('placeholder', window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + ''])
  149. } else if (placeholder.trim() + '') {
  150. deferredReplacement(placeholder.trim() + '', function () {
  151. if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
  152. _child.setAttribute(
  153. 'placeholder',
  154. window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']
  155. )
  156. }
  157. })
  158. }
  159. } catch (error) {}
  160. }
  161. } else if (child?.classList?.contains?.('el-select')) {
  162. // 处理 class 为 el-select 的组件
  163. this.processSelect(child)
  164. } else {
  165. // 递归处理子节点
  166. this.processTextNodes(child)
  167. }
  168. })
  169. }
  170. },
  171. processSelect(el) {
  172. // 遍历子节点并处理文本内容
  173. if (el.nodeType === Node.ELEMENT_NODE) {
  174. Array.from(el.childNodes).forEach(child => {
  175. if (child.nodeName === 'INPUT') {
  176. // 修改输入框和下拉框的 placeholder 内容
  177. let value = child.value
  178. let _child = child
  179. if (value && !isNumberRegex(value.trim())) {
  180. try {
  181. if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
  182. child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
  183. } else if (value.trim() + '') {
  184. deferredReplacement(value.trim() + '', function () {
  185. if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
  186. _child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
  187. }
  188. })
  189. }
  190. } catch (error) {}
  191. }
  192. } else {
  193. // 递归处理子节点
  194. this.processSelect(child)
  195. }
  196. })
  197. }
  198. },
  199. processAbsolutely(el) {
  200. // 遍历子节点并处理文本内容
  201. if (el.nodeType === Node.ELEMENT_NODE) {
  202. Array.from(el.childNodes).forEach(child => {
  203. if (child.nodeType === Node.TEXT_NODE) {
  204. let text = child.textContent
  205. let _child = child
  206. if (text && !isNumberRegex(text.trim())) {
  207. try {
  208. if (window?.Vue_Translation_Of_Text_Data?.[text.trim()]) {
  209. child.textContent = window?.Vue_Translation_Of_Text_Data?.[text.trim()]
  210. } else if (text.trim()) {
  211. deferredReplacement(text.trim(), function () {
  212. if (window.Vue_Translation_Of_Text_Data[text.trim()]) {
  213. _child.textContent = window.Vue_Translation_Of_Text_Data[text.trim()]
  214. }
  215. })
  216. }
  217. } catch (error) {}
  218. }
  219. } else {
  220. // 递归处理子节点
  221. this.processAbsolutely(child)
  222. }
  223. })
  224. }
  225. }
  226. }
  227. })
  228. }
  229. }
  230. export function translaBeforeRegistration(cb) {
  231. window.Vue_Translation_Of_Text_Type = window.localStorage.getItem('Vue_Translation_Of_Text_Type')
  232. if (window?.Vue_Translation_Of_Text_Type && ['en', 'ar', 'ru', 'ja'].includes(window?.Vue_Translation_Of_Text_Type)) {
  233. Vue.use(GlobalTextProcessor) // 注册插件
  234. axios
  235. .post(WindowsTranslateApi + '/api/v1/common/readTranslationOfText', {
  236. targetLanguage: window?.Vue_Translation_Of_Text_Type
  237. })
  238. .then(({ data }) => {
  239. var obj = {}
  240. var obj2 = {}
  241. data?.data?.map(item => {
  242. obj[item.source] = item.target
  243. obj2[item.target] = true
  244. })
  245. window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 }
  246. window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj }
  247. cb?.()
  248. })
  249. .catch(error => {
  250. cb?.()
  251. })
  252. } else {
  253. cb?.()
  254. }
  255. }