feat: 暂存

This commit is contained in:
王红彬
2024-09-06 18:30:04 +08:00
parent d94cbfa4a1
commit 187e593b66
10 changed files with 247 additions and 58 deletions

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterStore } from '@/stores/counter'; import { useCounterStore } from '@/stores/counter.ts';
import { useDark, useToggle } from '@vueuse/core'; import { useDark, useToggle } from '@vueuse/core';
const isDark = useDark(); const isDark = useDark();
@@ -20,6 +20,8 @@ const store = useCounterStore();
</el-icon> </el-icon>
<SvgIcon icon="lock"></SvgIcon> <SvgIcon icon="lock"></SvgIcon>
<ChangeTheme />
</template> </template>
<style scoped> <style scoped>

View File

@@ -0,0 +1,19 @@
<template>
<el-dropdown trigger="click">
<SvgIcon pointer icon="language"></SvgIcon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="changeLang('zh')">中文</el-dropdown-item>
<el-dropdown-item @click="changeLang('en')">English</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts">
const { locale } = useI18n();
const changeLang = (lang: string) => {
locale.value = lang;
localStorage.setItem('lang', lang);
};
</script>
``

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
const props = defineProps({
prefix: {
type: String,
default: 'icon',
},
icon: {
type: String,
required: true,
},
color: {
type: String,
},
size: {
type: Number,
},
pointer: {
type: Boolean,
},
});
const symbolId = computed(() => {
return `#${props.prefix}-${props.icon}`;
});
</script>
<template>
<el-icon :size="size" :color="color" :style="props.pointer ? { cursor: 'pointer' } : {}">
<svg aria-hidden="true">
<use :xlink:href="symbolId" :fill="color" />
</svg>
</el-icon>
</template>

8
src/components/icon/data.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare namespace TYPE {
type SvgIconType = {
icon: string;
size?: number;
color?: string;
prefix?: string;
};
}

View File

@@ -0,0 +1,6 @@
import type { VNode } from 'vue';
import SvgIcon from './SvgIcon.vue';
export const useSvgIcon = (props: TYPE.SvgIconType): VNode => {
return h(SvgIcon, props);
};

View File

@@ -0,0 +1,66 @@
<script setup lang="ts">
import { useDark } from '@vueuse/core';
import { useSvgIcon } from '../icon/useSvgIcon';
const isDark = useDark();
const darkIcon = useSvgIcon({ icon: 'dark', color: '#fde047' });
const lightIcon = useSvgIcon({ icon: 'light', color: '#fde047' });
// 添加动画效果
function toggleTheme(event: MouseEvent) {
const isAppearanceTransition =
// @ts-expect-error 实验性质方法
document.startViewTransition &&
!window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!isAppearanceTransition || !event) {
return;
}
const x = event.clientX;
const y = event.clientY;
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
);
// @ts-expect-error: Transition API
const transition = document.startViewTransition(async () => {
isDark.value = !isDark.value;
await nextTick();
});
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
];
document.documentElement.animate(
{
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
},
{
duration: 4500,
easing: 'ease-in',
pseudoElement: isDark.value
? '::view-transition-old(root)'
: '::view-transition-new(root)',
}
);
});
}
</script>
<!-- :border-color="blackColor"
:active-color="blackColor" -->
<template>
<el-switch
@click.stop="
(e:MouseEvent) => {
toggleTheme(e);
}
"
:before-change="() => false"
v-model="isDark"
inline-prompt
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #a1a1a1"
:active-icon="darkIcon"
:inactive-icon="lightIcon"
></el-switch>
</template>

View File

@@ -5,6 +5,7 @@ import { createMemoryHistory, createRouter } from 'vue-router';
import App from './App.vue'; import App from './App.vue';
import HelloWorld from './components/HelloWorld.vue'; import HelloWorld from './components/HelloWorld.vue';
// 引入黑色主题
import 'element-plus/theme-chalk/dark/css-vars.css'; import 'element-plus/theme-chalk/dark/css-vars.css';
import Demo from './components/Demo.vue'; import Demo from './components/Demo.vue';
import './style.css'; import './style.css';

