Explorar el Código

feature: 国际化修改

ljc hace 7 meses
padre
commit
419eaa8787

+ 1 - 0
package.json

@@ -25,6 +25,7 @@
     "clipboard": "^2.0.10",
     "codemirror": "^5.65.9",
     "core-js": "^3.6.5",
+    "crypto-js": "^4.2.0",
     "dayjs": "^1.11.4",
     "echarts": "^5.3.1",
     "element-plus": "^2.2.28",

+ 10 - 2
src/App.vue

@@ -1,18 +1,26 @@
 <template>
   <el-config-provider :size="globalComSize" :locale="zhCn">
-    <router-view></router-view>
+    <router-view v-if="isRouterAlive"></router-view>
   </el-config-provider>
 </template>
 
 <script lang="ts" setup>
-  import { computed } from 'vue'
+  import { computed, provide, nextTick } from 'vue'
   import { useSettingStore } from '@/store/modules/setting'
   // 配置element中文
   import zhCn from 'element-plus/es/locale/lang/zh-cn'
 
+  let isRouterAlive = true
   const SettingStore = useSettingStore()
   // 配置全局组件大小
   const globalComSize = computed((): string => SettingStore.themeConfig.globalComSize)
+  const reload = () => {
+    isRouterAlive = false
+    nextTick(function () {
+      isRouterAlive = true
+    })
+  }
+  provide('reload', reload)
 </script>
 
 <style lang="scss">

+ 124 - 0
src/assets/css/default.scss

@@ -0,0 +1,124 @@
+/* component style */
+.vue-slider-disabled {
+  opacity: 0.5;
+  cursor: not-allowed;
+}
+
+/* rail style */
+.vue-slider-rail {
+  background-color: #ccc;
+  border-radius: 15px;
+}
+
+/* process style */
+.vue-slider-process {
+  background-color: #3498db;
+  border-radius: 15px;
+}
+
+/* mark style */
+.vue-slider-mark {
+  z-index: 4;
+}
+.vue-slider-mark:first-child .vue-slider-mark-step, .vue-slider-mark:last-child .vue-slider-mark-step {
+  display: none;
+}
+.vue-slider-mark-step {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  background-color: rgba(0, 0, 0, 0.16);
+}
+.vue-slider-mark-label {
+  font-size: 14px;
+  white-space: nowrap;
+}
+/* dot style */
+.vue-slider-dot-handle {
+  cursor: pointer;
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  background-color: #fff;
+  box-sizing: border-box;
+  box-shadow: 0.5px 0.5px 2px 1px rgba(0, 0, 0, 0.32);
+}
+.vue-slider-dot-handle-focus {
+  box-shadow: 0px 0px 1px 2px rgba(52, 152, 219, 0.36);
+}
+
+.vue-slider-dot-handle-disabled {
+  cursor: not-allowed;
+  background-color: #ccc;
+}
+
+.vue-slider-dot-tooltip-inner {
+  font-size: 14px;
+  white-space: nowrap;
+  padding: 2px 5px;
+  min-width: 20px;
+  text-align: center;
+  color: #fff;
+  border-radius: 5px;
+  border-color: #3498db;
+  background-color: #3498db;
+  box-sizing: content-box;
+}
+.vue-slider-dot-tooltip-inner::after {
+  content: "";
+  position: absolute;
+}
+.vue-slider-dot-tooltip-inner-top::after {
+  top: 100%;
+  left: 50%;
+  transform: translate(-50%, 0);
+  height: 0;
+  width: 0;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px;
+  border-top-color: inherit;
+}
+.vue-slider-dot-tooltip-inner-bottom::after {
+  bottom: 100%;
+  left: 50%;
+  transform: translate(-50%, 0);
+  height: 0;
+  width: 0;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px;
+  border-bottom-color: inherit;
+}
+.vue-slider-dot-tooltip-inner-left::after {
+  left: 100%;
+  top: 50%;
+  transform: translate(0, -50%);
+  height: 0;
+  width: 0;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px;
+  border-left-color: inherit;
+}
+.vue-slider-dot-tooltip-inner-right::after {
+  right: 100%;
+  top: 50%;
+  transform: translate(0, -50%);
+  height: 0;
+  width: 0;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px;
+  border-right-color: inherit;
+}
+
+.vue-slider-dot-tooltip-wrapper {
+  opacity: 0;
+  transition: all 0.3s;
+}
+.vue-slider-dot-tooltip-wrapper-show {
+  opacity: 1;
+}
+
+/*# sourceMappingURL=default.css.map */

