Explorar o código

feat: index.html添加白屏loading;i18n添加空数据组件对应文字;fix页面修改后语言设置不生效问题

ext.zhangbin71 hai 2 semanas
pai
achega
07653572e8
Modificáronse 5 ficheiros con 117 adicións e 57 borrados
  1. 41 1
      index.html
  2. 1 0
      src/locales/en.js
  3. 1 0
      src/locales/zh-CN.js
  4. 31 15
      src/main.js
  5. 43 41
      src/pinia/langStore.js

+ 41 - 1
index.html

@@ -16,7 +16,47 @@
     <link href="/quill/quill.bubble.css" rel="stylesheet">
   </head>
   <body>
-    <div id="app"></div>
+    <!-- 初始加载占位(避免白屏闪烁) -->
+    <div id="app">
+      <div id="app-loading" style="
+        position: fixed;
+        inset: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: #ffffff;
+        z-index: 9999;
+        transition: opacity 0.3s ease;
+      ">
+        <div style="text-align: center;">
+          <div style="
+            width: 40px;
+            height: 40px;
+            border: 3px solid #e2e8f0;
+            border-top-color: #3b82f6;
+            border-radius: 50%;
+            animation: spin 0.8s linear infinite;
+            margin: 0 auto 12px;
+          "></div>
+          <div style="font-size: 14px; color: #94a3b8; font-family: sans-serif;">Loading...</div>
+        </div>
+      </div>
+    </div>
+    <style>
+      @keyframes spin {
+        to { transform: rotate(360deg); }
+      }
+    </style>
+    <script>
+      // 应用挂载后移除加载动画
+      window.__removeLoading = function() {
+        const el = document.getElementById('app-loading');
+        if (el) {
+          el.style.opacity = '0';
+          setTimeout(() => el.remove(), 300);
+        }
+      };
+    </script>
     <script type="module" src="/src/main.js"></script>
   </body>
 </html>

+ 1 - 0
src/locales/en.js

@@ -71,6 +71,7 @@ export default {
     reject: 'Reject',
     viewHomepage: 'View Homepage',
     empty:'No data available',
+    noData: 'No Data',
     all: 'All',
     studyStage: 'Study Stage',
     courseCategory: 'Course Category',

+ 1 - 0
src/locales/zh-CN.js

@@ -76,6 +76,7 @@ export default {
     reject: '拒绝',
     viewHomepage: '查看主页',
     empty:'暂无数据',
+    noData: '暂无数据',
     all: '全部',
     studyStage: '学习阶段',
     courseCategory: '教程分类',

+ 31 - 15
src/main.js

@@ -1,39 +1,55 @@
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'
+import { useLangStore } from '@/pinia/langStore'
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
 import router from './router'
-// import './styles/index.scss'
 import App from './App.vue'
-import i18n from './i18n' // 导入i18n配置
+import i18n from './i18n'
 // 导入自定义消息工具
 import message from './utils/message'
 // 导入全局样式(Tailwind CSS)
 import './styles/tailwind.css'
 
 const app = createApp(App)
-app.use(createPinia())
+const pinia = createPinia()
+app.use(pinia)
 
+const langStore = useLangStore()
+langStore.initializeLang()
 
-// 如果您正在使用CDN引入,请删除下面一行。
-import * as ElementPlusIconsVue from '@element-plus/icons-vue'
-import Breadcrumb from '@/components/Breadcrumb.vue'
-
-
-
-// 注册i18n
+// 注册 i18n
 app.use(i18n)
 
+// 按需注册 Element Plus 图标(仅注册实际使用的图标,减少包体积)
+// 如需全量注册,取消注释以下代码
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
   app.component(key, component)
 }
 
+// 全局注册 Breadcrumb 组件
+import Breadcrumb from '@/components/Breadcrumb.vue'
+app.component('Breadcrumb', Breadcrumb)
 
 app.use(router)
 app.use(ElementPlus)
-// 全局注册 Breadcrumb 组件
-app.component('Breadcrumb', Breadcrumb)
-// 全局注册消息工具
-app.config.globalProperties.$message = message;
 
-app.mount('#app')
+// 全局注册消息工具
+app.config.globalProperties.$message = message
+
+app.mount('#app')
+
+// 动态加载 PayPal SDK(从环境变量读取 client-id)
+// const paypalClientId = import.meta.env.VITE_PAYPAL_CLIENT_ID
+// if (paypalClientId) {
+//   const script = document.createElement('script')
+//   script.src = `https://www.paypal.com/sdk/js?client-id=${paypalClientId}&currency=USD`
+//   script.defer = true
+//   document.head.appendChild(script)
+// }
+
+// 移除初始加载动画
+if (window.__removeLoading) {
+  window.__removeLoading()
+}

+ 43 - 41
src/pinia/langStore.js

@@ -1,52 +1,54 @@
-import { defineStore } from 'pinia'
-import zhCn from 'element-plus/es/locale/lang/zh-cn'
-import en from 'element-plus/es/locale/lang/en'
-import zhMessages from '@/locales/zh-CN.js' // 中文语言包
-import enMessages from '@/locales/en.js'
+import { defineStore } from 'pinia';
+import i18n from '@/i18n'; // 导入 i18n 实例
 
-// 定义localStorage的key
-const LANG_KEY = 'APP_CURRENT_LANG'
+// 导入 Element Plus 语言包
+import zhCn from 'element-plus/es/locale/lang/zh-cn';
+import en from 'element-plus/es/locale/lang/en';
+
+// 语言包映射
 const elLocaleMap = {
   'zh-CN': zhCn,
-  en: en
-}
+  en: en,
+};
+
+const LANG_KEY = 'APP_CURRENT_LANG';
 
