mirror of
https://github.com/caojiezi2003/Snavigation.git
synced 2024-11-23 19:21:57 +00:00
feat: 完善设置
This commit is contained in:
parent
c184efb8ce
commit
fcf83ff50f
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "snavigation",
|
"name": "snavigation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.0.0 beta 3",
|
"version": "2.0.0 beta 4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
|
File diff suppressed because one or more lines are too long
90
src/App.vue
90
src/App.vue
@ -20,25 +20,41 @@
|
|||||||
<!-- 状态切换 -->
|
<!-- 状态切换 -->
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div
|
<div
|
||||||
|
class="all-controls"
|
||||||
v-show="
|
v-show="
|
||||||
status.siteStatus !== 'focus' && status.siteStatus !== 'normal'
|
status.siteStatus !== 'focus' && status.siteStatus !== 'normal'
|
||||||
"
|
"
|
||||||
class="change-status"
|
|
||||||
:title="status.siteStatus !== 'set' ? '设置' : '首页'"
|
|
||||||
@click.stop="
|
|
||||||
status.setSiteStatus(
|
|
||||||
status.siteStatus !== 'set' ? 'set' : 'normal'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<Transition name="fade" mode="out-in">
|
<div
|
||||||
<SvgIcon
|
class="change-status"
|
||||||
:iconName="`icon-${
|
:title="status.mainBoxBig ? '收起' : '展开'"
|
||||||
status.siteStatus !== 'set' ? 'setting' : 'home'
|
@click.stop="status.setMainBoxBig(!status.mainBoxBig)"
|
||||||
}`"
|
>
|
||||||
:key="status.siteStatus !== 'set' ? 'setting' : 'home'"
|
<Transition name="fade" mode="out-in">
|
||||||
/>
|
<SvgIcon
|
||||||
</Transition>
|
:iconName="`icon-${status.mainBoxBig ? 'packup' : 'unfold'}`"
|
||||||
|
:key="status.mainBoxBig ? 'packup' : 'unfold'"
|
||||||
|
/>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="change-status"
|
||||||
|
:title="status.siteStatus !== 'set' ? '设置' : '首页'"
|
||||||
|
@click.stop="
|
||||||
|
status.setSiteStatus(
|
||||||
|
status.siteStatus !== 'set' ? 'set' : 'normal'
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Transition name="fade" mode="out-in">
|
||||||
|
<SvgIcon
|
||||||
|
:iconName="`icon-${
|
||||||
|
status.siteStatus !== 'set' ? 'setting' : 'home'
|
||||||
|
}`"
|
||||||
|
:key="status.siteStatus !== 'set' ? 'setting' : 'home'"
|
||||||
|
/>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
<!-- Notification -->
|
<!-- Notification -->
|
||||||
@ -122,7 +138,7 @@ const mainPressKeyboard = (event) => {
|
|||||||
&.main-set {
|
&.main-set {
|
||||||
.main-box {
|
.main-box {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
margin-top: 200px;
|
margin-top: 220px;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
@ -134,26 +150,34 @@ const mainPressKeyboard = (event) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.change-status {
|
.all-controls {
|
||||||
cursor: pointer;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 10px;
|
width: 100%;
|
||||||
right: 10px;
|
top: 0;
|
||||||
|
padding: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: space-between;
|
||||||
font-size: 28px;
|
box-sizing: border-box;
|
||||||
padding: 8px;
|
.change-status {
|
||||||
border-radius: 8px;
|
cursor: pointer;
|
||||||
color: var(--main-text-color);
|
display: flex;
|
||||||
z-index: 1;
|
align-items: center;
|
||||||
transition: opacity 0.3s, background-color 0.3s, transform 0.3s;
|
justify-content: center;
|
||||||
&:hover {
|
font-size: 26px;
|
||||||
backdrop-filter: blur(20px);
|
padding: 8px;
|
||||||
background-color: var(--main-background-light-color);
|
border-radius: 8px;
|
||||||
}
|
color: var(--main-text-color);
|
||||||
&:active {
|
z-index: 1;
|
||||||
transform: scale(0.95);
|
transition: opacity 0.3s, background-color 0.3s, transform 0.3s;
|
||||||
|
&:hover {
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
background-color: var(--main-background-light-color);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<!-- 全局设置 -->
|
|
||||||
<template>
|
<template>
|
||||||
<n-tabs class="func" size="large" justify-content="space-evenly" animated>
|
<n-tabs class="func" size="large" justify-content="space-evenly" animated>
|
||||||
<n-tab-pane name="link" tab="捷径"> 即将完善 </n-tab-pane>
|
<n-tab-pane name="link" tab="捷径"> 即将完善 </n-tab-pane>
|
||||||
<n-tab-pane name="note" tab="便签"> 即将完善 </n-tab-pane>
|
<n-tab-pane name="note" tab="便签"> 即将完善 </n-tab-pane>
|
||||||
<n-tab-pane name="more" tab="还能有啥"> 还能有啥呢 😢 </n-tab-pane>
|
<n-tab-pane name="more" tab="更多"> 还能有啥呢 😢 </n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="main-box" @click.stop>
|
<!-- 一个盒子 -->
|
||||||
|
<div :class="status.mainBoxBig ? 'main-box big' : 'main-box'" @click.stop>
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
<AllBox v-if="status.siteStatus === 'box'" />
|
<AllBox v-if="status.siteStatus === 'box'" />
|
||||||
<AllSet v-else-if="status.siteStatus === 'set'" />
|
<AllSet v-else-if="status.siteStatus === 'set'" />
|
||||||
@ -19,15 +20,18 @@ const status = statusStore();
|
|||||||
.main-box {
|
.main-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 400px;
|
height: 460px;
|
||||||
max-height: 400px;
|
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
background-color: var(--main-background-light-color);
|
background-color: var(--main-background-light-color);
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transition: opacity 0.3s, transform 0.3s, margin-top 0.3s;
|
transition: opacity 0.3s, transform 0.3s, margin-top 0.3s, height 0.3s;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
|
:deep(.scrollbar) {
|
||||||
|
max-height: calc(460px - 84px);
|
||||||
|
}
|
||||||
:deep(.set-item) {
|
:deep(.set-item) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -63,5 +67,12 @@ const status = statusStore();
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.big {
|
||||||
|
height: 80%;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
:deep(.scrollbar) {
|
||||||
|
max-height: calc(80vh - 84px);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,26 +1,51 @@
|
|||||||
<!-- 全局设置 -->
|
|
||||||
<template>
|
<template>
|
||||||
<n-tabs class="set" size="large" justify-content="space-evenly" animated>
|
<n-tabs class="set" size="large" justify-content="space-evenly" animated>
|
||||||
<n-tab-pane name="main" tab="基础设置">
|
<n-tab-pane name="main" tab="基础设置">
|
||||||
<n-scrollbar style="max-height: 316px">
|
<n-scrollbar class="scrollbar">
|
||||||
<n-card class="set-item">
|
<n-h6 prefix="bar"> 壁纸 </n-h6>
|
||||||
|
<n-card
|
||||||
|
class="set-item cover"
|
||||||
|
:content-style="{ flexDirection: 'column', alignItems: 'flex-start' }"
|
||||||
|
>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<span class="title">壁纸偏好</span>
|
<span class="title">壁纸偏好</span>
|
||||||
<span class="tip">设置站点背景图片</span>
|
<span class="tip">设置站点背景图片</span>
|
||||||
</div>
|
</div>
|
||||||
|
<n-grid
|
||||||
|
class="cover-selete"
|
||||||
|
responsive="screen"
|
||||||
|
cols="2 s:3 m:4 l:4"
|
||||||
|
:x-gap="16"
|
||||||
|
:y-gap="16"
|
||||||
|
>
|
||||||
|
<n-grid-item
|
||||||
|
v-for="(item, index) in backgroundTypeArr"
|
||||||
|
:key="index"
|
||||||
|
:class="index === backgroundType ? 'item check' : 'item'"
|
||||||
|
@click="changeBackground(index)"
|
||||||
|
>
|
||||||
|
<span class="name" v-html="item.name" />
|
||||||
|
</n-grid-item>
|
||||||
|
</n-grid>
|
||||||
</n-card>
|
</n-card>
|
||||||
<n-card class="set-item">
|
<n-h6 prefix="bar"> 搜索 </n-h6>
|
||||||
<div class="name">
|
|
||||||
<span class="title">壁纸遮罩</span>
|
|
||||||
<span class="tip">壁纸周围是否显示暗色遮罩</span>
|
|
||||||
</div>
|
|
||||||
<n-switch v-model:value="showBackgroundGray" :round="false" />
|
|
||||||
</n-card>
|
|
||||||
<n-card class="set-item">
|
<n-card class="set-item">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<span class="title">搜索引擎</span>
|
<span class="title">搜索引擎</span>
|
||||||
<span class="tip">切换搜索引擎</span>
|
<span class="tip">切换或自定义搜索引擎</span>
|
||||||
</div>
|
</div>
|
||||||
|
<n-button
|
||||||
|
strong
|
||||||
|
secondary
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
status.setSiteStatus('focus');
|
||||||
|
status.setEngineChangeStatus(true);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
前往调整
|
||||||
|
</n-button>
|
||||||
</n-card>
|
</n-card>
|
||||||
<n-card class="set-item">
|
<n-card class="set-item">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
@ -43,52 +68,123 @@
|
|||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="personalization" tab="个性调整">
|
<n-tab-pane name="personalization" tab="个性调整">
|
||||||
<n-card class="set-item">
|
<n-scrollbar class="scrollbar">
|
||||||
<div class="name">
|
<n-h6 prefix="bar"> 壁纸 </n-h6>
|
||||||
<span class="title">时间显秒</span>
|
<n-card class="set-item">
|
||||||
<span class="tip">是否在分钟后面显示秒数</span>
|
<div class="name">
|
||||||
</div>
|
<span class="title">壁纸遮罩</span>
|
||||||
<n-switch v-model:value="showSeconds" :round="false" />
|
<span class="tip">壁纸周围是否显示暗色遮罩</span>
|
||||||
</n-card>
|
</div>
|
||||||
<n-card class="set-item">
|
<n-switch v-model:value="showBackgroundGray" :round="false" />
|
||||||
<div class="name">
|
</n-card>
|
||||||
<span class="title">自动聚焦</span>
|
<n-h6 prefix="bar"> 天气与时间 </n-h6>
|
||||||
<span class="tip">打开网站时自动聚焦搜索框</span>
|
<n-card class="set-item">
|
||||||
</div>
|
<div class="name">
|
||||||
<n-switch v-model:value="autoFocus" :round="false" />
|
<span class="title">时间显秒</span>
|
||||||
</n-card>
|
<span class="tip">是否在分钟后面显示秒数</span>
|
||||||
<n-card class="set-item">
|
</div>
|
||||||
<div class="name">
|
<n-switch v-model:value="showSeconds" :round="false" />
|
||||||
<span class="title">自动失焦</span>
|
</n-card>
|
||||||
<span class="tip">跳转搜索后搜索框自动失焦</span>
|
<n-h6 prefix="bar"> 搜索框 </n-h6>
|
||||||
</div>
|
<n-card class="set-item">
|
||||||
<n-switch v-model:value="autoInputBlur" :round="false" />
|
<div class="name">
|
||||||
</n-card>
|
<span class="title">自动聚焦</span>
|
||||||
|
<span class="tip">打开网站时自动聚焦搜索框</span>
|
||||||
|
</div>
|
||||||
|
<n-switch v-model:value="autoFocus" :round="false" />
|
||||||
|
</n-card>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="name">
|
||||||
|
<span class="title">自动失焦</span>
|
||||||
|
<span class="tip">跳转搜索后搜索框自动失焦</span>
|
||||||
|
</div>
|
||||||
|
<n-switch v-model:value="autoInputBlur" :round="false" />
|
||||||
|
</n-card>
|
||||||
|
</n-scrollbar>
|
||||||
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="other" tab="其他设置">
|
||||||
|
<n-scrollbar class="scrollbar">
|
||||||
|
<n-h6 prefix="bar"> 重置 </n-h6>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="name">
|
||||||
|
<span class="title">站点重置</span>
|
||||||
|
<span class="tip">若站点显示异常或出现问题时可尝试此操作</span>
|
||||||
|
</div>
|
||||||
|
<n-button strong secondary @click="resetSite"> 重置 </n-button>
|
||||||
|
</n-card>
|
||||||
|
<n-h6 prefix="bar"> 备份 </n-h6>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="name">
|
||||||
|
<span class="title">站点备份</span>
|
||||||
|
<span class="tip">将站点配置及个性化内容进行备份</span>
|
||||||
|
</div>
|
||||||
|
<n-button strong secondary @click="backupSite"> 备份 </n-button>
|
||||||
|
</n-card>
|
||||||
|
<n-h6 prefix="bar"> 恢复 </n-h6>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="name">
|
||||||
|
<span class="title">数据恢复</span>
|
||||||
|
<span class="tip">将备份的站点内容进行恢复</span>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
ref="recoverRef"
|
||||||
|
type="file"
|
||||||
|
style="display: none"
|
||||||
|
accept=".json"
|
||||||
|
@change="recoverSite"
|
||||||
|
/>
|
||||||
|
<n-button strong secondary @click="recoverRef?.click()">
|
||||||
|
恢复
|
||||||
|
</n-button>
|
||||||
|
</n-card>
|
||||||
|
</n-scrollbar>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="other" tab="其他设置"> 其他设置 </n-tab-pane>
|
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NTabs, NTabPane, NCard, NSwitch, NSelect, NScrollbar } from "naive-ui";
|
import { ref } from "vue";
|
||||||
|
import {
|
||||||
|
NTabs,
|
||||||
|
NTabPane,
|
||||||
|
NCard,
|
||||||
|
NSwitch,
|
||||||
|
NSelect,
|
||||||
|
NScrollbar,
|
||||||
|
NButton,
|
||||||
|
NGrid,
|
||||||
|
NGridItem,
|
||||||
|
NH6,
|
||||||
|
} from "naive-ui";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { setStore } from "@/stores";
|
import { setStore, statusStore } from "@/stores";
|
||||||
|
|
||||||
const set = setStore();
|
const set = setStore();
|
||||||
|
const status = statusStore();
|
||||||
const {
|
const {
|
||||||
backgroundType,
|
backgroundType,
|
||||||
showBackgroundGray,
|
showBackgroundGray,
|
||||||
searchEngine,
|
|
||||||
lastSearchEngine,
|
|
||||||
customEngine,
|
|
||||||
showCleanInput,
|
|
||||||
autoFocus,
|
autoFocus,
|
||||||
autoInputBlur,
|
autoInputBlur,
|
||||||
timeStyle,
|
|
||||||
showSeconds,
|
showSeconds,
|
||||||
showSuggestions,
|
showSuggestions,
|
||||||
urlJumpType,
|
urlJumpType,
|
||||||
} = storeToRefs(set);
|
} = storeToRefs(set);
|
||||||
|
const recoverRef = ref(null);
|
||||||
|
|
||||||
|
// 壁纸类别
|
||||||
|
const backgroundTypeArr = [
|
||||||
|
{ name: "本地默认", tip: "默认壁纸,随机更换" },
|
||||||
|
{ name: "每日必应", tip: "必应每日一图,每天更新" },
|
||||||
|
{ name: "随机风景", tip: "随机风景图,随机更换" },
|
||||||
|
{ name: "随机动漫", tip: "随机二次元图,随机更换" },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 切换壁纸
|
||||||
|
const changeBackground = (type) => {
|
||||||
|
backgroundType.value = type;
|
||||||
|
$message.success("壁纸设置成功,刷新后生效");
|
||||||
|
};
|
||||||
|
|
||||||
// 链接跳转方式
|
// 链接跳转方式
|
||||||
const urlJumpTypeOptions = [
|
const urlJumpTypeOptions = [
|
||||||
@ -101,4 +197,122 @@ const urlJumpTypeOptions = [
|
|||||||
value: "href",
|
value: "href",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 站点重置
|
||||||
|
const resetSite = () => {
|
||||||
|
$noti.dialog({
|
||||||
|
title: "站点重置",
|
||||||
|
content: "确认重置站点为默认状态?你的全部数据以及自定义设置都将丢失!",
|
||||||
|
clickVerify: () => {
|
||||||
|
localStorage.clear();
|
||||||
|
$message.info("站点重置成功,即将刷新");
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 站点备份
|
||||||
|
const backupSite = () => {
|
||||||
|
try {
|
||||||
|
const date = new Date();
|
||||||
|
const dateString = date.toISOString().replace(/[:.]/g, "-");
|
||||||
|
const fileName = `Snavigation_Backup_${dateString}.json`;
|
||||||
|
const jsonData = JSON.stringify(set.$state);
|
||||||
|
const blob = new Blob([jsonData], { type: "application/json" });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileName;
|
||||||
|
a.style.display = "none";
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
// 备份完成
|
||||||
|
$message.success("站点备份成功");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("站点备份失败:", error);
|
||||||
|
$message.error("站点备份失败");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 站点恢复
|
||||||
|
const recoverSite = async () => {
|
||||||
|
try {
|
||||||
|
const fileInput = recoverRef.value;
|
||||||
|
if (!fileInput?.files.length) {
|
||||||
|
$message.error("请选择要恢复的备份文件");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const file = fileInput.files[0];
|
||||||
|
const jsonData = await file.text();
|
||||||
|
const data = JSON.parse(jsonData);
|
||||||
|
// 恢复数据
|
||||||
|
$noti.dialog({
|
||||||
|
title: "站点恢复",
|
||||||
|
content: "确认使用该恢复文件?你现有的数据以及自定义设置都将被覆盖!",
|
||||||
|
clickVerify: () => {
|
||||||
|
const isSuccess = set.recoverSiteData(data);
|
||||||
|
if (isSuccess) {
|
||||||
|
$message.info("站点恢复成功,即将刷新");
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
$message.error("站点数据恢复失败,请重试");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clickCancel: () => {
|
||||||
|
recoverRef.value.value = null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("站点数据恢复失败:", error);
|
||||||
|
$message.error("站点数据恢复失败,请重试");
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.cover-selete {
|
||||||
|
margin-top: 12px;
|
||||||
|
.item {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: var(--main-background-light-color);
|
||||||
|
transition: background-color 0.3s, box-shadow 0.3s;
|
||||||
|
&.check {
|
||||||
|
background-color: var(--main-background-hover-color);
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 14px;
|
||||||
|
top: -4px;
|
||||||
|
left: -4px;
|
||||||
|
right: -4px;
|
||||||
|
bottom: -4px;
|
||||||
|
border: 2px solid var(--main-background-hover-color);
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--main-background-hover-color);
|
||||||
|
box-shadow: 0 0 0px 2px var(--main-background-hover-color);
|
||||||
|
&::before {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- 自定义通知组件 -->
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- 自定义通知组件 -->
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div
|
<div
|
||||||
@ -11,6 +11,7 @@
|
|||||||
<Transition name="fadeDown">
|
<Transition name="fadeDown">
|
||||||
<div v-if="notiShow" :class="['notification-content', notiType]">
|
<div v-if="notiShow" :class="['notification-content', notiType]">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
<SvgIcon iconName="icon-info" />
|
||||||
<div class="title" v-html="notiTitle" />
|
<div class="title" v-html="notiTitle" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content" v-html="notiContent" />
|
<div class="content" v-html="notiContent" />
|
||||||
@ -49,13 +50,13 @@ const allNoti = {
|
|||||||
return console.error("Noti:请传入必要数据");
|
return console.error("Noti:请传入必要数据");
|
||||||
}
|
}
|
||||||
// 获取配置
|
// 获取配置
|
||||||
const { title, content, clickVerify, ClickCancel } = options;
|
const { title, content, clickVerify, clickCancel } = options;
|
||||||
if (!title || !content) return console.error("Noti:参数错误或不完整");
|
if (!title || !content) return console.error("Noti:参数错误或不完整");
|
||||||
// 更改数据
|
// 更改数据
|
||||||
notiTitle.value = title;
|
notiTitle.value = title;
|
||||||
notiContent.value = content;
|
notiContent.value = content;
|
||||||
notiClickVerify.value = clickVerify;
|
notiClickVerify.value = clickVerify;
|
||||||
notiClickCancel.value = ClickCancel;
|
notiClickCancel.value = clickCancel;
|
||||||
notizIndex.value = findMaxZIndex();
|
notizIndex.value = findMaxZIndex();
|
||||||
notiShow.value = true;
|
notiShow.value = true;
|
||||||
},
|
},
|
||||||
@ -120,14 +121,23 @@ onMounted(() => {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
background-color: var(--main-background-light-color);
|
background-color: var(--main-background-light-color);
|
||||||
|
box-shadow: var(--main-box-shadow);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
.header {
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
|
.i-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.content {
|
.content {
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
.actions {
|
.actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -142,6 +152,7 @@ onMounted(() => {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
font-family: "HarmonyOS_Regular", sans-serif;
|
||||||
background-color: var(--main-background-light-color);
|
background-color: var(--main-background-light-color);
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
|
@ -2,8 +2,14 @@
|
|||||||
<Transition name="fadeDown" mode="out-in">
|
<Transition name="fadeDown" mode="out-in">
|
||||||
<div v-if="status.engineChangeStatus" class="engine-choose">
|
<div v-if="status.engineChangeStatus" class="engine-choose">
|
||||||
<n-scrollbar style="max-height: 44.5vh">
|
<n-scrollbar style="max-height: 44.5vh">
|
||||||
<div class="all-engine">
|
<n-grid
|
||||||
<div
|
class="all-engine"
|
||||||
|
responsive="screen"
|
||||||
|
cols="2 s:3 m:4 l:4"
|
||||||
|
:x-gap="10"
|
||||||
|
:y-gap="10"
|
||||||
|
>
|
||||||
|
<n-grid-item
|
||||||
v-for="(item, key) in defaultEngine"
|
v-for="(item, key) in defaultEngine"
|
||||||
:key="key"
|
:key="key"
|
||||||
:class="['engine', key === set.searchEngine ? 'choose' : null]"
|
:class="['engine', key === set.searchEngine ? 'choose' : null]"
|
||||||
@ -11,19 +17,19 @@
|
|||||||
>
|
>
|
||||||
<SvgIcon :iconName="`icon-${key}`" />
|
<SvgIcon :iconName="`icon-${key}`" />
|
||||||
<span class="name">{{ item.name }}</span>
|
<span class="name">{{ item.name }}</span>
|
||||||
</div>
|
</n-grid-item>
|
||||||
<div class="engine" @click="customEngine">
|
<n-grid-item class="engine" @click="customEngine">
|
||||||
<SvgIcon iconName="icon-custom" />
|
<SvgIcon iconName="icon-custom" />
|
||||||
<span class="name">自定义</span>
|
<span class="name">自定义</span>
|
||||||
</div>
|
</n-grid-item>
|
||||||
</div>
|
</n-grid>
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { NScrollbar } from "naive-ui";
|
import { NScrollbar, NGrid, NGridItem } from "naive-ui";
|
||||||
import { statusStore, setStore } from "@/stores";
|
import { statusStore, setStore } from "@/stores";
|
||||||
import defaultEngine from "@/assets/defaultEngine.json";
|
import defaultEngine from "@/assets/defaultEngine.json";
|
||||||
|
|
||||||
@ -60,11 +66,10 @@ const customEngine = () => {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
.all-engine {
|
.all-engine {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: grid;
|
box-sizing: border-box;
|
||||||
gap: 10px;
|
|
||||||
grid-template-columns: repeat(4, minmax(0px, 1fr));
|
|
||||||
.engine {
|
.engine {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -87,10 +92,24 @@ const customEngine = () => {
|
|||||||
}
|
}
|
||||||
&.choose {
|
&.choose {
|
||||||
background-color: var(--main-background-hover-color);
|
background-color: var(--main-background-hover-color);
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 14px;
|
||||||
|
top: -4px;
|
||||||
|
left: -4px;
|
||||||
|
right: -4px;
|
||||||
|
bottom: -4px;
|
||||||
|
border: 2px solid var(--main-background-hover-color);
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--main-background-hover-color);
|
background-color: var(--main-background-hover-color);
|
||||||
box-shadow: 0 0 0px 2px var(--main-background-hover-color);
|
box-shadow: 0 0 0px 2px var(--main-background-hover-color);
|
||||||
|
&::before {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<!-- 搜索框 -->
|
||||||
<div class="search-input" @click.stop>
|
<div class="search-input" @click.stop>
|
||||||
|
<!-- 搜索框遮罩 -->
|
||||||
<div
|
<div
|
||||||
v-if="status.siteStatus === 'focus'"
|
v-if="status.siteStatus === 'focus'"
|
||||||
class="mask"
|
class="mask"
|
||||||
@click="closeSearchInput(false)"
|
@click="closeSearchInput(false)"
|
||||||
|
@contextmenu.stop="
|
||||||
|
(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
|
<!-- 主搜索框 -->
|
||||||
<div
|
<div
|
||||||
ref="searchAllRef"
|
ref="searchAllRef"
|
||||||
:class="status.siteStatus === 'focus' ? 'all focus' : 'all'"
|
:class="status.siteStatus === 'focus' ? 'all focus' : 'all'"
|
||||||
@ -38,7 +46,7 @@
|
|||||||
<SvgIcon iconName="icon-search" className="search" />
|
<SvgIcon iconName="icon-search" className="search" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 搜索引擎 -->
|
<!-- 搜索引擎切换 -->
|
||||||
<SearchEngine />
|
<SearchEngine />
|
||||||
<!-- 搜索建议 -->
|
<!-- 搜索建议 -->
|
||||||
<Suggestions
|
<Suggestions
|
||||||
@ -158,8 +166,9 @@ const pressKeyboard = (event) => {
|
|||||||
|
|
||||||
// 更换搜索引擎
|
// 更换搜索引擎
|
||||||
const changeEngine = () => {
|
const changeEngine = () => {
|
||||||
status.setSiteStatus("focus");
|
status.setSiteStatus("focus", false);
|
||||||
status.setEngineChangeStatus(!status.engineChangeStatus);
|
status.setEngineChangeStatus(!status.engineChangeStatus);
|
||||||
|
console.log(status.engineChangeStatus);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="`weather-time ${status.siteStatus}`" @click.stop>
|
<!-- 天气时钟 -->
|
||||||
|
<div
|
||||||
|
:class="[
|
||||||
|
'weather-time',
|
||||||
|
status.siteStatus,
|
||||||
|
status.mainBoxBig &&
|
||||||
|
status.siteStatus !== 'normal' &&
|
||||||
|
status.siteStatus !== 'focus'
|
||||||
|
? 'hidden'
|
||||||
|
: null,
|
||||||
|
]"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
:class="['time', set.timeStyle]"
|
:class="['time', set.timeStyle]"
|
||||||
@click.stop="
|
@click.stop="
|
||||||
@ -119,7 +131,7 @@ onBeforeUnmount(() => {
|
|||||||
transform: translateY(-140px);
|
transform: translateY(-140px);
|
||||||
color: var(--main-text-color);
|
color: var(--main-text-color);
|
||||||
animation: fade-time-in 0.6s cubic-bezier(0.21, 0.78, 0.36, 1);
|
animation: fade-time-in 0.6s cubic-bezier(0.21, 0.78, 0.36, 1);
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s, opacity 0.5s;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
&.focus {
|
&.focus {
|
||||||
transform: translateY(-180px);
|
transform: translateY(-180px);
|
||||||
@ -128,6 +140,10 @@ onBeforeUnmount(() => {
|
|||||||
&.set {
|
&.set {
|
||||||
transform: translateY(-220px);
|
transform: translateY(-220px);
|
||||||
}
|
}
|
||||||
|
&.hidden {
|
||||||
|
transform: translateY(-180px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
.time {
|
.time {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 3rem;
|
font-size: 3rem;
|
||||||
|
@ -6,6 +6,7 @@ const useSetDataStore = defineStore("setData", {
|
|||||||
// 壁纸类别
|
// 壁纸类别
|
||||||
// 0 本地 / 1 必应 / 2 随机风景 / 3 随机动漫 / 4 自定义
|
// 0 本地 / 1 必应 / 2 随机风景 / 3 随机动漫 / 4 自定义
|
||||||
backgroundType: 2,
|
backgroundType: 2,
|
||||||
|
backgroundCustom: "",
|
||||||
// 壁纸遮罩
|
// 壁纸遮罩
|
||||||
showBackgroundGray: true,
|
showBackgroundGray: true,
|
||||||
// 搜索引擎
|
// 搜索引擎
|
||||||
@ -36,6 +37,23 @@ const useSetDataStore = defineStore("setData", {
|
|||||||
// 设置新引擎
|
// 设置新引擎
|
||||||
this.searchEngine = value;
|
this.searchEngine = value;
|
||||||
},
|
},
|
||||||
|
// 恢复数据
|
||||||
|
recoverSiteData(data) {
|
||||||
|
let isSuccess = false;
|
||||||
|
try {
|
||||||
|
for (const key in data) {
|
||||||
|
if (Object.hasOwnProperty.call(data, key)) {
|
||||||
|
const item = data[key];
|
||||||
|
this[key] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isSuccess = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("站点数据恢复时处理失败:", error);
|
||||||
|
isSuccess = false;
|
||||||
|
}
|
||||||
|
return isSuccess;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// 开启数据持久化
|
// 开启数据持久化
|
||||||
persist: {
|
persist: {
|
||||||
|
@ -12,6 +12,8 @@ const useStatusDataStore = defineStore("statusData", {
|
|||||||
engineChangeStatus: false,
|
engineChangeStatus: false,
|
||||||
// 搜索框文本
|
// 搜索框文本
|
||||||
searchInputValue: "",
|
searchInputValue: "",
|
||||||
|
// 盒子大小
|
||||||
|
mainBoxBig: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
@ -19,9 +21,10 @@ const useStatusDataStore = defineStore("statusData", {
|
|||||||
setImgLoadStatus(value) {
|
setImgLoadStatus(value) {
|
||||||
this.imgLoadStatus = value;
|
this.imgLoadStatus = value;
|
||||||
},
|
},
|
||||||
setSiteStatus(value) {
|
setSiteStatus(value, alsoChange = true) {
|
||||||
this.siteStatus = value;
|
this.siteStatus = value;
|
||||||
this.searchInputValue = "";
|
this.searchInputValue = "";
|
||||||
|
if (alsoChange) this.engineChangeStatus = false;
|
||||||
},
|
},
|
||||||
setEngineChangeStatus(value) {
|
setEngineChangeStatus(value) {
|
||||||
this.engineChangeStatus = value;
|
this.engineChangeStatus = value;
|
||||||
@ -29,6 +32,15 @@ const useStatusDataStore = defineStore("statusData", {
|
|||||||
setSearchInputValue(value) {
|
setSearchInputValue(value) {
|
||||||
this.searchInputValue = value;
|
this.searchInputValue = value;
|
||||||
},
|
},
|
||||||
|
setMainBoxBig(value) {
|
||||||
|
this.mainBoxBig = value;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 开启数据持久化
|
||||||
|
persist: {
|
||||||
|
key: "statusData",
|
||||||
|
storage: window.localStorage,
|
||||||
|
paths: ["mainBoxBig"],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user