BIN
src/assets/theme/fonts/element-icons.ttf


BIN
src/assets/theme/fonts/element-icons.woff


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/assets/theme/index.scss


+ 71 - 0
src/config/index.ts

@@ -1,2 +1,73 @@
 // * 默认主题颜色
 export const PRIMARY_COLOR = '#409eff'
+/**
+ * 开发环境配置
+ * Host 服务器地址
+ */
+// 8.210.194.53
+// 139.99.63.178
+// 145.239.1.65   cwgchinese
+//103.148.59.49:18500
+//193.134.208.230
+
+const ht = window.location.protocol
+const ho = window.location.host.split('.')[1]
+const c = import.meta.env.VITE_APP_ENV
+let Host00, Host85
+switch (c) {
+  // 测试环境
+  case 'test':
+    Host00 = ht + '//secure.' + ho + '.com'
+    Host85 = ht + '//ad.' + ho + '.com'
+    break
+  // 生产环境
+  case 'production':
+    Host00 = ht + '//secure.' + ho + '.com'
+    Host85 = ht + '//ad.' + ho + '.com'
+    break
+
+  default:
+    // 开发环境
+    Host00 = 'http://103.214.175.29:8000'
+    Host85 = 'http://103.171.34.61:8500'
+    Host85 = 'http://192.168.0.18:8500'
+    break
+}
+const config = {
+  Host00,
+  Host85,
+  Host80: ht + '//secure.' + ho + '.com',
+  Code: {
+    StatusOK: 200,
+    StatusFail: 400,
+    StatusSessionExpire: 600,
+    StatusSNotFound: 404,
+  },
+  Pattern: {
+    Email: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/,
+    Password:
+      /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([~!@&%$^\\(\\)#_]).*\\1.*\\1.*\\1)[A-Za-z0-9~!@&%$^\\(\\)#_]{8,16}$/,
+    Password1: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,15}$/,
+    Phone: /^1(3|4|5|6|7|8|9)\d{9}$/,
+    Tel: /^[0][1-9]{2,3}-[0-9]{5,10}$/,
+    Num: /\d/,
+    NonNegInt: /^[0-9]+?$/, //非负整数
+    PosInt: /^[1-9]\d*$/, //正整数
+    nonnegative: /^[0-9]+([.]{1}[0-9]{1,2})?$/, //非负数(最多两位小数)
+    englishName: /^[^\u4e00-\u9fa5]+$/,
+  },
+}
+
+// const dev = {
+//   Host: "http://47.75.159.72:8000"
+// }
+// const build = {
+//   Host: "http://192.168.2.2"
+// }
+//
+// if (process.env.NODE_ENV == 'dev') {
+//   config.Host = dev.Host
+// } else {
+//   config.Host = build.Host
+// }
+export default config

+ 1 - 1
src/i18n/index.ts

@@ -11,7 +11,6 @@ function LocaleLanguage() {
 
   // 如果没有存储的语言设置,则使用浏览器语言
   let lang = 'cn'
-  console.log(navigator, 'lanaa')
   if (navigator.languages.includes('zh')) {
     lang = 'cn'
   } else if (!navigator.languages.includes('zh')) {
@@ -30,6 +29,7 @@ function LocaleLanguage() {
 const i18n = createI18n({
   locale: LocaleLanguage(),
   fallbackLocale: import.meta.env.VITE_APP_I18N_FALLBACK_LOCALE || 'cn',
+  globalInjection: true,
   messages: {
     en,
     zh: cn,

+ 2 - 8
src/layout/components/Header/ToolRight.vue

@@ -1,21 +1,15 @@
 <template>
   <div class="m-tool-right">
-    <GlobalComSize class="item-children" />
-    <HeaderSearch class="item-children" />
-    <Remind class="item-children" />
+    <Language class="item-children" />
     <ScreenFull class="item-children" />
-    <Setting class="item-children" />
     <Avatar />
   </div>
 </template>
 
 <script lang="ts" setup>
-  import GlobalComSize from './components/globalComSize.vue'
-  import HeaderSearch from './components/HeaderSearch.vue'
-  import Remind from './components/Remind.vue'
   import ScreenFull from './components/ScreenFull.vue'
-  import Setting from './components/Setting.vue'
   import Avatar from './components/Avatar.vue'
+  import Language from './components/Language.vue'
 </script>
 
 <style lang="scss" scoped>

+ 0 - 1
src/layout/components/Header/components/Avatar.vue

@@ -1,7 +1,6 @@
 <template>
   <el-dropdown>
     <span class="el-dropdown-link">
-      <el-avatar :size="30" class="avatar" :src="AvatarLogo" />
       {{ userInfo.username }}
       <el-icon class="header-icon el-icon--right">
         <arrow-down />

+ 85 - 0
src/layout/components/Header/components/Language.vue

@@ -0,0 +1,85 @@
+<template>
+  <div class="m-screenful">
+    <el-dropdown trigger="click" class="language">
+      <span class="el-dropdown-link">
+        {{ langName }}
+        <el-icon class="el-icon--right">
+          <arrow-down />
+        </el-icon>
+      </span>
+      <template #dropdown>
+        <el-dropdown-menu>
+          <el-dropdown-item @click="SwitchLanguage('cn')">中文简体</el-dropdown-item>
+          <el-dropdown-item @click="SwitchLanguage('en')">English</el-dropdown-item>
+        </el-dropdown-menu>
+      </template>
+    </el-dropdown>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ArrowDown } from '@element-plus/icons-vue'
+  import axios from 'axios'
+  import { getCurrentInstance, onMounted, inject } from 'vue'
+  const reload = inject('reload')
+  const langs = {
+    cn: '中文简体',
+    en: 'English',
+  }
+  // vue3实例
+  const v3This = getCurrentInstance()
+  //显示语言
+  let langName = ''
+
+  // 切换显示语言
+  const SwitchLanguage = (lang) => {
+    console.log(v3This, 'this')
+    if (lang != v3This.ctx.Session.Get('lang')) {
+      switchLang(lang)
+    }
+  }
+  //修改语言
+  const switchLang = async (lang) => {
+    v3This.ctx.$i18n.locale = lang
+    langName = langs[lang]
+    v3This.ctx.Session.Set('lang', lang)
+    axios.defaults.headers.common['Language'] = sessionStorage.getItem('lang')
+    setTimeout(() => {
+      reload()
+    }, 800)
+  }
+
+  // 初始化显示语言
+  const initLanguage = () => {
+    if (!v3This.ctx.Session.Get('lang')) {
+      v3This.ctx.Session.Set('lang', 'cn')
+    }
+    let lang = v3This.ctx.Session.Get('lang') || 'cn'
+    v3This.ctx.$i18n.locale = lang
+    langName = langs[lang]
+  }
+
+  onMounted(() => {
+    initLanguage()
+  })
+</script>
+
+<style lang="scss" scoped>
+  .m-screenful {
+    display: flex;
+    align-items: center;
+    padding-right: 0;
+    justify-content: center;
+    cursor: pointer;
+    transition: all 0.3s;
+    .language {
+      .el-dropdown-link {
+        background-color: rgba(247, 247, 250, 1);
+        border: none;
+        border-radius: 30px;
+        padding: 6px 20px;
+        cursor: pointer;
+      }
+    }
+  }
+</style>

+ 40 - 0
src/lib/crypt.js

@@ -0,0 +1,40 @@
+/*
+ * @Description: 本地数据加密解密
+ * @Author: sql
+ * @Date: 2018-11-23 20:38:06
+ * @LastEditTime: 2018-11-29 16:14:16
+ */
+import CryptoJs from 'crypto-js'
+
+class CryptToJS {
+  constructor() {
+    this.crypt = CryptoJs
+    this.secret = 'Believe in yourself.'
+  }
+  // 加密内容, 原文
+  Encrypt(text) {
+    return this.crypt.AES.encrypt(text, this.secret).toString()
+  }
+  // 解密,加密内容
+  Decrypt(text) {
+    if (text == null || text.length == 0) {
+      return ''
+    }
+    try {
+      const decrypted = this.crypt.AES.decrypt(text, this.secret)
+      const result = decrypted.toString(CryptoJs.enc.Utf8)
+      // Check if decryption was successful and result is valid UTF-8
+      if (result && result.length > 0) {
+        return result
+      } else {
+        console.warn('Decryption failed or resulted in empty string')
+        return ''
+      }
+    } catch (error) {
+      console.error('Decryption error:', error)
+      return ''
+    }
+  }
+}
+
+export default new CryptToJS()

+ 60 - 0
src/lib/session.js

@@ -0,0 +1,60 @@
+/*
+ * @Description: sessionStorage 封装
+ */
+import crypt from '@/lib/crypt'
+
+class SessionStorage {
+  constructor() {
+    this.Data = sessionStorage
+  }
+
+  // 获取 key中的数据
+  Get(key, flag = false) {
+    let res = null
+    try {
+      if (flag) {
+        res = CryptoJS(this.Data[key])
+      } else {
+        res = this.Data[key]
+      }
+      return this.IsExist(key) ? res : null
+    } catch (error) {
+      console.error(`Error getting session data for key "${key}":`, error)
+      return null
+    }
+  }
+
+  // 更新或创建新数据
+  Set(key, val, flag = false) {
+    let res = null
+    try {
+      if (flag) {
+        res = crypt.Encrypt(String(val))
+      } else {
+        res = String(val)
+      }
+      this.Data[key] = sessionStorage[key] = res
+    } catch (error) {
+      console.error(`Error setting session data for key "${key}":`, error)
+    }
+  }
+
+  // 输出 key 数据
+  Del(key) {
+    this.Data[key] = null
+    sessionStorage.removeItem(key)
+  }
+
+  // key数据是否存在
+  IsExist(key) {
+    return this.Data.getItem(key) ? true : false
+  }
+
+  // 清除所有session
+  Clear() {
+    this.Data = null
+    sessionStorage.clear()
+  }
+}
+
+export default new SessionStorage

+ 11 - 1
src/main.ts

@@ -25,9 +25,19 @@ import '@/assets/iconfont/iconfont.js'
 // 引入国际化
 import i18n from './i18n'
 
+import Config from './config'
+import SessionStorage from './lib/session.js'
+//定义mixin
+const mixins = {
+  created() {
+    this.Session = SessionStorage
+    this.Config = Config
+  },
+}
+
 const app = createApp(App)
 registerElIcons(app)
-
+app.mixin(mixins)
 app.component('SvgIcon', SvgIcon)
 app.component('PageWrapLayout', PageWrapLayout)
 

+ 7 - 1
src/routers/index.ts

@@ -1,4 +1,10 @@
-import { createRouter, createWebHistory, RouteRecordRaw, createWebHashHistory, Router } from 'vue-router'
+import {
+  createRouter,
+  createWebHistory,
+  RouteRecordRaw,
+  createWebHashHistory,
+  Router,
+} from 'vue-router'
 import Layout from '@/layout/index.vue'
 // 扩展继承属性
 interface extendRoute {

+ 11 - 2
src/utils/validate.ts

@@ -16,6 +16,7 @@ export function validUsername(str) {
 }
 
 /**
+ * 验证网址
  * @param {string} url
  * @returns {Boolean}
  */
@@ -26,6 +27,7 @@ export function validURL(url) {
 }
 
 /**
+ * 验证小写字母
  * @param {string} str
  * @returns {Boolean}
  */
@@ -35,6 +37,7 @@ export function validLowerCase(str) {
 }
 
 /**
+ * 验证大写字母
  * @param {string} str
  * @returns {Boolean}
  */
@@ -44,6 +47,7 @@ export function validUpperCase(str) {
 }
 
 /**
+ * 验证是否是字母
  * @param {string} str
  * @returns {Boolean}
  */
@@ -53,6 +57,7 @@ export function validAlphabets(str) {
 }
 
 /**
+ * 验证是否是邮箱
  * @param {string} email
  * @returns {Boolean}
  */
@@ -63,6 +68,7 @@ export function validEmail(email) {
 }
 
 /**
+ * 验证是否是字符串
  * @param {string} str
  * @returns {Boolean}
  */
@@ -74,6 +80,7 @@ export function isString(str) {
 }
 
 /**
+ * 验证是否是数组
  * @param {Array} arg
  * @returns {Boolean}
  */
@@ -91,7 +98,8 @@ export function isArray(arg) {
  */
 export function verifyPhone(val: string) {
   // false: 手机号码不正确
-  if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0|1,5-9]))\d{8}$/.test(val)) return false
+  if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0|1,5-9]))\d{8}$/.test(val))
+    return false
   // true: 手机号码正确
   else return true
 }
@@ -116,7 +124,8 @@ export function verifyTextColor(val: string, text = '', color = 'red') {
  * @returns 返回 true: 身份证正确
  */
 export function verifyIdCard(val: string) {
-  const regx = /(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/
+  const regx =
+    /(^\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(^\d{6}(18|19|20)\d{2}(0\d|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)$)/
   return regx.test(val)
 }
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio