Compare commits
2 Commits
b29579afde
...
907c6dd1c2
Author | SHA1 | Date | |
---|---|---|---|
907c6dd1c2 | |||
efdc89bba1 |
@@ -52,6 +52,7 @@ business-center-vite (主仓库 business-center-vite)
|
||||
| pinia-plugin-persistedstate | 4.2.x | [官网](https://prazdevs.github.io/pinia-plugin-persistedstate/zh/) [npm](https://www.npmjs.com/package/pinia-plugin-persistedstate) [GitHub](https://github.com/prazdevs/pinia-plugin-persistedstate) | Pinia 存储持久化插件 |
|
||||
| vue-router | 4.5.x | [官网](https://router.vuejs.org/) [npm](https://www.npmjs.com/package/vue-router) [GitHub](https://github.com/vuejs/router) | 路由管理 |
|
||||
| vue-i18n | 11.1.x | [官网](https://vue-i18n.intlify.dev/) [npm](https://www.npmjs.com/package/vue-i18n) [GitHub](https://github.com/intlify/vue-i18n) | i18n 国际化 |
|
||||
| @vueuse/core | 12.7.x | [官网](https://vueuse.org/) [中文网](https://vueuse.nodejs.cn/) [npm](https://www.npmjs.com/package/@vueuse/core) [GitHub](https://github.com/vueuse/vueuse) | Vue 组合实用工具集合 |
|
||||
|
||||
|
||||
### 命名规范
|
||||
|
77
frontend/package-lock.json
generated
77
frontend/package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "business-center-vite",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^12.7.0",
|
||||
"element-plus": "^2.9.5",
|
||||
"pinia": "^2.3.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
@@ -1998,9 +1999,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
|
||||
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==",
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
@@ -2711,36 +2712,36 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
|
||||
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
|
||||
"version": "12.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.7.0.tgz",
|
||||
"integrity": "sha512-jtK5B7YjZXmkGNHjviyGO4s3ZtEhbzSgrbX+s5o+Lr8i2nYqNyHuPVOeTdM1/hZ5Tkxg/KktAuAVDDiHMraMVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/web-bluetooth": "^0.0.16",
|
||||
"@vueuse/metadata": "9.13.0",
|
||||
"@vueuse/shared": "9.13.0",
|
||||
"vue-demi": "*"
|
||||
"@types/web-bluetooth": "^0.0.20",
|
||||
"@vueuse/metadata": "12.7.0",
|
||||
"@vueuse/shared": "12.7.0",
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/metadata": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
|
||||
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
|
||||
"version": "12.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.7.0.tgz",
|
||||
"integrity": "sha512-4VvTH9mrjXqFN5LYa5YfqHVRI6j7R00Vy4995Rw7PQxyCL3z0Lli86iN4UemWqixxEvYfRjG+hF9wL8oLOn+3g==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
|
||||
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
|
||||
"version": "12.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.7.0.tgz",
|
||||
"integrity": "sha512-coLlUw2HHKsm7rPN6WqHJQr18WymN4wkA/3ThFaJ4v4gWGWAQQGK+MJxLuJTBs4mojQiazlVWAKNJNpUWGRkNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vue-demi": "*"
|
||||
"vue": "^3.5.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
@@ -3516,6 +3517,48 @@
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/element-plus/node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
|
||||
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/element-plus/node_modules/@vueuse/core": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
|
||||
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
|
||||
"license": "MIT",
|
||||
"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/metadata": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
|
||||
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/element-plus/node_modules/@vueuse/shared": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
|
||||
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"vue-demi": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^12.7.0",
|
||||
"element-plus": "^2.9.5",
|
||||
"pinia": "^2.3.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
|
@@ -9,6 +9,7 @@ const themeConfigStore = useThemeConfigStore()
|
||||
|
||||
<template>
|
||||
{{ themeConfigStore.elConfig.size }}
|
||||
{{ themeConfigStore.themeConfig.themeMode }}
|
||||
<el-config-provider :size="themeConfigStore.elConfig.size" :z-index="themeConfigStore.elConfig.zIndex"
|
||||
:button="{ autoInsertSpace: true }" :locale="locale">
|
||||
<MainView />
|
||||
|
@@ -1,26 +1,3 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
@@ -84,3 +61,11 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.light body {
|
||||
}
|
||||
|
||||
.dark body {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
/* transition: 0.4s; */
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
|
98
frontend/src/components/DarkSwitch/DarkSwitch.vue
Normal file
98
frontend/src/components/DarkSwitch/DarkSwitch.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<ElSwitch v-model="themeConfig.themeMode" :active-icon="Moon" active-value="dark" :inactive-icon="Sunny"
|
||||
inactive-value="light" inline-prompt @click="_toggleDark($event)" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeMount } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ElSwitch } from 'element-plus'
|
||||
import { Moon, Sunny } from '@element-plus/icons-vue'
|
||||
import { useThemeConfigStore } from '@/stores/themeConfig'
|
||||
import { useDark, useToggle } from '@vueuse/core'
|
||||
|
||||
const themeConfigStore = useThemeConfigStore()
|
||||
|
||||
const { themeConfig } = storeToRefs(themeConfigStore)
|
||||
|
||||
const isDark = useDark()
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (themeConfig.value.themeMode === 'auto') {
|
||||
|
||||
} else {
|
||||
if (themeConfig.value.themeMode === 'dark') {
|
||||
isDark.value = true
|
||||
} else {
|
||||
isDark.value = false
|
||||
}
|
||||
}
|
||||
const root = document.documentElement
|
||||
root.classList.add(isDark.value ? 'dark' : 'light')
|
||||
})
|
||||
|
||||
const _toggleDark = async (event: MouseEvent) => {
|
||||
if (typeof document.startViewTransition === 'function') {
|
||||
const x = event.clientX
|
||||
const y = event.clientY
|
||||
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y))
|
||||
nextTick(async () => {
|
||||
let _isDark: boolean
|
||||
const transition = document.startViewTransition(() => {
|
||||
const root = document.documentElement
|
||||
_isDark = root.classList.contains('dark')
|
||||
root.classList.remove(_isDark ? 'dark' : 'light')
|
||||
root.classList.add(_isDark ? 'light' : 'dark')
|
||||
})
|
||||
await transition.ready.then(() => {
|
||||
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]
|
||||
// console.log('_isDark', _isDark)
|
||||
document.documentElement.animate(
|
||||
{
|
||||
// clipPath: _isDark ? [...clipPath].reverse() : clipPath,
|
||||
clipPath: clipPath,
|
||||
},
|
||||
{
|
||||
duration: 500,
|
||||
easing: 'ease-in',
|
||||
// pseudoElement: _isDark ? '::view-transition-old(root)' : '::view-transition-new(root)',
|
||||
pseudoElement: '::view-transition-new(root)',
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
})
|
||||
} else {
|
||||
const toggleDark = useToggle(themeConfig.value.isDark)
|
||||
await toggleDark()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 注意这里不加 scope, 是全局样式 */
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
mix-blend-mode: normal;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
::view-transition-old(root) {
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
::view-transition-new(root) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dark,
|
||||
.light {
|
||||
&::view-transition-old(root) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&::view-transition-new(root) {
|
||||
z-index: 999;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -8,6 +8,9 @@ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
// element-plus 深色模式
|
||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
// 导入 vue-i18n 模块
|
||||
|
@@ -1,20 +1,41 @@
|
||||
import { ref } from 'vue'
|
||||
import { computed, ref, type WritableComputedRef } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { ElConfigSize, ThemeMode } from '@/types/common/ThemeConfig';
|
||||
import { useDark } from '@vueuse/core';
|
||||
|
||||
export const useThemeConfigStore = defineStore('themeConfig', () => {
|
||||
// refer: https://element-plus.org/zh-CN/component/config-provider.html
|
||||
const elConfig = ref<{
|
||||
// 全局组件大小
|
||||
size: "" | "small" | "default" | "large";
|
||||
size: ElConfigSize;
|
||||
// 全局初始化 zIndex 的值
|
||||
zIndex?: number;
|
||||
}>({
|
||||
size: 'small',
|
||||
zIndex: 3000,
|
||||
// zIndex: 3000,
|
||||
})
|
||||
|
||||
const themeConfig = ref<{
|
||||
themeMode: ThemeMode,
|
||||
// updateThemeMode: Function,
|
||||
getCurrentThemeMode: Function,
|
||||
}>({
|
||||
themeMode: 'auto',
|
||||
// updateThemeMode: (themeMode: ThemeMode) => {
|
||||
// themeConfig.value.themeMode = themeMode
|
||||
// },
|
||||
getCurrentThemeMode: () => {
|
||||
if (themeConfig.value.themeMode === 'auto') {
|
||||
return ''
|
||||
}
|
||||
return themeConfig.value.themeMode
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
elConfig,
|
||||
|
||||
themeConfig,
|
||||
}
|
||||
}, {
|
||||
// 启用持久化
|
||||
|
10
frontend/src/types/common/ThemeConfig.ts
Normal file
10
frontend/src/types/common/ThemeConfig.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
/**
|
||||
* element-plus config
|
||||
*/
|
||||
export type ElConfigSize = '' | 'small' | 'default' | 'large'
|
||||
|
||||
/**
|
||||
* theme config
|
||||
*/
|
||||
export type ThemeMode = 'auto' | 'light' | 'dark'
|
@@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<RouterView />
|
||||
|
||||
<header>
|
||||
<div class="wrapper">
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'small'">哈哈哈</ElButton>
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'default'">哈哈哈</ElButton>
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'large'">哈哈哈</ElButton>
|
||||
<nav>
|
||||
<!-- <RouterLink to="/">Home</RouterLink> -->
|
||||
<!-- <RouterLink to="/about">About</RouterLink> -->
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<DarkSwitch />
|
||||
<div class="wrapper">
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'small'">哈哈哈</ElButton>
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'default'">哈哈哈</ElButton>
|
||||
<ElButton @click="() => themeConfigStore.elConfig.size = 'large'">哈哈哈</ElButton>
|
||||
<nav>
|
||||
<!-- <RouterLink to="/">Home</RouterLink> -->
|
||||
<!-- <RouterLink to="/about">About</RouterLink> -->
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DarkSwitch from '@/components/DarkSwitch/DarkSwitch.vue';
|
||||
import { useThemeConfigStore } from '@/stores/themeConfig';
|
||||
import { ElButton } from 'element-plus';
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
|
Reference in New Issue
Block a user