feat: 完成主题切换,语言切换的本地存储

This commit is contained in:
MTrun 2021-12-17 11:55:42 +08:00
parent 7f67f482da
commit 557ddd6ee5
27 changed files with 446 additions and 102 deletions

View File

@ -8,12 +8,13 @@
"lint": "eslint \"{src}/**/*.{vue,ts,tsx}\" --fix --ext" "lint": "eslint \"{src}/**/*.{vue,ts,tsx}\" --fix --ext"
}, },
"dependencies": { "dependencies": {
"@vicons/ionicons5": "^0.11.0", "@vicons/ionicons5": "~0.11.0",
"axios": "^0.23.0", "axios": "^0.23.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"naive-ui": "^2.19.9", "naive-ui": "^2.19.9",
"pinia": "^2.0.6", "pinia": "^2.0.6",
"vue": "^3.2.16", "vue": "^3.2.16",
"vue-i18n": "^9.2.0-beta.23",
"vue-router": "4.0.12" "vue-router": "4.0.12"
}, },
"devDependencies": { "devDependencies": {
@ -23,6 +24,7 @@
"@vitejs/plugin-vue": "^1.9.3", "@vitejs/plugin-vue": "^1.9.3",
"@vitejs/plugin-vue-jsx": "^1.2.0", "@vitejs/plugin-vue-jsx": "^1.2.0",
"@vue/compiler-sfc": "^3.2.20", "@vue/compiler-sfc": "^3.2.20",
"@vueuse/core": "^7.3.0",
"default-passive-events": "^2.0.0", "default-passive-events": "^2.0.0",
"eslint": "^8.4.1", "eslint": "^8.4.1",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",

108
pnpm-lock.yaml generated
View File

@ -4,10 +4,11 @@ specifiers:
'@types/node': ^16.11.1 '@types/node': ^16.11.1
'@typescript-eslint/eslint-plugin': ^5.6.0 '@typescript-eslint/eslint-plugin': ^5.6.0
'@typescript-eslint/parser': ^5.6.0 '@typescript-eslint/parser': ^5.6.0
'@vicons/ionicons5': ^0.11.0 '@vicons/ionicons5': ~0.11.0
'@vitejs/plugin-vue': ^1.9.3 '@vitejs/plugin-vue': ^1.9.3
'@vitejs/plugin-vue-jsx': ^1.2.0 '@vitejs/plugin-vue-jsx': ^1.2.0
'@vue/compiler-sfc': ^3.2.20 '@vue/compiler-sfc': ^3.2.20
'@vueuse/core': ^7.3.0
axios: ^0.23.0 axios: ^0.23.0
default-passive-events: ^2.0.0 default-passive-events: ^2.0.0
eslint: ^8.4.1 eslint: ^8.4.1
@ -28,6 +29,7 @@ specifiers:
vite-plugin-mock: ^2.9.6 vite-plugin-mock: ^2.9.6
vite-plugin-style-import: ^1.2.1 vite-plugin-style-import: ^1.2.1
vue: ^3.2.16 vue: ^3.2.16
vue-i18n: ^9.2.0-beta.23
vue-router: 4.0.12 vue-router: 4.0.12
vue-tsc: ^0.28.7 vue-tsc: ^0.28.7
@ -38,6 +40,7 @@ dependencies:
naive-ui: rg.cnpmjs.org/naive-ui/2.21.5_vue@3.2.24 naive-ui: rg.cnpmjs.org/naive-ui/2.21.5_vue@3.2.24
pinia: rg.cnpmjs.org/pinia/2.0.6_typescript@4.5.2+vue@3.2.24 pinia: rg.cnpmjs.org/pinia/2.0.6_typescript@4.5.2+vue@3.2.24
vue: rg.cnpmjs.org/vue/3.2.24 vue: rg.cnpmjs.org/vue/3.2.24
vue-i18n: rg.cnpmjs.org/vue-i18n/9.2.0-beta.23_vue@3.2.24
vue-router: rg.cnpmjs.org/vue-router/4.0.12_vue@3.2.24 vue-router: rg.cnpmjs.org/vue-router/4.0.12_vue@3.2.24
devDependencies: devDependencies:
@ -47,6 +50,7 @@ devDependencies:
'@vitejs/plugin-vue': rg.cnpmjs.org/@vitejs/plugin-vue/1.10.2_vite@2.7.1 '@vitejs/plugin-vue': rg.cnpmjs.org/@vitejs/plugin-vue/1.10.2_vite@2.7.1
'@vitejs/plugin-vue-jsx': rg.cnpmjs.org/@vitejs/plugin-vue-jsx/1.3.1 '@vitejs/plugin-vue-jsx': rg.cnpmjs.org/@vitejs/plugin-vue-jsx/1.3.1
'@vue/compiler-sfc': rg.cnpmjs.org/@vue/compiler-sfc/3.2.24 '@vue/compiler-sfc': rg.cnpmjs.org/@vue/compiler-sfc/3.2.24
'@vueuse/core': rg.cnpmjs.org/@vueuse/core/7.3.0_vue@3.2.24
default-passive-events: rg.cnpmjs.org/default-passive-events/2.0.0 default-passive-events: rg.cnpmjs.org/default-passive-events/2.0.0
eslint: rg.cnpmjs.org/eslint/8.4.1 eslint: rg.cnpmjs.org/eslint/8.4.1
eslint-config-prettier: rg.cnpmjs.org/eslint-config-prettier/8.3.0_eslint@8.4.1 eslint-config-prettier: rg.cnpmjs.org/eslint-config-prettier/8.3.0_eslint@8.4.1
@ -510,6 +514,54 @@ packages:
version: 1.2.1 version: 1.2.1
dev: true dev: true
rg.cnpmjs.org/@intlify/core-base/9.2.0-beta.23:
resolution: {integrity: sha512-sNet9/RpU/qydW1bOwVICYzGIC/SWyV+1gakcSP12XD1tGEiaoI1Ln+6nHh4dICfegR/5XyaoJ7NC4/ukH7/Ew==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@intlify/core-base/download/@intlify/core-base-9.2.0-beta.23.tgz}
name: '@intlify/core-base'
version: 9.2.0-beta.23
engines: {node: '>= 12'}
dependencies:
'@intlify/devtools-if': rg.cnpmjs.org/@intlify/devtools-if/9.2.0-beta.23
'@intlify/message-compiler': rg.cnpmjs.org/@intlify/message-compiler/9.2.0-beta.23
'@intlify/shared': rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23
'@intlify/vue-devtools': rg.cnpmjs.org/@intlify/vue-devtools/9.2.0-beta.23
dev: false
rg.cnpmjs.org/@intlify/devtools-if/9.2.0-beta.23:
resolution: {integrity: sha512-f2iY2LFRHTwPnBpT0R/kG8CwZbUWiSccMzfXYLwhjJC1irCcFCXmVtL9Mkz5gc0Elqvl+zOWxk5g9rwhah5bBQ==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@intlify/devtools-if/download/@intlify/devtools-if-9.2.0-beta.23.tgz}
name: '@intlify/devtools-if'
version: 9.2.0-beta.23
engines: {node: '>= 12'}
dependencies:
'@intlify/shared': rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23
dev: false
rg.cnpmjs.org/@intlify/message-compiler/9.2.0-beta.23:
resolution: {integrity: sha512-qmGN8k5yGGdZ5St8yg8U4Tg2K9Sc6h3BhWCdJKAqQVs5jnfZG+nMtsLVgnJUWkDvhjzyg7/rEOhHm2uJcu4vjw==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@intlify/message-compiler/download/@intlify/message-compiler-9.2.0-beta.23.tgz}
name: '@intlify/message-compiler'
version: 9.2.0-beta.23
engines: {node: '>= 12'}
dependencies:
'@intlify/shared': rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23
source-map: rg.cnpmjs.org/source-map/0.6.1
dev: false
rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23:
resolution: {integrity: sha512-3aELL2KTp1MWKGm2gIUKSagthgKzcK5hpQEFzOwkJ1SAthpTXR7BHeWGEaD+Lj+Pbiz3U8cspvp8s2lFWVbYxg==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@intlify/shared/download/@intlify/shared-9.2.0-beta.23.tgz}
name: '@intlify/shared'
version: 9.2.0-beta.23
engines: {node: '>= 12'}
dev: false
rg.cnpmjs.org/@intlify/vue-devtools/9.2.0-beta.23:
resolution: {integrity: sha512-5uGvrtUQhiyEqrMpDYh1FAU5uZviLaiEy1HAs+ypX46EdaDvyEYYpWvhezTWZ7hsDBsbsKJ9ICjgTvZxm6PDcw==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@intlify/vue-devtools/download/@intlify/vue-devtools-9.2.0-beta.23.tgz}
name: '@intlify/vue-devtools'
version: 9.2.0-beta.23
engines: {node: '>= 12'}
dependencies:
'@intlify/core-base': rg.cnpmjs.org/@intlify/core-base/9.2.0-beta.23
'@intlify/shared': rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23
dev: false
rg.cnpmjs.org/@jest/types/27.4.2: rg.cnpmjs.org/@jest/types/27.4.2:
resolution: {integrity: sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@jest/types/download/@jest/types-27.4.2.tgz} resolution: {integrity: sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@jest/types/download/@jest/types-27.4.2.tgz}
name: '@jest/types' name: '@jest/types'
@ -1044,6 +1096,43 @@ packages:
name: '@vue/shared' name: '@vue/shared'
version: 3.2.24 version: 3.2.24
rg.cnpmjs.org/@vueuse/core/7.3.0_vue@3.2.24:
resolution: {integrity: sha512-gPJyMMAquva9Qwqz63qGQT122m5hWI8Kuy8kfPV/JLQU7m01CXooyv8FIrX9TV8OxVcHBTPXPJHY0oyUiFoNgw==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@vueuse/core/download/@vueuse/core-7.3.0.tgz}
id: rg.cnpmjs.org/@vueuse/core/7.3.0
name: '@vueuse/core'
version: 7.3.0
peerDependencies:
'@vue/composition-api': ^1.1.0
vue: ^2.6.0 || ^3.2.0
peerDependenciesMeta:
'@vue/composition-api':
optional: true
vue:
optional: true
dependencies:
'@vueuse/shared': rg.cnpmjs.org/@vueuse/shared/7.3.0_vue@3.2.24
vue: rg.cnpmjs.org/vue/3.2.24
vue-demi: rg.cnpmjs.org/vue-demi/0.12.1_vue@3.2.24
dev: true
rg.cnpmjs.org/@vueuse/shared/7.3.0_vue@3.2.24:
resolution: {integrity: sha512-vOAeI84tIXKVkzm8s/Mxbrzhj0QN6NyVc/sC6LrW0AjVNdvpD8sB1dZiDn9yh8T77WJmloCEt4zZVIppeq7I+w==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/@vueuse/shared/download/@vueuse/shared-7.3.0.tgz}
id: rg.cnpmjs.org/@vueuse/shared/7.3.0
name: '@vueuse/shared'
version: 7.3.0
peerDependencies:
'@vue/composition-api': ^1.1.0
vue: ^2.6.0 || ^3.2.0
peerDependenciesMeta:
'@vue/composition-api':
optional: true
vue:
optional: true
dependencies:
vue: rg.cnpmjs.org/vue/3.2.24
vue-demi: rg.cnpmjs.org/vue-demi/0.12.1_vue@3.2.24
dev: true
rg.cnpmjs.org/acorn-jsx/5.3.2_acorn@8.6.0: rg.cnpmjs.org/acorn-jsx/5.3.2_acorn@8.6.0:
resolution: {integrity: sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/acorn-jsx/download/acorn-jsx-5.3.2.tgz} resolution: {integrity: sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/acorn-jsx/download/acorn-jsx-5.3.2.tgz}
id: rg.cnpmjs.org/acorn-jsx/5.3.2 id: rg.cnpmjs.org/acorn-jsx/5.3.2
@ -4260,7 +4349,6 @@ packages:
optional: true optional: true
dependencies: dependencies:
vue: rg.cnpmjs.org/vue/3.2.24 vue: rg.cnpmjs.org/vue/3.2.24
dev: false
rg.cnpmjs.org/vue-eslint-parser/8.0.1_eslint@8.4.1: rg.cnpmjs.org/vue-eslint-parser/8.0.1_eslint@8.4.1:
resolution: {integrity: sha1-JeCLIKQUVRUx8+GfmZkC4ez0XxM=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/vue-eslint-parser/download/vue-eslint-parser-8.0.1.tgz} resolution: {integrity: sha1-JeCLIKQUVRUx8+GfmZkC4ez0XxM=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/vue-eslint-parser/download/vue-eslint-parser-8.0.1.tgz}
@ -4283,6 +4371,22 @@ packages:
- supports-color - supports-color
dev: true dev: true
rg.cnpmjs.org/vue-i18n/9.2.0-beta.23_vue@3.2.24:
resolution: {integrity: sha512-9zpylFVjhMDiNnSpa8pFf/lXiALKzxDKEo9QrSV906cN0m6jtyjvjCWw6dRx/7Q4ZJuwXYg0wi/UtUkgu0wkQw==, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/vue-i18n/download/vue-i18n-9.2.0-beta.23.tgz}
id: rg.cnpmjs.org/vue-i18n/9.2.0-beta.23
name: vue-i18n
version: 9.2.0-beta.23
engines: {node: '>= 12'}
peerDependencies:
vue: ^3.0.0
dependencies:
'@intlify/core-base': rg.cnpmjs.org/@intlify/core-base/9.2.0-beta.23
'@intlify/shared': rg.cnpmjs.org/@intlify/shared/9.2.0-beta.23
'@intlify/vue-devtools': rg.cnpmjs.org/@intlify/vue-devtools/9.2.0-beta.23
'@vue/devtools-api': rg.cnpmjs.org/@vue/devtools-api/6.0.0-beta.20.1
vue: rg.cnpmjs.org/vue/3.2.24
dev: false
rg.cnpmjs.org/vue-router/4.0.12_vue@3.2.24: rg.cnpmjs.org/vue-router/4.0.12_vue@3.2.24:
resolution: {integrity: sha1-jceSzd9bsavMOQj5BkE23n4TxGA=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/vue-router/download/vue-router-4.0.12.tgz} resolution: {integrity: sha1-jceSzd9bsavMOQj5BkE23n4TxGA=, registry: http://r.cnpmjs.org/, tarball: https://rg.cnpmjs.org/vue-router/download/vue-router-4.0.12.tgz}
id: rg.cnpmjs.org/vue-router/4.0.12 id: rg.cnpmjs.org/vue-router/4.0.12

View File

@ -0,0 +1,3 @@
import LangSelect from './index.vue';
export { LangSelect };

View File

@ -0,0 +1,28 @@
<template>
<n-dropdown
trigger="hover"
@select="handleSelect"
:show-arrow="true"
:options="options"
>
<n-button quaternary>
<n-icon size="20" :depth="1">
<LanguageIcon />
</n-icon>
</n-button>
</n-dropdown>
</template>
<script lang="ts" setup>
import { useLangStore } from '@/store/modules/langStore/langStore'
import { Language as LanguageIcon } from '@vicons/ionicons5'
import { langList } from '@/settings/designSetting'
import { LangEnum } from '@/enums/styleEnum'
const langStore = useLangStore()
const options = langList
const handleSelect = (key: LangEnum) => {
langStore.changeLang(key)
}
</script>

View File

@ -1,12 +1,10 @@
<template> <template>
<div>
<n-button quaternary @click="changeTheme"> <n-button quaternary @click="changeTheme">
<n-icon size="20" :depth="1"> <n-icon size="20" :depth="1">
<MoonIcon v-if="designStore.darkTheme" /> <MoonIcon v-if="designStore.darkTheme" />
<SunnyIcon v-else /> <SunnyIcon v-else />
</n-icon> </n-icon>
</n-button> </n-button>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -2,3 +2,8 @@ export enum ThemeEnum {
dark = 'dark', dark = 'dark',
light = 'light' light = 'light'
} }
export enum LangEnum {
zh = 'zh',
en = 'en'
}

12
src/i18n/en/index.ts Normal file
View File

@ -0,0 +1,12 @@
import login from './login'
const global = {
doc_addr: "Doc Address",
form_account: "Please enter your account or email",
form_password: "Please enter your password"
}
export default {
global: global,
login: login
}

7
src/i18n/en/login.ts Normal file
View File

@ -0,0 +1,7 @@
export default {
desc: "Log in to GoView",
form_auto: "Sign in automatically",
form_button: "Login",
login_success: "Login success",
login_message: "Please complete the letter",
}

View File

@ -0,0 +1,20 @@
//语言
import { lang } from '@/settings/designSetting'
import { createI18n } from 'vue-i18n' //引入vue-i18n组件
import { getLocalStorage } from '@/utils/index'
import { GO_LANG_SELECT } from '@/settings/storageConst'
import zh from './zh/index'
import en from './en/index'
const lang_storage = getLocalStorage(GO_LANG_SELECT)
const i18n = createI18n({
locale: lang_storage || lang,
globalInjection: true,
messages: {
zh: zh,
en: en
}
})
export default i18n

12
src/i18n/zh/index.ts Normal file
View File

@ -0,0 +1,12 @@
import login from './login'
const global = {
doc_addr: "文档地址",
form_account: "请输入账号或邮箱",
form_password: "请输入密码",
}
export default {
global: global,
login: login
}

7
src/i18n/zh/login.ts Normal file
View File

@ -0,0 +1,7 @@
export default {
desc: "登录 GoView",
form_auto: "自动登录",
form_button: "登录",
login_success: "登录成功",
login_message: "请填写完整信息",
}

View File

@ -2,12 +2,17 @@
<div class="go-header"> <div class="go-header">
<header class="go-header-box"> <header class="go-header-box">
<div class="li"> <div class="li">
<n-space>
<slot name="left"></slot> <slot name="left"></slot>
</n-space>
</div> </div>
<div class="ri"> <div class="ri">
<n-space>
<slot name="right"> <slot name="right">
<LangSelect />
<ThemeSelect /> <ThemeSelect />
</slot> </slot>
</n-space>
</div> </div>
</header> </header>
<n-divider class="go-header-divider" /> <n-divider class="go-header-divider" />
@ -16,6 +21,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ThemeSelect } from '@/components/ThemeSelect' import { ThemeSelect } from '@/components/ThemeSelect'
import { LangSelect } from '@/components/LangSelect'
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,38 +1,42 @@
import { createApp } from 'vue'; import { createApp } from 'vue'
import App from './App.vue'; import App from './App.vue'
import router, { setupRouter } from '@/router'; import router, { setupRouter } from '@/router'
import { setupStore } from '@/store'; import i18n from '@/i18n/index'
import { setupNaive, setupDirectives } from '@/plugins'; import { setupStore } from '@/store'
import { AppProvider } from '@/components/Application'; import { setupNaive, setupDirectives } from '@/plugins'
import { AppProvider } from '@/components/Application'
import { setHtmlTheme } from '@/utils/style' import { setHtmlTheme } from '@/utils/style'
async function appInit() { async function appInit() {
const appProvider = createApp(AppProvider); const appProvider = createApp(AppProvider)
const app = createApp(App); const app = createApp(App)
// 注册全局常用的 naive-ui 组件 // 注册全局常用的 naive-ui 组件
setupNaive(app); setupNaive(app)
// 注册全局自定义指令v-permission权限指令 // 注册全局自定义指令v-permission权限指令
setupDirectives(app); setupDirectives(app)
// 挂载状态管理 // 挂载状态管理
setupStore(app); setupStore(app)
// 处理主题色
setHtmlTheme()
// 优先挂载一下 Provider 解决路由守卫Axios中可使用DialogMessage 等之类组件 // 优先挂载一下 Provider 解决路由守卫Axios中可使用DialogMessage 等之类组件
appProvider.mount('#appProvider', true); appProvider.mount('#appProvider', true)
// 挂载路由 // 挂载路由
await setupRouter(app); await setupRouter(app)
// 路由准备就绪后挂载APP实例 // 路由准备就绪后挂载APP实例
await router.isReady(); await router.isReady()
app.mount('#app', true); // Store 准备就绪后处理主题色
setHtmlTheme()
// 语言注册
app.use(i18n)
app.mount('#app', true)
} }
void appInit(); void appInit()

View File

@ -1,4 +1,21 @@
// app theme preset color import { LangEnum } from '@/enums/styleEnum'
// 默认语言
export const lang = LangEnum.zh
// 语言数组
export const langList = [
{
label: '中文',
key: LangEnum.zh
},
{
label: 'English',
key: LangEnum.en
}
]
// 主体色
export const appThemeList: string[] = [ export const appThemeList: string[] = [
'#2d8cf0', '#2d8cf0',
'#0960bd', '#0960bd',
@ -17,22 +34,20 @@ export const appThemeList: string[] = [
'#78DEC7', '#78DEC7',
'#1768AC', '#1768AC',
'#FB9300', '#FB9300',
'#FC5404', '#FC5404'
]; ]
export const theme = { export const theme = {
darkThemeName: 'dark',
lightThemeName: 'light',
//深色主题 //深色主题
darkTheme: true, darkTheme: true,
//系统主题色 //系统主题色
appTheme: '#63e2b7', appTheme: '#63e2b7',
//系统内置主题色列表 //系统内置主题色列表
appThemeList, appThemeList
}; }
// 修改边框圆角 // 修改边框圆角
export const borderRadius = '8px' export const borderRadius = '8px'
// 轮播间隔 // 轮播间隔
export const carouselInterval = 5000 export const carouselInterval = 4000

View File

@ -0,0 +1,4 @@
export const GO_ACCESS_TOKEN = 'GO-ACCESS-TOKEN' // 用户token
export const GO_CURRENT_USER = 'GO-CURRENT-USER' // 当前用户信息
export const GO_LANG_SELECT = 'GO-LANG-SELECT' // 当前选择的语言类型
export const GO_Theme_SELECT = 'GO-Theme-SELECT' // 当前选择的主题

View File

@ -1,6 +1,10 @@
import { ThemeEnum } from '@/enums/styleEnum'
export interface DesignStateType { export interface DesignStateType {
//深色主题 // 是否是深色主题
darkTheme: boolean; darkTheme: boolean;
// 主题名称
themeName: ThemeEnum;
//系统风格 //系统风格
appTheme: string; appTheme: string;
//系统内置风格 //系统内置风格

View File

@ -1,34 +1,47 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia'
import { store } from '@/store'; import { store } from '@/store'
import { theme } from '@/settings/designSetting'; import { theme } from '@/settings/designSetting'
const { darkTheme, appTheme, appThemeList } = theme;
import { DesignStateType } from './designStore.d' import { DesignStateType } from './designStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils/index'
import { GO_Theme_SELECT } from '@/settings/storageConst'
import { ThemeEnum } from '@/enums/styleEnum'
const { darkTheme, appTheme, appThemeList } = theme
const storageThemeName = getLocalStorage(GO_Theme_SELECT)
export const useDesignStore = defineStore({ export const useDesignStore = defineStore({
id: 'useDesignStore', id: 'useDesignStore',
state: (): DesignStateType => ({ state: (): DesignStateType => ({
darkTheme, // 是否暗黑
darkTheme: storageThemeName === ThemeEnum.dark,
// 主题名称
themeName:
storageThemeName || (darkTheme && ThemeEnum.dark) || ThemeEnum.light,
// 颜色色号
appTheme, appTheme,
appThemeList, // 颜色列表
appThemeList
}), }),
getters: { getters: {
getDarkTheme(): boolean { getDarkTheme(e): boolean {
return this.darkTheme; return this.darkTheme
}, },
getAppTheme(): string { getAppTheme(): string {
return this.appTheme; return this.appTheme
}, },
getAppThemeList(): string[] { getAppThemeList(): string[] {
return this.appThemeList; return this.appThemeList
}, }
}, },
actions: { actions: {
changeTheme(): void { changeTheme(): void {
this.darkTheme = !this.darkTheme this.darkTheme = !this.darkTheme
this.themeName = this.darkTheme ? ThemeEnum.dark : ThemeEnum.light
setLocalStorage(GO_Theme_SELECT, this.themeName)
} }
} }
}); })
export function useDesignSettingWithOut() { export function useDesignSettingWithOut() {
return useDesignStore(store); return useDesignStore(store)
} }

View File

@ -0,0 +1,5 @@
import { LangEnum } from '@/enums/styleEnum'
export interface LangStateType {
// 当前语言
lang: LangEnum
}

View File

@ -0,0 +1,26 @@
import { defineStore } from 'pinia'
import { lang } from '@/settings/designSetting'
import { LangStateType } from './langStore.d'
import { LangEnum } from '@/enums/styleEnum'
import i18n from '@/i18n/index'
import { setLocalStorage } from '@/utils/index'
import { GO_LANG_SELECT } from '@/settings/storageConst'
export const useLangStore = defineStore({
id: 'useLangStore',
state: (): LangStateType => ({
lang
}),
getters: {
getLang(): LangEnum {
return this.lang
}
},
actions: {
changeLang(lang: LangEnum): void {
this.lang = lang
i18n.global.locale = lang
setLocalStorage(GO_LANG_SELECT, lang)
}
}
})

View File

@ -1,2 +0,0 @@
export const ACCESS_TOKEN = 'ACCESS-TOKEN'; // 用户token
export const CURRENT_USER = 'CURRENT-USER'; // 当前用户信息

View File

@ -1,5 +1,7 @@
import { DesignStateType } from '@/store/modules/designStore/designStore.d'; import { DesignStateType } from '@/store/modules/designStore/designStore.d';
import { LangStateType } from '@/store/modules/langStore/langStore.d';
export interface allStore { export interface allStore {
useDesignStore: DesignStateType; useDesignStore: DesignStateType;
useLangStore: LangStateType;
} }

View File

View File

@ -1,5 +1,5 @@
import { h } from 'vue'; import { h } from 'vue'
import { NIcon } from 'naive-ui'; import { NIcon } from 'naive-ui'
/** /**
* * ID * * ID
@ -7,24 +7,76 @@ import { NIcon } from 'naive-ui';
*/ */
export function getUUID(randomLength: number) { export function getUUID(randomLength: number) {
return Number( return Number(
Math.random() Math.random().toString().substr(2, randomLength) + Date.now()
.toString() ).toString(36)
.substr(2, randomLength) + Date.now()
).toString(36);
} }
/** /**
* * render * * render
*/ */
export const renderIcon = (icon: typeof NIcon) => { export const renderIcon = (icon: typeof NIcon) => {
return () => h(NIcon, null, { default: () => h(icon) }); return () => h(NIcon, null, { default: () => h(icon) })
} }
/** /**
* * vite 使 require * * vite 使 require
* @param name * @param name
* @returns * @returns url
*/ */
export const requireUrl = (path: string, name: string) => { export const requireUrl = (path: string, name: string) => {
return new URL(`${path}/${name}`, import.meta.url).href return new URL(`${path}/${name}`, import.meta.url).href
} }
/**
* *
* @param k
* @param v
* @returns RemovableRef
*/
export const setLocalStorage = <T>(k: string, v: T) => {
try {
window.localStorage.setItem(k, JSON.stringify(v))
} catch (error) {
return false
}
}
/**
* *
* @returns any
*/
export const getLocalStorage: (k: string) => any = (k: string) => {
const item = window.localStorage.getItem(k)
try {
return item ? JSON.parse(item) : item
} catch (err) {
return item
}
}
/**
* *
* @param k
* @param v
* @returns RemovableRef
*/
export const setSessionStorage = <T>(k: string, v: T) => {
try {
window.sessionStorage.setItem(k, JSON.stringify(v))
} catch (error) {
return false
}
}
/**
* *
* @returns any
*/
export const getSessionStorage: (k: string) => any = (k: string) => {
const item = window.sessionStorage.getItem(k)
try {
return item ? JSON.parse(item) : item
} catch (err) {
return item
}
}

View File

@ -1,6 +1,6 @@
import { ResultEnum } from "@/enums/httpEnum" import { ResultEnum } from '@/enums/httpEnum'
import { ErrorPageNameMap } from "@/enums/pageEnum" import { ErrorPageNameMap } from '@/enums/pageEnum'
import router from '@/router'; import router from '@/router'
/** /**
* * * *
@ -18,7 +18,13 @@ export const redirectErrorPage = (code: ResultEnum) => {
* * * *
* @param pageName * @param pageName
*/ */
export const routerTurnByName = (pageName: string) => { export const routerTurnByName = (pageName: string, isReplace?: boolean) => {
if (isReplace) {
router.replace({
name: pageName
})
return
}
router.push({ router.push({
name: pageName name: pageName
}) })

View File

@ -1,12 +1,11 @@
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { theme as themeEnum } from '@/settings/designSetting'
export const setHtmlTheme = (themeName?: string) => { export const setHtmlTheme = (themeName?: string) => {
const e = window.document.documentElement const e = window.document.documentElement
if (themeName) { if (themeName) {
e.setAttribute("data-theme", themeName); e.setAttribute('data-theme', themeName)
return return
} }
const designStore = useDesignStore() const designStore = useDesignStore()
e.setAttribute("data-theme", designStore.getDarkTheme ? themeEnum.darkThemeName : themeEnum.lightThemeName); e.setAttribute('data-theme', designStore.themeName)
} }

View File

@ -17,6 +17,7 @@
<Header> <Header>
<template #left></template> <template #left></template>
<template #right> <template #right>
<LangSelect />
<ThemeSelect /> <ThemeSelect />
</template> </template>
</Header> </Header>
@ -28,14 +29,14 @@
:key="i" :key="i"
class="go-login-carousel-img" class="go-login-carousel-img"
:src="getImageUrl(item, 'login')" :src="getImageUrl(item, 'login')"
alt="展示图片" alt="image"
/> />
</n-carousel> </n-carousel>
</div> </div>
<div class="login-account"> <div class="login-account">
<div class="login-account-container"> <div class="login-account-container">
<n-collapse-transition :appear="true" :show="show"> <n-collapse-transition :appear="true" :show="show">
<n-card class="login-account-card" title="登录 GoView"> <n-card class="login-account-card" :title="$t('login.desc')">
<div class="login-account-top"> <div class="login-account-top">
<img <img
class="login-account-top-logo" class="login-account-top-logo"
@ -53,7 +54,7 @@
<n-form-item path="username"> <n-form-item path="username">
<n-input <n-input
v-model:value="formInline.username" v-model:value="formInline.username"
placeholder="请输入用户名" :placeholder="$t('global.form_account')"
> >
<template #prefix> <template #prefix>
<n-icon size="18"> <n-icon size="18">
@ -67,7 +68,7 @@
v-model:value="formInline.password" v-model:value="formInline.password"
type="password" type="password"
show-password-toggle show-password-toggle
placeholder="请输入密码" :placeholder="$t('global.form_password')"
> >
<template #prefix> <template #prefix>
<n-icon size="18"> <n-icon size="18">
@ -80,7 +81,7 @@
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex-initial"> <div class="flex-initial">
<n-checkbox v-model:checked="autoLogin"> <n-checkbox v-model:checked="autoLogin">
自动登录 {{ $t('login.form_auto') }}
</n-checkbox> </n-checkbox>
</div> </div>
</div> </div>
@ -93,7 +94,7 @@
:loading="loading" :loading="loading"
block block
> >
登录 {{ $t('login.form_button') }}
</n-button> </n-button>
</n-form-item> </n-form-item>
</n-form> </n-form>
@ -104,7 +105,7 @@
</div> </div>
<div class="go-login-box-footer"> <div class="go-login-box-footer">
<n-a>文档地址: </n-a> <n-a>{{ $t('global.doc_addr') }}: </n-a>
<n-a italic href="http://www.mtruning.club/"> <n-a italic href="http://www.mtruning.club/">
http://www.mtruning.club/ http://www.mtruning.club/
</n-a> </n-a>
@ -116,16 +117,20 @@
import { reactive, ref, onMounted } from 'vue' import { reactive, ref, onMounted } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useMessage } from 'naive-ui' import { useMessage } from 'naive-ui'
import { import { useI18n } from 'vue-i18n'
PersonOutline as PersonOutlineIcon,
LockClosedOutline as LockClosedOutlineIcon
} from '@vicons/ionicons5'
import { requireUrl } from '@/utils/index' import { requireUrl } from '@/utils/index'
import { routerTurnByName } from '@/utils/page'
import shuffle from 'lodash/shuffle' import shuffle from 'lodash/shuffle'
import { carouselInterval } from '@/settings/designSetting' import { carouselInterval } from '@/settings/designSetting'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { ThemeSelect } from '@/components/ThemeSelect' import { ThemeSelect } from '@/components/ThemeSelect'
import { LangSelect } from '@/components/LangSelect'
import { Header } from '@/layout/components/Header' import { Header } from '@/layout/components/Header'
import { PageEnum } from '@/enums/pageEnum'
import {
PersonOutline as PersonOutlineIcon,
LockClosedOutline as LockClosedOutlineIcon
} from '@vicons/ionicons5'
interface FormState { interface FormState {
username: string username: string
@ -139,6 +144,7 @@ const loading = ref(false)
const autoLogin = ref(true) const autoLogin = ref(true)
const show = ref(false) const show = ref(false)
const designStore = useDesignStore() const designStore = useDesignStore()
const { t } = useI18n()
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
@ -152,8 +158,16 @@ const formInline = reactive({
}) })
const rules = { const rules = {
username: { required: true, message: '请输入用户名', trigger: 'blur' }, username: {
password: { required: true, message: '请输入密码', trigger: 'blur' } required: true,
message: t('global.form_account'),
trigger: 'blur'
},
password: {
required: true,
message: t('global.form_password'),
trigger: 'blur'
}
} }
// //
@ -194,11 +208,10 @@ const handleSubmit = (e: Event) => {
if (!errors) { if (!errors) {
const { username, password } = formInline const { username, password } = formInline
loading.value = true loading.value = true
message.success(`${t('login.login_success')}`)
message.success('登录成功!') routerTurnByName(PageEnum.BASE_HOME_NAME, true)
router.replace('/')
} else { } else {
message.error('请填写完整信息,并且进行验证码校验') message.error(`${t('login.login_message')}`)
} }
}) })
} }

1
types/config.d.ts vendored
View File

@ -1 +0,0 @@