mirror of
https://github.com/caojiezi2003/Snavigation.git
synced 2024-11-23 10:59:46 +00:00
feat: 优化消息通知效果
This commit is contained in:
parent
82d822d8a6
commit
855c313fec
3
.env
3
.env
@ -1,2 +1,5 @@
|
||||
# 搜索框提示词
|
||||
VITE_INPUT_TIP = "想要搜点什么"
|
||||
|
||||
# 进入欢迎词
|
||||
VITE_WELCOME_TEXT = "欢迎访问本站"
|
Binary file not shown.
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 138 KiB |
21
src/App.vue
21
src/App.vue
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<!-- 壁纸 -->
|
||||
<Cover />
|
||||
<Cover @loadComplete="loadComplete" />
|
||||
<!-- 主界面 -->
|
||||
<Transition name="fade" mode="out-in">
|
||||
<main v-if="status.imgLoadStatus" id="main" @click="mainClick">
|
||||
@ -20,19 +20,36 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { nextTick } from "vue";
|
||||
import { statusStore } from "@/stores";
|
||||
import { Notivue, Notifications } from "notivue";
|
||||
import { Notivue, Notifications, usePush } from "notivue";
|
||||
import { getGreeting } from "@/utils/timeTools";
|
||||
import Cover from "@/components/Cover.vue";
|
||||
import WeatherTime from "@/components/WeatherTime.vue";
|
||||
import SearchInp from "@/components/SearchInp.vue";
|
||||
import Footer from "@/components/Footer.vue";
|
||||
|
||||
const status = statusStore();
|
||||
const push = usePush();
|
||||
|
||||
// 获取配置
|
||||
const welcomeText = import.meta.env.VITE_WELCOME_TEXT ?? "欢迎访问本站";
|
||||
|
||||
// 全局点击
|
||||
const mainClick = () => {
|
||||
status.setSiteStatus("normal");
|
||||
};
|
||||
|
||||
// 加载完成事件
|
||||
const loadComplete = () => {
|
||||
nextTick(() => {
|
||||
push.info({
|
||||
title: getGreeting(),
|
||||
message: welcomeText,
|
||||
duration: 2000,
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -7,6 +7,7 @@
|
||||
:src="bgUrl"
|
||||
@load="imgLoadComplete"
|
||||
@error.once="imgLoadError"
|
||||
@animationend="imgAnimationEnd"
|
||||
/>
|
||||
<Transition name="fade">
|
||||
<div v-if="set.showBackgroundGray" class="gray" />
|
||||
@ -22,6 +23,7 @@ const set = setStore();
|
||||
const status = statusStore();
|
||||
const bgUrl = ref(null);
|
||||
const imgTimeout = ref(null);
|
||||
const emit = defineEmits(["loadComplete"]);
|
||||
|
||||
// 壁纸随机数
|
||||
// 请依据文件夹内的图片个数修改 Math.random() 后面的第一个数字
|
||||
@ -53,8 +55,14 @@ const setBgUrl = () => {
|
||||
const imgLoadComplete = () => {
|
||||
imgTimeout.value = setTimeout(() => {
|
||||
status.setImgLoadStatus(true);
|
||||
console.log("壁纸加载完成");
|
||||
}, 500);
|
||||
}, Math.floor(Math.random() * (600 - 300 + 1)) + 300);
|
||||
};
|
||||
|
||||
// 图片动画完成
|
||||
const imgAnimationEnd = () => {
|
||||
console.log("壁纸加载且动画完成");
|
||||
// 加载完成事件
|
||||
emit("loadComplete");
|
||||
};
|
||||
|
||||
// 图片显示失败
|
||||
|
@ -6,9 +6,11 @@
|
||||
@click="closeSearchInput"
|
||||
/>
|
||||
<div
|
||||
ref="searchAllRef"
|
||||
:class="status.siteStatus === 'focus' ? 'all focus' : 'all'"
|
||||
:style="{ pointerEvents: inputClickable ? 'none' : 'auto' }"
|
||||
ref="searchAllRef"
|
||||
@animationstart="inputClickable = true"
|
||||
@animationend="inputAnimationEnd"
|
||||
>
|
||||
<div class="engine" title="切换搜索引擎">
|
||||
<SvgIcon iconName="icon-baidu" className="baidu" />
|
||||
@ -40,9 +42,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { statusStore, setStore } from "@/stores";
|
||||
import { ref } from "vue";
|
||||
import { usePush } from "notivue";
|
||||
import { statusStore, setStore } from "@/stores";
|
||||
import Suggestions from "@/components/Suggestions.vue";
|
||||
|
||||
const set = setStore();
|
||||
@ -109,26 +111,19 @@ const toSearch = (val, type = 1) => {
|
||||
} else {
|
||||
status.setSiteStatus("focus");
|
||||
searchInputRef.value?.focus();
|
||||
push.info({ message: "请输入搜索内容", duration: 1000 });
|
||||
push.info({ message: "请输入搜索内容", duration: 1500 });
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索框 Dom 操作
|
||||
const searchInputDom = (dom) => {
|
||||
if (!dom) return false;
|
||||
dom.addEventListener("animationstart", () => {
|
||||
console.log("动画开始");
|
||||
inputClickable.value = true;
|
||||
});
|
||||
dom.addEventListener("animationend", () => {
|
||||
console.log("动画结束");
|
||||
// 搜索框动画结束
|
||||
const inputAnimationEnd = () => {
|
||||
console.log("搜索框动画结束");
|
||||
inputClickable.value = false;
|
||||
// 自动 focus
|
||||
if (set.autoFocus) {
|
||||
status.setSiteStatus("focus");
|
||||
searchInputRef.value?.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 键盘事件
|
||||
@ -140,10 +135,6 @@ const pressKeyboard = (event) => {
|
||||
// 子组件事件
|
||||
suggestionsRef.value?.keyboardEvents(keyCode, event);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
searchInputDom(searchAllRef.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -232,7 +232,10 @@ defineExpose({ keyboardEvents });
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 44vh;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
color: var(--main-text-color);
|
||||
background-color: var(--main-background-light-color);
|
||||
backdrop-filter: blur(30px) saturate(1.25);
|
||||
@ -260,12 +263,22 @@ defineExpose({ keyboardEvents });
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@media (min-width: 520px) {
|
||||
&:hover,
|
||||
&.focus {
|
||||
background-color: var(--main-background-light-color);
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
background-color: var(--main-background-light-color);
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -7,8 +7,7 @@ import SvgIcon from "@/components/SvgIcon.vue";
|
||||
import "@/utils/iconfont.js";
|
||||
// Notivue
|
||||
import { notivue } from "notivue";
|
||||
import "notivue/notifications.css"; // Only needed if using built-in notifications
|
||||
import "notivue/animations.css"; // Only needed if using built-in animations
|
||||
import "notivue/notifications.css";
|
||||
|
||||
// 主组件
|
||||
import App from "@/App.vue";
|
||||
@ -27,6 +26,11 @@ app.use(pinia);
|
||||
app.use(notivue, {
|
||||
pauseOnHover: false,
|
||||
limit: 1,
|
||||
animations: {
|
||||
enter: "notivue-slide-in",
|
||||
leave: "notivue-slide-out",
|
||||
clearAll: "notivue-fade",
|
||||
},
|
||||
});
|
||||
app.component("SvgIcon", SvgIcon);
|
||||
app.mount("#app");
|
||||
|
@ -29,11 +29,6 @@ body {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: var(--main-text-color);
|
||||
background-color: var(--main-text-hover-color);
|
||||
}
|
||||
|
||||
// Transition 动画
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
@ -68,6 +63,12 @@ body {
|
||||
}
|
||||
|
||||
// Notivue
|
||||
.notivue-slide-in {
|
||||
animation: notivue-slide-in 0.7s ease-in-out both;
|
||||
}
|
||||
.notivue-slide-out {
|
||||
animation: notivue-slide-out 0.3s ease-in-out both;
|
||||
}
|
||||
.Notivue__notification {
|
||||
background-color: var(--main-background-light-color);
|
||||
// backdrop-filter: blur(30px) saturate(1.25);
|
||||
@ -77,11 +78,27 @@ body {
|
||||
display: none;
|
||||
}
|
||||
.Notivue__content {
|
||||
padding: 0.5rem;
|
||||
.Notivue__content-message {
|
||||
text-align: center;
|
||||
padding: 0.8rem 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.Notivue__content-title {
|
||||
margin: 0;
|
||||
margin-right: 6px;
|
||||
line-height: inherit;
|
||||
color: var(--main-text-grey-color);
|
||||
}
|
||||
.Notivue__content-message {
|
||||
line-height: inherit;
|
||||
color: var(--main-text-grey-color);
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
flex-direction: column;
|
||||
.Notivue__content-title {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,3 +165,56 @@ body {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes notivue-slide-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-200px);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
70% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes notivue-slide-out {
|
||||
from {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 文本选中
|
||||
::selection {
|
||||
color: var(--main-text-color);
|
||||
background-color: var(--main-text-hover-color);
|
||||
}
|
||||
|
||||
// 滚动条
|
||||
::-webkit-scrollbar {
|
||||
background-color: transparent;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 12px;
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
|
||||
background-color: var(--main-background-color);
|
||||
}
|
||||
|
@ -27,3 +27,27 @@ export const getCurrentTime = () => {
|
||||
};
|
||||
return currentTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据实时时间返回不同的问候语
|
||||
* @returns {string} 问候语
|
||||
*/
|
||||
export const getGreeting = () => {
|
||||
const currentTime = new Date();
|
||||
const currentHour = currentTime.getHours();
|
||||
let greeting = "";
|
||||
if (currentHour >= 5 && currentHour < 9) {
|
||||
greeting = "早上好";
|
||||
} else if (currentHour >= 9 && currentHour < 12) {
|
||||
greeting = "上午好";
|
||||
} else if (currentHour >= 12 && currentHour < 18) {
|
||||
greeting = "下午好";
|
||||
} else if (currentHour >= 18 && currentHour < 24) {
|
||||
greeting = "晚上好";
|
||||
} else if (currentHour >= 0 && currentHour < 5) {
|
||||
greeting = "凌晨好";
|
||||
} else {
|
||||
greeting = "夜深了";
|
||||
}
|
||||
return greeting;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user