linwenxin 9 bulan lalu
induk
melakukan
5836bb384d
3 mengubah file dengan 346 tambahan dan 101 penghapusan
  1. 252 0
      src/global-text-processor.js
  2. 92 99
      src/main.js
  3. 2 2
      src/pages/mine/index.vue

+ 252 - 0
src/global-text-processor.js

@@ -0,0 +1,252 @@
+import axios from 'axios'
+import Vue from 'vue'
+import { delayPerform } from 'js-perform-lock'
+
+const WindowsTranslateApi = 'https://jiasm.zfire.top/translate'
+// const WindowsTranslateApi = 'http://127.0.0.1:7001'
+
+// 数据过滤校验
+function isNumberRegex(str) {
+  const regexPatterns = [
+    /^\d+$/, // 纯数字
+    /^\d*\.\d+$/, // 浮点数
+    /^([01]\d|2[0-3]):([0-5]\d)$/, // 时间 (HH:MM)
+    /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/, // 时间 (HH:MM:SS)
+    /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/, // 完整时间戳
+    /^[A-Za-z]+$/, // 纯字母
+    /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]+$/, // 字母和数字
+    /^(?=.*[A-Za-z])(?=.*[\p{P}\p{S}])[\p{L}\p{P}\p{S}]+$/u, // 字母和标点符号
+    /^(?=.*\d)(?=.*[\p{P}\p{S}])[\d\p{P}\p{S}]+$/u, // 数字和标点符号
+    /^[\p{P}\s\dA-Za-z]+$/u // 字母、数字和标点符号
+  ]
+  return regexPatterns.some(pattern => pattern.test(str)) || !!window.Vue_Translation_Of_Text_Old_Data[str]
+}
+
+// 文本转译请求
+function pushNewText(data) {
+  return new Promise(function (r, j) {
+    axios
+      .post(WindowsTranslateApi + '/api/v1/common/translationOfText', data)
+      .then(response => {
+        if (response.data.code === 0) {
+          var obj = {}
+          var obj2 = {}
+          response.data.data.map(val => {
+            obj[val[0]] = val[1]
+            obj2[val[1]] = true
+          })
+          window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 }
+          window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj }
+          r({ ...obj })
+        }
+      })
+      .catch(j)
+  })
+}
+
+var deferredReplacement = (function () {
+  var allKeywords = []
+  var keywords = []
+  var zhixingfun = []
+  var index = 0
+  var index2 = 0
+
+  const dInit = new delayPerform(250).refactor(function () {
+    let len = index
+    let len2 = index2
+    let keywords_ = keywords.splice(0, len)
+    let zhixingfun_ = zhixingfun.splice(0, len2)
+    index -= len
+    index2 -= len2
+    if (keywords_.length > 0) {
+      pushNewText({
+        keywords: keywords_,
+        targetLanguage: window?.Vue_Translation_Of_Text_Type
+      }).then(data => {
+        for (var i = 0; i < len2; i++) {
+          zhixingfun_?.[i]?.()
+        }
+      })
+    } else if (zhixingfun_.length > 0) {
+      setTimeout(function () {
+        for (var i = 0; i < len2; i++) {
+          zhixingfun_?.[i]?.()
+        }
+      }, 250)
+    }
+  })
+
+  return function (text, cb) {
+    dInit()
+    if (!allKeywords.includes(text)) {
+      index++
+      allKeywords.push(text)
+      keywords.push(text)
+    }
+    index2++
+    zhixingfun.push(cb)
+  }
+})()
+
+export const GlobalTextProcessor = {
+  install(Vue) {
+    Vue.mixin({
+      updated() {
+        this.$nextTick(() => {
+          this.processTextNodes(this.$el)
+          this.autoSelect('uni-tabbar-bottom')
+        })
+      },
+      methods: {
+        // 通过class修改
+        autoSelect(name) {
+          document.querySelectorAll(`.${name}`).forEach(element => {
+            this.processAbsolutely(element)
+          })
+        },
+        // 通过标签名修改
+        autoHtmlSelect(name) {
+          document.getElementsByTagName(name).forEach(element => {
+            this.processAbsolutely(element)
+          })
+        },
+        processTextNodes(el) {
+          // 遍历子节点并处理文本内容
+          if (el.nodeType === Node.ELEMENT_NODE) {
+            // 跳过 table-body中的td 元素
+            if (el.nodeName.toLowerCase() === 'td') {
+              return
+            }
+            Array.from(el.childNodes).forEach(child => {
+              if (child.nodeType === Node.TEXT_NODE) {
+                let text = child.textContent
+                let _child = child
+                if (text && !isNumberRegex(text.trim())) {
+                  try {
+                    if (window?.Vue_Translation_Of_Text_Data?.[text.trim()]) {
+                      child.textContent = window?.Vue_Translation_Of_Text_Data?.[text.trim()]
+                    } else if (text.trim()) {
+                      deferredReplacement(text.trim(), function () {
+                        if (window.Vue_Translation_Of_Text_Data[text.trim()]) {
+                          _child.textContent = window.Vue_Translation_Of_Text_Data[text.trim()]
+                        }
+                      })
+                    }
+                  } catch (error) {}
+                }
+              } else if (child.nodeName === 'INPUT' || child.nodeName === 'TEXTAREA' || child.nodeName === 'SELECT') {
+                // 修改输入框和下拉框的 placeholder 内容
+                let placeholder = child.getAttribute('placeholder')
+                let _child = child
+                if (placeholder && !isNumberRegex(placeholder.trim())) {
+                  try {
+                    if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
+                      child.setAttribute('placeholder', window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + ''])
+                    } else if (placeholder.trim() + '') {
+                      deferredReplacement(placeholder.trim() + '', function () {
+                        if (window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']) {
+                          _child.setAttribute(
+                            'placeholder',
+                            window?.Vue_Translation_Of_Text_Data?.[placeholder.trim() + '']
+                          )
+                        }
+                      })
+                    }
+                  } catch (error) {}
+                }
+              } else if (child?.classList?.contains?.('el-select')) {
+                // 处理 class 为 el-select 的组件
+                this.processSelect(child)
+              } else {
+                // 递归处理子节点
+                this.processTextNodes(child)
+              }
+            })
+          }
+        },
+        processSelect(el) {
+          // 遍历子节点并处理文本内容
+          if (el.nodeType === Node.ELEMENT_NODE) {
+            Array.from(el.childNodes).forEach(child => {
+              if (child.nodeName === 'INPUT') {
+                // 修改输入框和下拉框的 placeholder 内容
+                let value = child.value
+                let _child = child
+                if (value && !isNumberRegex(value.trim())) {
+                  try {
+                    if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
+                      child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
+                    } else if (value.trim() + '') {
+                      deferredReplacement(value.trim() + '', function () {
+                        if (window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']) {
+                          _child.value = window?.Vue_Translation_Of_Text_Data?.[value.trim() + '']
+                        }
+                      })
+                    }
+                  } catch (error) {}
+                }
+              } else {
+                // 递归处理子节点
+                this.processSelect(child)
+              }
+            })
+          }
+        },
+        processAbsolutely(el) {
+          // 遍历子节点并处理文本内容
+          if (el.nodeType === Node.ELEMENT_NODE) {
+            Array.from(el.childNodes).forEach(child => {
+              if (child.nodeType === Node.TEXT_NODE) {
+                let text = child.textContent
+                let _child = child
+                if (text && !isNumberRegex(text.trim())) {
+                  try {
+                    if (window?.Vue_Translation_Of_Text_Data?.[text.trim()]) {
+                      child.textContent = window?.Vue_Translation_Of_Text_Data?.[text.trim()]
+                    } else if (text.trim()) {
+                      deferredReplacement(text.trim(), function () {
+                        if (window.Vue_Translation_Of_Text_Data[text.trim()]) {
+                          _child.textContent = window.Vue_Translation_Of_Text_Data[text.trim()]
+                        }
+                      })
+                    }
+                  } catch (error) {}
+                }
+              } else {
+                // 递归处理子节点
+                this.processAbsolutely(child)
+              }
+            })
+          }
+        }
+      }
+    })
+  }
+}
+
+export function translaBeforeRegistration(cb) {
+  window.Vue_Translation_Of_Text_Type = window.localStorage.getItem('Vue_Translation_Of_Text_Type')
+  if (window?.Vue_Translation_Of_Text_Type && ['en', 'ar', 'ru', 'ja'].includes(window?.Vue_Translation_Of_Text_Type)) {
+    Vue.use(GlobalTextProcessor) // 注册插件
+    axios
+      .post(WindowsTranslateApi + '/api/v1/common/readTranslationOfText', {
+        targetLanguage: window?.Vue_Translation_Of_Text_Type
+      })
+      .then(({ data }) => {
+        var obj = {}
+        var obj2 = {}
+        data?.data?.map(item => {
+          obj[item.source] = item.target
+          obj2[item.target] = true
+        })
+        window.Vue_Translation_Of_Text_Old_Data = { ...(window.Vue_Translation_Of_Text_Old_Data || {}), ...obj2 }
+        window.Vue_Translation_Of_Text_Data = { ...(window.Vue_Translation_Of_Text_Data || {}), ...obj }
+        cb?.()
+      })
+      .catch(error => {
+        cb?.()
+      })
+  } else {
+    cb?.()
+  }
+}