-// 默认语言(优先从localStorage读取,没有则用浏览器默认)
-const defaultLang = localStorage.getItem(LANG_KEY) || (navigator.language || 'zh-CN').toLowerCase();
-localStorage.setItem(LANG_KEY, defaultLang)
+const getInitialLang = () => {
+  const savedLang = localStorage.getItem(LANG_KEY);
+  if (savedLang && ['zh-CN', 'en'].includes(savedLang)) {
+    return savedLang;
+  }
+  const browserLang = navigator.language || 'zh-CN';
+  return browserLang.toLowerCase().startsWith('en') ? 'en' : 'zh-CN';
+};
 
 export const useLangStore = defineStore('lang', {
-  state: () => ({
-    // 当前语言
-    currentLang: defaultLang === 'en' ? 'en' : 'zh-CN', // 兼容处理,只保留en/zh-CN
-    elLocale: elLocaleMap[defaultLang === 'en' ? 'en' : 'zh-CN']
-  }),
+  state: () => {
+    const initialLang = getInitialLang();
+    return {
+      currentLang: initialLang,
+      elLocale: elLocaleMap[initialLang],
+    };
+  },
   actions: {
-    // 切换语言
     changeLang(lang) {
-      this.currentLang = lang
-      this.elLocale = elLocaleMap[lang === 'en' ? 'en' : 'zh-CN']
-      // 持久化到localStorage
-      localStorage.setItem(LANG_KEY, lang)
-      
-      // 触发i18n实例的语言切换(后续在i18n配置中关联)
-      if (window.$i18n && window.$i18n.global) {
-        window.$i18n.global.locale.value = lang
-      }
-      window.$i18n.locale = lang
-      console.log('切换到语言:', lang, $i18n)
-      // 动态设置页面标题
-      this.updateDynamicTitle()
+      if (!['zh-CN', 'en'].includes(lang)) return;
+
+      this.currentLang = lang;
+      this.elLocale = elLocaleMap[lang];
+      i18n.global.locale.value = lang; // 正确更新 i18n 实例的 locale
+      localStorage.setItem(LANG_KEY, lang);
+      this.updateDynamicTitle();
     },
-    // 动态更新页面标题
     updateDynamicTitle() {
-      // 从语言包获取网站标题
-      const siteTitle = this.currentLang === 'en' ? enMessages.common.title : zhMessages.common.title;
-      if (siteTitle) {
-        document.title = siteTitle
-      }
+      // 动态更新页面标题
+      document.title = i18n.global.t('common.title');
     },
-    
-   
-  }
-})
+    // 初始化时设置语言
+    initializeLang() {
+      const initialLang = this.currentLang;
+      i18n.global.locale.value = initialLang;
+      this.updateDynamicTitle();
+    }
+  },
+});