国际化、主题处理

This commit is contained in:
Gary Fu
2023-12-16 21:05:00 +08:00
parent ffb209c494
commit 99629bc0a5
9 changed files with 184 additions and 49 deletions

144
package-lock.json generated
View File

@@ -9,10 +9,12 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
"@vueuse/core": "^10.7.0",
"dayjs": "^1.11.8", "dayjs": "^1.11.8",
"element-plus": "^2.3.4", "element-plus": "^2.3.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.0.32", "pinia": "^2.0.32",
"pinia-plugin-persistedstate": "^3.2.0",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
@@ -635,9 +637,9 @@
} }
}, },
"node_modules/@types/web-bluetooth": { "node_modules/@types/web-bluetooth": {
"version": "0.0.16", "version": "0.0.20",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
}, },
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "4.2.1", "version": "4.2.1",
@@ -778,23 +780,23 @@
"integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ=="
}, },
"node_modules/@vueuse/core": { "node_modules/@vueuse/core": {
"version": "9.13.0", "version": "10.7.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.7.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", "integrity": "sha512-4EUDESCHtwu44ZWK3Gc/hZUVhVo/ysvdtwocB5vcauSV4B7NiGY5972WnsojB3vRNdxvAt7kzJWE2h9h7C9d5w==",
"dependencies": { "dependencies": {
"@types/web-bluetooth": "^0.0.16", "@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "9.13.0", "@vueuse/metadata": "10.7.0",
"@vueuse/shared": "9.13.0", "@vueuse/shared": "10.7.0",
"vue-demi": "*" "vue-demi": ">=0.14.6"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/core/node_modules/vue-demi": { "node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.0", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==", "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -817,28 +819,28 @@
} }
}, },
"node_modules/@vueuse/metadata": { "node_modules/@vueuse/metadata": {
"version": "9.13.0", "version": "10.7.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", "integrity": "sha512-GlaH7tKP2iBCZ3bHNZ6b0cl9g0CJK8lttkBNUX156gWvNYhTKEtbweWLm9rxCPIiwzYcr/5xML6T8ZUEt+DkvA==",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared": { "node_modules/@vueuse/shared": {
"version": "9.13.0", "version": "10.7.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.7.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", "integrity": "sha512-kc00uV6CiaTdc3i1CDC4a3lBxzaBE9AgYNtFN87B5OOscqeWElj/uza8qVDmk7/U8JbqoONLbtqiLJ5LGRuqlw==",
"dependencies": { "dependencies": {
"vue-demi": "*" "vue-demi": ">=0.14.6"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared/node_modules/vue-demi": { "node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.0", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==", "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -1217,6 +1219,94 @@
"vue": "^3.2.0" "vue": "^3.2.0"
} }
}, },
"node_modules/element-plus/node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/element-plus/node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/element-plus/node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.21.2", "version": "1.21.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
@@ -2792,6 +2882,14 @@
} }
} }
}, },
"node_modules/pinia-plugin-persistedstate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.0.tgz",
"integrity": "sha512-tZbNGf2vjAQcIm7alK40sE51Qu/m9oWr+rEgNm/2AWr1huFxj72CjvpQcIQzMknDBJEkQznCLAGtJTIcLKrKdw==",
"peerDependencies": {
"pinia": "^2.0.0"
}
},
"node_modules/pinia/node_modules/vue-demi": { "node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",

View File

@@ -10,10 +10,12 @@
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
"@vueuse/core": "^10.7.0",
"dayjs": "^1.11.8", "dayjs": "^1.11.8",
"element-plus": "^2.3.4", "element-plus": "^2.3.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.0.32", "pinia": "^2.0.32",
"pinia-plugin-persistedstate": "^3.2.0",
"vue": "^3.2.47", "vue": "^3.2.47",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"

View File

@@ -1,9 +1,13 @@
<script setup> <script setup>
import { useGlobalConfigStore } from '@/stores/globalConfig'
import { $changeLocale, elementLocale } from '@/languages/MessagesConfig'
const globalConfigStore = useGlobalConfigStore()
$changeLocale(globalConfigStore.currentLocale)
</script> </script>
<template> <template>
<el-config-provider :locale="$currentLocale.localeData"> <el-config-provider :locale="elementLocale.localeData">
<router-view /> <router-view />
</el-config-provider> </el-config-provider>
</template> </template>

View File

@@ -1,6 +1,11 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { useDark } from '@vueuse/core'
import { Check } from '@element-plus/icons-vue'
import { useGlobalConfigStore } from '@/stores/globalConfig'
const globalConfigStore = useGlobalConfigStore()
const isCollapseLeft = ref(false) const isCollapseLeft = ref(false)
@@ -10,6 +15,8 @@ const updateCollapseLeft = () => {
emit('update:collapseLeft', isCollapseLeft.value) emit('update:collapseLeft', isCollapseLeft.value)
} }
const isDark = useDark()
defineProps({ defineProps({
collapseLeft: { collapseLeft: {
type: Boolean type: Boolean
@@ -41,12 +48,18 @@ defineProps({
index="1-1" index="1-1"
@click="$changeLocale('zh-CN')" @click="$changeLocale('zh-CN')"
> >
<el-icon v-if="globalConfigStore.currentLocale==='zh-CN'">
<Check />
</el-icon>
{{ $t('common.label.langCn') }} {{ $t('common.label.langCn') }}
</el-menu-item> </el-menu-item>
<el-menu-item <el-menu-item
index="1-2" index="1-2"
@click="$changeLocale('en-US')" @click="$changeLocale('en-US')"
> >
<el-icon v-if="globalConfigStore.currentLocale==='en-US'">
<Check />
</el-icon>
{{ $t('common.label.langEn') }} {{ $t('common.label.langEn') }}
</el-menu-item> </el-menu-item>
</el-sub-menu> </el-sub-menu>
@@ -54,15 +67,24 @@ defineProps({
<template #title> <template #title>
{{ $t('common.label.theme') }} {{ $t('common.label.theme') }}
</template> </template>
<el-menu-item index="2-1"> <el-menu-item
index="2-1"
@click="isDark=false"
>
<el-icon v-if="!isDark">
<Check />
</el-icon>
{{ $t('common.label.themeDefault') }} {{ $t('common.label.themeDefault') }}
</el-menu-item> </el-menu-item>
<el-menu-item index="2-2"> <el-menu-item
index="2-2"
@click="isDark=true"
>
<el-icon v-if="isDark">
<Check />
</el-icon>
{{ $t('common.label.themeDark') }} {{ $t('common.label.themeDark') }}
</el-menu-item> </el-menu-item>
<el-menu-item index="2-3">
{{ $t('common.label.themePurple') }}
</el-menu-item>
</el-sub-menu> </el-sub-menu>
<el-sub-menu index="3"> <el-sub-menu index="3">
<template #title> <template #title>

View File

@@ -1,11 +1,12 @@
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import { reactive } from 'vue' import { ref } from 'vue'
import messagesCn from './messages_cn' import messagesCn from './messages_cn'
import messagesEn from './messages_en' import messagesEn from './messages_en'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs' import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import en from 'element-plus/dist/locale/en.mjs' import en from 'element-plus/dist/locale/en.mjs'
import 'dayjs/locale/zh-cn' import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useGlobalConfigStore } from '@/stores/globalConfig'
const DEFAULT_LOCALE = 'zh-CN' const DEFAULT_LOCALE = 'zh-CN'
dayjs.locale(DEFAULT_LOCALE) // dayjs的语言配置 dayjs.locale(DEFAULT_LOCALE) // dayjs的语言配置
@@ -20,20 +21,20 @@ const i18n = createI18n({
} // set locale messages } // set locale messages
}) })
const $currentLocale = reactive({ // 用于element-plus export const elementLocale = ref({ // 用于element-plus
localeData: zhCn localeData: zhCn
}) })
const $changeLocale = function (locale) { export const $changeLocale = function (locale) {
this.$i18n.locale = locale i18n.global.locale.value = locale
this.$currentLocale.localeData = locale === DEFAULT_LOCALE ? zhCn : en elementLocale.value.localeData = locale === DEFAULT_LOCALE ? zhCn : en
dayjs.locale(locale.toLowerCase()) dayjs.locale(locale.toLowerCase())
useGlobalConfigStore().changeLocale(locale)
} }
export default { export default {
install (app) { install (app) {
app.use(i18n) app.use(i18n)
app.config.globalProperties.$currentLocale = $currentLocale
app.config.globalProperties.$changeLocale = $changeLocale app.config.globalProperties.$changeLocale = $changeLocale
} }
} }

View File

@@ -1,8 +1,9 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue' import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { usePinia } from '@/store'
import messagesConfig from '@/languages/MessagesConfig' import messagesConfig from '@/languages/MessagesConfig'
@@ -13,7 +14,7 @@ import './assets/main.css'
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) app.use(usePinia)
app.use(router) app.use(router)
app.use(ElementPlus) app.use(ElementPlus)
app.use(messagesConfig) app.use(messagesConfig)

17
src/store.js Normal file
View File

@@ -0,0 +1,17 @@
import { defineStore, createPinia } from 'pinia'
import piniaPluginPersistedState from 'pinia-plugin-persistedstate'
import { useGlobalConfigStore } from '@/stores/globalConfig'
export const usePinia = {
install (app) {
const pinia = createPinia()
pinia.use(piniaPluginPersistedState)
app.use(pinia)
return pinia
}
}
export const useStore = defineStore('store', () => {
return {
globalConfig: useGlobalConfigStore()
}
})

View File

@@ -1,12 +0,0 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

View File

@@ -7,4 +7,6 @@ export const useGlobalConfigStore = defineStore('globalConfig', () => {
currentLocale.value = locale currentLocale.value = locale
} }
return { currentLocale, changeLocale } return { currentLocale, changeLocale }
}, {
persist: true
}) })