+ 92 - 99
src/main.js

@@ -1,76 +1,69 @@
 import Vue from 'vue'
 import App from './App'
-import store from "store";
-import uView from "uview-ui";
-Vue.use(uView);
+import store from 'store'
+import uView from 'uview-ui'
+Vue.use(uView)
 
 Vue.config.productionTip = false
 
-import {
-  setStorage,
-  getStorage,
-  removeStorage
-} from "@/common/utils/storage.js"
+import { setStorage, getStorage, removeStorage } from '@/common/utils/storage.js'
 
 // #ifdef H5
 // 解析地址栏参数
 function getQueryVariable(variable) {
   // 从?开始获取后面的所有数据
-  var query = window.location.search.substring(1);
+  var query = window.location.search.substring(1)
   // 从字符串&开始分隔成数组split
-  var vars = query.split('&');
+  var vars = query.split('&')
   // 遍历该数组
   for (var i = 0; i < vars.length; i++) {
     // 从等号部分分割成字符
-    var pair = vars[i].split('=');
+    var pair = vars[i].split('=')
     // 如果第一个元素等于 传进来的参的话 就输出第二个元素
     if (pair[0] == variable) {
-      return (pair[1]);
+      return pair[1]
     }
   }
-  return undefined;
+  return undefined
 }