11
src/stores/global.ts Normal file
View File

@@ -0,0 +1,11 @@
import { defineStore } from 'pinia';
export const useGlobalStore = defineStore('global', () => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
});

View File

@@ -1,79 +1,110 @@
:root { /* 清除 HTML 默认样式的 CSS Reset */
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; *,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
/* 使字体大小在浏览器上更容易控制 */
font-size: 100%;
line-height: 1.5; line-height: 1.5;
font-weight: 400; }
color-scheme: light dark; body {
color: rgba(255, 255, 255, 0.87); /* 确保 body 占满整个屏幕高度 */
background-color: #242424; min-height: 100vh;
text-rendering: optimizeSpeed;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
img,
picture,
video,
canvas,
svg {
/* 确保多媒体元素不超过其容器 */
display: block;
max-width: 100%;
}
button,
input,
select,
textarea {
/* 去除表单元素的默认样式,使用继承字体 */
font: inherit;
}
a { a {
font-weight: 500; /* 清除链接的默认下划线和颜色 */
color: #646cff; text-decoration: none;
text-decoration: inherit; color: inherit;
}
a:hover {
color: #535bf2;
} }
body { ul,
margin: 0; ol {
display: flex; /* 清除列表的默认缩进和样式 */
place-items: center; list-style: none;
min-width: 320px;
min-height: 100vh;
} }
h1 { table {
font-size: 3.2em; /* 确保表格的布局正确 */
line-height: 1.1; border-collapse: collapse;
width: 100%;
}
/* 确保所有元素都有一致的外边距、填充和边界盒模型 */
* {
box-sizing: inherit;
}
html {
/* 为所有浏览器设定一致的滚动行为 */
scroll-behavior: smooth;
} }
button { button {
border-radius: 8px; /* 去除按钮的默认边框 */
border: 1px solid transparent; background: none;
padding: 0.6em 1.2em; border: none;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer; cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
} }
.card { blockquote,
padding: 2em; q {
/* 取消 blockquote 和 q 的默认引用样式 */
quotes: none;
} }
#app { blockquote::before,
max-width: 1280px; blockquote::after,
margin: 0 auto; q::before,
padding: 2rem; q::after {
text-align: center; content: '';
} }
@media (prefers-color-scheme: light) { // 添加主题切换动画
:root { ::view-transition-new(root),
color: #213547; ::view-transition-old(root) {
background-color: #ffffff; animation: none;
} mix-blend-mode: normal;
a:hover { }
color: #747bff;
} ::view-transition-old(root) {
button { z-index: 1;
background-color: #f9f9f9; }
}
::view-transition-new(root) {
z-index: 2147483646;
}
html.dark::view-transition-old(root) {
z-index: 2147483646;
}
html.dark::view-transition-new(root) {
z-index: 1;
} }

12
src/vite-env.d.ts vendored
View File

@@ -1 +1,13 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
/**
* 1. /// <reference types="vite/client" />:
• 这行代码是一个三斜线指令,它告诉 TypeScript 编译器去引用 vite/client 的类型声明。
• Vite 自带的 vite/client 模块中包含了 Vite 环境下常用的全局变量和工具的类型声明。比如:
• import.meta: Vite 扩展了 ES Modules 中的 import.meta 对象,在 Vite 项目中有额外的属性如 import.meta.env该属性中包含了一些 Vite 的环境变量。
• import.meta.env: 通过它,你可以访问定义在 .env 文件或 VITE_ 前缀的自定义环境变量。这些变量在 vite/client 模块中有类型定义,能提供良好的开发体验和自动完成支持。
2. vite-env.d.ts 文件的作用:
• 这是一个全局的类型声明文件,通常用于声明在整个项目中可以使用的全局类型。
• 该文件通常位于项目的根目录下,它使 TypeScript 知道 Vite 环境下的一些特殊语法(如 import.meta以及任何自定义的全局类型。
• 这个文件的存在确保在使用 Vite 特定功能(例如动态导入、环境变量)时,不会出现 TypeScript 编译错误,并能获得相应的类型提示。
*/