-if (getQueryVariable("x-token")) {
-  setStorage('token', getQueryVariable("x-token") || '')
+if (getQueryVariable('x-token')) {
+  setStorage('token', getQueryVariable('x-token') || '')
 }
-if (getQueryVariable("openId")) {
-  setStorage('openId', getQueryVariable("openId") || '')
+if (getQueryVariable('openId')) {
+  setStorage('openId', getQueryVariable('openId') || '')
 }
-if (getQueryVariable("username")) {
-  setStorage('name', getQueryVariable("username") || '')
+if (getQueryVariable('username')) {
+  setStorage('name', getQueryVariable('username') || '')
 }
-if (getQueryVariable("useravatar")) {
-  setStorage('avatar', getQueryVariable("useravatar") || '')
+if (getQueryVariable('useravatar')) {
+  setStorage('avatar', getQueryVariable('useravatar') || '')
 }
-if (getQueryVariable("userId")) {
-  setStorage('userId', getQueryVariable("userId") || '')
+if (getQueryVariable('userId')) {
+  setStorage('userId', getQueryVariable('userId') || '')
 }
-if (getQueryVariable("mobile")) {
-  setStorage('mobile', getQueryVariable("mobile") || '')
+if (getQueryVariable('mobile')) {
+  setStorage('mobile', getQueryVariable('mobile') || '')
 }
-if (getQueryVariable("miniProgram")) {
-  setStorage('miniProgram', getQueryVariable("miniProgram") || '')
+if (getQueryVariable('miniProgram')) {
+  setStorage('miniProgram', getQueryVariable('miniProgram') || '')
 }
-if (getQueryVariable("appId")) {
-  setStorage('appId', getQueryVariable("appId") || '')
+if (getQueryVariable('appId')) {
+  setStorage('appId', getQueryVariable('appId') || '')
 }
 
-if (getQueryVariable("miniOpenId")) {
-  setStorage('miniOpenId', getQueryVariable("miniOpenId") || '')
+if (getQueryVariable('miniOpenId')) {
+  setStorage('miniOpenId', getQueryVariable('miniOpenId') || '')
 }
 
-if (getQueryVariable("sharerOpenId")) {
-  setStorage('sharerOpenId', getQueryVariable("sharerOpenId") || '')
+if (getQueryVariable('sharerOpenId')) {
+  setStorage('sharerOpenId', getQueryVariable('sharerOpenId') || '')
 }
 
 // #endif
 
-import {
-  Base64
-} from 'js-base64'
+import { Base64 } from 'js-base64'
 Vue.prototype.$Base64 = Base64
 
-
 import {
   toast,
   successToast,
@@ -88,37 +81,35 @@ import {
   getLocation,
   getAddress,
   getNowDate,
-  getNowDatetime,
-} from "common/utils/common"
-import {
-  navToPage
-} from "common/utils/navPag"
-Vue.prototype.$navToPage = navToPage;
-Vue.prototype.$H5Href = process.env.VUE_APP_HREF;
-Vue.prototype.$toast = toast;
-Vue.prototype.$successToast = successToast;
-Vue.prototype.$showLoading = showLoading;
-Vue.prototype.$tipLoading = tipLoading;
-Vue.prototype.$hideLoading = hideLoading;
-Vue.prototype.$modal = modal;
-Vue.prototype.$tips = tips;
-Vue.prototype.$navPage = navPage;
-Vue.prototype.$redPage = redPage;
-Vue.prototype.$backPage = backPage;
-Vue.prototype.$callPhone = callPhone;
-Vue.prototype.$copy = copy;
-Vue.prototype.$openLocation = openLocation;
-Vue.prototype.$getLocation = getLocation;
-Vue.prototype.$getAddress = getAddress;
-Vue.prototype.$getNowDate = getNowDate;
-Vue.prototype.$getNowDatetime = getNowDatetime;
-Vue.prototype.$setStorage = setStorage;
-Vue.prototype.$getStorage = getStorage;
-Vue.prototype.$removeStorage = removeStorage;
+  getNowDatetime
+} from 'common/utils/common'
+import { navToPage } from 'common/utils/navPag'
+Vue.prototype.$navToPage = navToPage
+Vue.prototype.$H5Href = process.env.VUE_APP_HREF
+Vue.prototype.$toast = toast
+Vue.prototype.$successToast = successToast
+Vue.prototype.$showLoading = showLoading
+Vue.prototype.$tipLoading = tipLoading
+Vue.prototype.$hideLoading = hideLoading
+Vue.prototype.$modal = modal
+Vue.prototype.$tips = tips
+Vue.prototype.$navPage = navPage
+Vue.prototype.$redPage = redPage
+Vue.prototype.$backPage = backPage
+Vue.prototype.$callPhone = callPhone
+Vue.prototype.$copy = copy
+Vue.prototype.$openLocation = openLocation
+Vue.prototype.$getLocation = getLocation
+Vue.prototype.$getAddress = getAddress
+Vue.prototype.$getNowDate = getNowDate
+Vue.prototype.$getNowDatetime = getNowDatetime
+Vue.prototype.$setStorage = setStorage
+Vue.prototype.$getStorage = getStorage
+Vue.prototype.$removeStorage = removeStorage
 
 // 注入全局
-import pages from 'mixins';
-Vue.mixin(pages);
+import pages from 'mixins'
+Vue.mixin(pages)
 
 App.mpType = 'app'
 
@@ -136,30 +127,23 @@ Vue.prototype.$onLaunched = new Promise((resolve, reject) => {
   Vue.prototype.$isReject = reject
 })
 
-import custom from '@/components/custom.vue';
-import Loading from '@/components/Loading.vue';
-import zjPageLayout from "@/components/zj-container/zj-page-layout.vue"
-Vue.component('custom', custom);
-Vue.component('Loading', Loading);
-Vue.component('zjPageLayout', zjPageLayout);
+import custom from '@/components/custom.vue'
+import Loading from '@/components/Loading.vue'
+import zjPageLayout from '@/components/zj-container/zj-page-layout.vue'
+Vue.component('custom', custom)
+Vue.component('Loading', Loading)
+Vue.component('zjPageLayout', zjPageLayout)
 
-import floatButton from '@/components/floatButton.vue';
+import floatButton from '@/components/floatButton.vue'
 Vue.component('floatButton', floatButton)
 
-import {
-  getUserInfo,
-  getConfigInfo,
-  getTemplateInfo,
-} from "@/common/utils/util.js";
-Vue.prototype.$getUserInfo = getUserInfo;
-Vue.prototype.$getConfigInfo = getConfigInfo;
-Vue.prototype.$getTemplateInfo = getTemplateInfo;
+import { getUserInfo, getConfigInfo, getTemplateInfo } from '@/common/utils/util.js'
+Vue.prototype.$getUserInfo = getUserInfo
+Vue.prototype.$getConfigInfo = getConfigInfo
+Vue.prototype.$getTemplateInfo = getTemplateInfo
 
 // #ifdef H5
-import {
-  router,
-  RouterMount
-} from 'router'
+import { router, RouterMount } from 'router'
 Vue.use(router)
 import Mylink from 'uni-simple-router/dist/link.vue'
 // 组件式导航
@@ -167,18 +151,27 @@ Vue.component('my-link', Mylink)
 // #endif
 
 // 渲染图片文件
-Vue.prototype.$imageUrl = process.env.VUE_APP_BASE_URL + process.env.VUE_APP_BASE_API + '/common/img/get?key=';
-
-const app = new Vue({
-  ...App,
-  store
+Vue.prototype.$imageUrl = process.env.VUE_APP_BASE_URL + process.env.VUE_APP_BASE_API + '/common/img/get?key='
+
+import { translaBeforeRegistration } from './global-text-processor' // 导入插件
+Vue.prototype.$setLanguage = function (type) {
+  window.localStorage.setItem('Vue_Translation_Of_Text_Type', type)
+  setTimeout(() => {
+    location.reload(true)
+  }, 200)
+}
+translaBeforeRegistration(function () {
+  const app = new Vue({
+    ...App,
+    store
+  })
+
+  //v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
+  // #ifdef H5
+  RouterMount(app, router, '#app')
+  // #endif
+
+  // #ifndef H5
+  app.$mount() //为了兼容小程序及app端必须这样写才有效果
+  // #endif
 })
-
-//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
-// #ifdef H5
-RouterMount(app, router, '#app')
-// #endif
-
-// #ifndef H5
-app.$mount(); //为了兼容小程序及app端必须这样写才有效果
-// #endif

+ 2 - 2
src/pages/mine/index.vue

@@ -99,7 +99,7 @@
             </view>
           </view>
 
-          <view class="order-container card">
+          <!-- <view class="order-container card">
             <view class="home-title">
               <view class="left">我的订单</view>
               <view class="right" @tap="navToPage('/packageMine/pages/order/list?tab=', 1)">
@@ -121,7 +121,7 @@
                 <view class="title">{{ item.title }}</view>
               </view>
             </view>
-          </view>
+          </view> -->
 
           <view class="menu-container card">
             <view class="home-title">