支持设置背景图片,不再局限于面板模式,支持设置毛玻璃效果

This commit is contained in:
fofolee
2024-12-19 00:39:44 +08:00
parent be663fc4e3
commit 45780a2e0c
11 changed files with 1749 additions and 669 deletions

View File

@@ -15,7 +15,7 @@ import programmings from "./js/options/programs.js";
import defaultProfile from "./js/options/defaultProfile.js";
import Cron from "croner";
import QuickCommand from "components/quickcommandUI/QuickCommand";
import autoDetach from "./js/autoDetach.js";
// import autoDetach from "./js/autoDetach.js";
export default defineComponent({
components: { QuickCommand },
@@ -122,7 +122,7 @@ export default defineComponent({
this.enterData = enter;
// 自动分离目前还没有好的方案
// if (this.$root.profile.autoDetachFeatures?.includes(enter.code)) {
// autoDetach.autoDetach();
// autoDetach.autoDetach();
// }
this.$router.push(enter.code);
},
@@ -240,5 +240,16 @@ export default defineComponent({
this.utools.setStorage("st_v300Inited", true);
},
},
watch: {
// 监听 glassEffect 值变化
'profile.glassEffect': {
immediate: true,
handler(val) {
// 给 body 添加 glass-effect-menu 类和强度值
document.body.classList.toggle('glass-effect-menu', val > 0);
document.body.style.setProperty('--glass-effect-strength', val);
}
}
}
});
</script>

View File

@@ -124,7 +124,7 @@
:class="{
featureIco: 1,
featureIcoHover: isWarpperHover,
'feature-disabled': !isCommandActivated
'feature-disabled': !isCommandActivated,
}"
>
<img :src="commandInfo.features.icon" />
@@ -141,7 +141,7 @@
v-html="commandInfo.features.explain.trim() || '<br/>'"
/>
</div>
<!-- 配模式 -->
<!-- 配模式 -->
<div class="row">
<div
:class="
@@ -170,10 +170,7 @@
:color="matchTypeColor(cmd.type)"
:class="cardBadgeClass"
>
<q-icon
class="q-mr-xs"
:name="commandTypes.window.icon"
/>
<q-icon class="q-mr-xs" :name="commandTypes.window.icon" />
{{ getShortStrByByte(cmd.match.app[0]) }}
</q-badge>
<q-tooltip>
@@ -209,10 +206,7 @@
:color="matchTypeColor(cmd.type)"
:class="cardBadgeClass"
>
<q-icon
class="q-mr-xs"
:name="commandTypes.regex.icon"
/>
<q-icon class="q-mr-xs" :name="commandTypes.regex.icon" />
{{ getShortStrByByte(cmd.match) }}
</q-badge>
<q-tooltip>
@@ -351,7 +345,7 @@ export default {
matchTypeColor() {
return (cmdType = "key") => {
if (!this.canCommandRunAtCurrentOS || !this.isCommandActivated) {
return this.$q.dark.isActive ? 'grey-9' : this.disabledColor;
return this.$q.dark.isActive ? "grey-9" : this.disabledColor;
}
return this.commandTypes[cmdType].color;
};
@@ -371,9 +365,10 @@ export default {
return this.$root.nativeProfile.crontabs[this.featureCode];
},
cardBadgeClass() {
return (!this.canCommandRunAtCurrentOS || !this.isCommandActivated) && this.$q.dark.isActive
? 'text-grey-6'
: '';
return (!this.canCommandRunAtCurrentOS || !this.isCommandActivated) &&
this.$q.dark.isActive
? "text-grey-6"
: "";
},
},
props: {
@@ -454,7 +449,9 @@ export default {
// 导出到剪贴板
exportCommandRaw() {
utools.copyText(JSON.stringify(this.getRawCommand(), null, 4)) &&
utools.showNotification(`${this.commandInfo.features.explain}」已复制到剪贴板`);
utools.showNotification(
`${this.commandInfo.features.explain}」已复制到剪贴板`
);
},
// 导出到文件
exportCommandFile() {
@@ -478,8 +475,21 @@ export default {
.q-card.command {
cursor: pointer;
user-select: none;
background: #ffffff08;
transition: 0.5s;
transition: all 0.3s ease;
background: rgba(255, 255, 255, 0.3) !important;
backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
-webkit-backdrop-filter: blur(
calc(var(--glass-effect-strength) * 1px)
) !important;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 16px 0 rgba(31, 38, 135, 0.07);
}
.body--dark .q-card.command {
background: rgba(57, 57, 57, 0.09) !important;
border: 1px solid rgb(59 58 58 / 5%);
box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%),
0 3px 1px -2px rgb(69 67 67 / 12%);
}
.q-badge {

View File

@@ -235,7 +235,7 @@
/>
</template>
<q-tooltip
>一个可以直接运行代码的代码编辑器<br />
>一个可以代码的代码编辑器<br />
也可在主输入框输入关键字「RunCode」进入
</q-tooltip>
</q-field>
@@ -319,62 +319,105 @@
<q-icon name="color_lens" />
</q-item-section>
<q-item-section>主颜色</q-item-section>
<q-tooltip>你可以更改界面的主题色,会员限定</q-tooltip>
<q-tooltip>你可以更改界面的主题色,会员限定 😎</q-tooltip>
<q-menu
v-if="$refs.user.isVIP"
nchor="top left"
self="bottom end"
style="min-width: 200px; min-height: 200px"
>
<q-card>
<q-color
@change="setPrimaryColor"
v-model="$root.profile.primaryColor"
/>
<q-btn
color="primary"
label="重置为默认"
class="full-width"
@click="resetPrimary"
/>
</q-card>
<q-color
@change="setPrimaryColor"
v-model="$root.profile.primaryColor"
/>
<q-btn
color="primary"
label="重置为默认"
class="full-width"
@click="resetPrimary"
/>
</q-menu>
</q-item>
<q-item clickable :disable="!$refs.user.isVIP">
<q-item-section side>
<q-icon name="image" />
</q-item-section>
<q-item-section>面板视图背景图片</q-item-section>
<q-tooltip
>为面板视图设置一张背景图片,会员限定<br />请不要选择尺寸太大的图片,将影响插件载入速度</q-tooltip
>
<q-item-section>背景图片设置</q-item-section>
<q-tooltip>设置背景图片,会员限定 😎</q-tooltip>
<q-menu
v-if="$refs.user.isVIP"
nchor="top left"
anchor="top left"
self="bottom end"
>
<q-card>
<q-file
dense
standout="bg-primary text-white"
v-model="selectFile"
autofocus
@update:model-value="changeBackground()"
accept="image/*"
label="请选择一张图片"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
<q-card-section>
<div class="text-subtitle2">亮色模式背景</div>
<q-file
dense
standout="bg-primary text-white"
v-model="selectFileLight"
autofocus
@update:model-value="setBackgroundImg('light')"
accept="image/*"
label="请选择一张图片"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</q-card-section>
<q-card-section>
<div class="text-subtitle2">暗色模式背景</div>
<q-file
dense
standout="bg-primary text-white"
v-model="selectFileDark"
@update:model-value="setBackgroundImg('dark')"
accept="image/*"
label="请选择一张图片"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</q-card-section>
<q-btn
color="negative"
label="取消背景"
class="full-width"
@click="changeBackground(1)"
@click="removeBackgroundImg()"
/>
</q-card>
</q-menu>
</q-item>
<!-- 毛玻璃效果滑块 -->
<q-item>
<q-item-section side>
<q-icon name="blur_on" />
</q-item-section>
<q-item-section class="flex">毛玻璃效果</q-item-section>
<q-tooltip
>启用毛玻璃界面,并调节效果强度,会员限定 😎</q-tooltip
>
<q-item-section side>
<div
class="flex items-center justify-center"
style="width: 56px"
>
<q-knob
v-model="$root.profile.glassEffect"
:min="0"
:max="12"
color="primary"
:thickness="0.6"
size="24px"
track-color="grey-3"
@change="toggleGlassEffect"
class="q-mx-auto"
/>
</div>
</q-item-section>
</q-item>
<q-item clickable :disable="!$refs.user.isVIP">
<q-item-section side>
<q-icon name="label" />
@@ -386,6 +429,7 @@
v-model="$root.profile.denseTagBar"
:disable="!$refs.user.isVIP"
color="primary"
@update:model-value="$root.saveProfile"
/></q-item-section>
</q-item>
<q-item clickable>
@@ -398,6 +442,7 @@
><q-toggle
v-model="$root.profile.autofocusSearch"
color="primary"
@update:model-value="$root.saveProfile"
/></q-item-section>
</q-item>
<!-- 自动分离 -->
@@ -495,7 +540,8 @@ export default {
data() {
return {
setCssVar: setCssVar,
selectFile: ref(null),
selectFileLight: null,
selectFileDark: null,
showAbout: false,
showPanelConf: false,
showUserDara: false,
@@ -565,17 +611,34 @@ export default {
// 设置主题色
setPrimaryColor() {
this.setCssVar("primary", this.$root.profile.primaryColor);
this.$root.saveProfile();
},
// 重置主题色
resetPrimary() {
this.$root.profile.primaryColor = this.$root.profile.defaultPrimaryColor;
this.setPrimaryColor();
},
// 修改面板视图背景
changeBackground(reset = false) {
let base64 = window.getBase64Ico(this.selectFile.path);
this.$root.profile.backgroundImg = reset ? null : base64;
this.configurationPage.$forceUpdate();
// 修改背景
async setBackgroundImg(mode) {
const file =
mode === "light" ? this.selectFileLight : this.selectFileDark;
if (!file) return;
// 使用 Node.js 处理图片
const processedImage = await window.imageProcessor(file.path);
// 更新配置
if (mode === "light") {
this.$root.profile.backgroundImgLight = processedImage;
} else {
this.$root.profile.backgroundImgDark = processedImage;
}
this.$root.saveProfile();
},
removeBackgroundImg() {
this.$root.profile.backgroundImgLight = "";
this.$root.profile.backgroundImgDark = "";
this.$root.saveProfile();
},
// 取消收藏
unMarkTag() {
@@ -628,6 +691,76 @@ export default {
this.showAutoDetachFeatures = false;
quickcommand.showMessageBox("设置成功");
},
toggleGlassEffect(val) {
this.$root.profile.glassEffect = val;
this.$root.saveProfile();
},
},
};
</script>
<style>
/* 基础菜单样式 - 始终保持最小毛玻璃效果 */
.q-menu {
background: rgba(255, 255, 255, 0.15) !important;
backdrop-filter: blur(5px) !important;
-webkit-backdrop-filter: blur(5px) !important;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 16px 0 rgba(31, 38, 135, 0.07);
}
.body--dark .q-menu {
background: rgba(0, 0, 0, 0.2) !important;
border: 1px solid rgba(255, 255, 255, 0.05);
}
/* 毛玻璃菜单效果 - 叠加用户设置的效果 */
body.glass-effect-menu .q-menu {
background: rgba(
255,
255,
255,
calc(0.15 + var(--glass-effect-strength) * 0.01)
) !important;
backdrop-filter: blur(
calc(5px + var(--glass-effect-strength) * 1px)
) !important;
-webkit-backdrop-filter: blur(
calc(5px + var(--glass-effect-strength) * 1px)
) !important;
}
/* 暗色模式菜单 */
body.body--dark.glass-effect-menu .q-menu {
background: rgba(
0,
0,
0,
calc(0.2 + var(--glass-effect-strength) * 0.02)
) !important;
}
/* 菜单列表透明背景 */
.q-menu .q-list {
background: transparent !important;
}
/* 菜单项浮效果 */
.q-menu .q-item:hover {
background: rgba(255, 255, 255, 0.1) !important;
}
.body--dark .q-menu .q-item:hover {
background: rgba(255, 255, 255, 0.05) !important;
}
/* 输入框样式 */
.q-menu .q-field__control {
background: rgba(255, 255, 255, 0.15) !important;
border-radius: 4px;
}
.body--dark .q-menu .q-field__control {
background: rgba(0, 0, 0, 0.3) !important;
}
</style>

View File

@@ -92,7 +92,7 @@
</div>
<div class="row items-center q-mr-lg">
<q-icon size="sm" name="image" class="q-mr-sm"></q-icon>
为面板视图设置背景图片
设置背景图片以及开启毛玻璃效果
</div>
<div class="row items-center q-mr-lg">
<q-icon size="sm" name="label" class="q-mr-sm"></q-icon>

View File

@@ -160,3 +160,46 @@ body {
.q-tooltip[data-v-anchor="center right"] {
transform-origin: center left;
}
.full-height {
height: 100vh;
}
.config-page-container {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
}
.background-layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
/* 毛玻璃效果叠加 */
body.glass-effect-menu .q-card.command {
background: rgba(255, 255, 255, calc(0.3 + var(--glass-effect-strength) * 0.01)) !important;
}
body.body--dark.glass-effect-menu .q-card.command {
background: rgba(30, 30, 30, calc(0.3 + var(--glass-effect-strength) * 0.02)) !important;
}
/* 标签栏毛玻璃效果 */
body.glass-effect-menu .q-tabs {
background: rgba(255, 255, 255, calc(0.15 + var(--glass-effect-strength) * 0.01)) !important;
backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
-webkit-backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
border-right: 1px solid rgba(255, 255, 255, 0.1);
}
body.body--dark.glass-effect-menu .q-tabs {
background: rgba(0, 0, 0, calc(0.2 + var(--glass-effect-strength) * 0.02)) !important;
border-right: 1px solid rgba(255, 255, 255, 0.05);
}

View File

@@ -3,7 +3,8 @@ export default {
commandCardStyle: "dense",
primaryColor: "#009688",
defaultPrimaryColor: "#009688",
backgroundImg: null,
backgroundImgLight: "",
backgroundImgDark: "",
autofocusSearch: false,
denseTagBar: false,
quickFileEnable: false,
@@ -13,6 +14,7 @@ export default {
pluNickNameEnable: false,
pluNickNameTag: "别名",
autoDetachFeatures: [],
glassEffect: 0,
},
native: {
crontabs: {},

View File

@@ -1,5 +1,21 @@
<template>
<div class="relative">
<div class="config-page-container">
<div
class="background-layer"
:style="{
background: $q.dark.isActive
? $root.profile.backgroundImgDark
? `url('${$root.profile.backgroundImgDark}')`
: 'none'
: $root.profile.backgroundImgLight
? `url('${$root.profile.backgroundImgLight}')`
: 'none',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundAttachment: 'fixed',
}"
></div>
<!-- 标签栏 -->
<!-- 面板视图不显示标签栏 -->
<q-scroll-area
@@ -17,8 +33,6 @@
v-model="currentTag"
vertical
switch-indicator
active-class="text-primary text-weight-bolder"
content-class="text-blue-grey"
:key="$root.profile.denseTagBar"
:dense="$root.profile.denseTagBar"
>
@@ -27,11 +41,8 @@
v-for="tag in allQuickCommandTags"
:key="tag"
:name="tag"
:content-class="
tag === '搜索结果' || activatedQuickPanels.includes(tag)
? 'text-blue-7 text-weight-bolder'
: ''
"
:data-search-result="tag === '搜索结果'"
:data-active-panel="activatedQuickPanels.includes(tag)"
>
{{ tag }}
<q-tooltip v-if="tag === '未分类'">
@@ -48,16 +59,10 @@
:style="{
bottom: footerBarHeight,
left: tabBarWidth,
background:
commandCardStyle === 'mini' && $root.profile.backgroundImg
? `url('${$root.profile.backgroundImg}')`
: 'none',
backgroundSize: 'cover',
}"
v-model="currentTag"
transition-prev="fade"
transition-next="fade"
swipeable
transition-prev="slide-down"
transition-next="slide-up"
>
<q-tab-panel
style="padding: 0"
@@ -131,7 +136,7 @@
@click="$q.dark.toggle()"
>
<q-tooltip>
{{ $q.dark.isActive ? '切换到亮色模式' : '切换到暗色模式' }}
{{ $q.dark.isActive ? "切换到亮色模式" : "切换到暗色模式" }}
</q-tooltip>
</q-btn>
<!-- 切换视图 -->
@@ -373,7 +378,7 @@ export default {
// 启用的面板
this.activatedQuickPanels = quickpanels;
},
// 获取所有的快捷命令(导出的格式)
// 获取所有的命令(导出的格式)
getAllQuickCommands() {
this.allQuickCommands = _.cloneDeep(defaultCommands);
this.$root.utools.getAll("qc_").forEach((x) => {
@@ -392,7 +397,7 @@ export default {
])
.filter((x) => x);
},
// 监听命令变更
// 监听命令变更件
commandChanged(event) {
switch (event.type) {
case "remove":
@@ -457,7 +462,7 @@ export default {
};
this.isCommandEditorShow = true;
},
// 是否为认命令
// 是否为认命令
isDefaultCommand(code) {
return code.slice(0, 8) === "default_";
},
@@ -494,9 +499,10 @@ export default {
this.$nextTick(() => {
let el = document.getElementById(code);
el.scrollIntoViewIfNeeded();
el.querySelector('.q-card').style.boxShadow = "0px 1px var(--q-primary)";
el.querySelector(".q-card").style.boxShadow =
"0px 1px var(--q-primary)";
setTimeout(() => {
el.querySelector('.q-card').style.boxShadow = "";
el.querySelector(".q-card").style.boxShadow = "";
}, 5000);
// 跳转标签
document
@@ -504,7 +510,7 @@ export default {
.scrollIntoView({ behavior: "smooth" });
});
},
// 修改并定位当前标签
// 修改并定位当前标签事件
changeCurrentTag(tagName) {
this.currentTag = tagName;
this.$nextTick(() => {
@@ -575,7 +581,7 @@ export default {
// 搜索时跳转到搜索结果标签
this.changeCurrentTag(searchTagName);
} else {
// 清空搜索回跳到前标签
// 清空搜索回跳到前标签
if (this.allQuickCommandTags.slice(-1)[0] === searchTagName)
this.allQuickCommandTags.pop();
if (this.currentTag !== this.lastTag)
@@ -639,20 +645,42 @@ export default {
</script>
<style scoped>
/* 标签栏容器样式 */
.q-tabs {
height: 100vh !important;
background: transparent !important;
}
/* 标签栏和底栏内的按钮悬浮效果 */
.q-tabs .q-tab:hover,
.absolute-bottom .q-btn:hover {
background: rgba(255, 255, 255, 0.1) !important;
}
.body--dark .q-tabs .q-tab:hover,
.body--dark .absolute-bottom .q-btn:hover {
background: rgba(255, 255, 255, 0.05) !important;
}
.q-tab {
word-break: break-all;
white-space: normal;
position: relative;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
color: var(--q-blue-grey) !important;
opacity: 0.7;
transition: all 0.3s ease;
}
/* 标签悬浮效果 */
.q-tab:hover {
transform: translateX(4px);
/* 激活标签样式 */
.q-tab--active {
color: var(--q-primary) !important;
font-weight: 600 !important;
opacity: 1;
}
.q-tab:hover::after {
content: '';
content: "";
position: absolute;
left: 0;
bottom: 0;
@@ -664,6 +692,19 @@ export default {
transition: opacity 0.3s;
}
/* 特殊标签样式(搜索结果和激活面板) */
.q-tab[data-search-result="true"],
.q-tab[data-active-panel="true"] {
color: #4286de !important;
font-weight: 600 !important;
}
/* 标签悬浮效果 */
.q-tab:hover {
opacity: 0.9;
transform: translateX(4px);
}
/* 标签内容过渡效果 */
.q-tab__content {
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
@@ -672,11 +713,12 @@ export default {
/* 面板过渡效果 */
.q-tab-panels {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: none !important;
}
.q-tab-panel {
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 暗色模式适配 */
@@ -686,10 +728,53 @@ export default {
/* 标签滚动区域样式 */
.q-scroll-area {
background: rgba(0, 0, 0, 0.02);
background: transparent;
}
:deep(.body--dark) .q-scroll-area {
background: rgba(255, 255, 255, 0.03);
background: transparent;
}
/* 底栏输入框样式 */
.absolute-bottom .q-field__control {
background: rgba(255, 255, 255, 0.15) !important;
border-radius: 4px;
}
.body--dark .absolute-bottom .q-field__control {
background: rgba(0, 0, 0, 0.2) !important;
}
/* 底栏毛玻璃效果 */
body.glass-effect-menu .absolute-bottom {
background: rgba(
255,
255,
255,
calc(0.15 + var(--glass-effect-strength) * 0.01)
) !important;
backdrop-filter: blur(calc(var(--glass-effect-strength) * 1px)) !important;
-webkit-backdrop-filter: blur(
calc(var(--glass-effect-strength) * 1px)
) !important;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
body.body--dark.glass-effect-menu .absolute-bottom {
background: rgba(
0,
0,
0,
calc(0.2 + var(--glass-effect-strength) * 0.02)
) !important;
border-top: 1px solid rgba(255, 255, 255, 0.05);
}
/* 调整内容层级 */
.q-scroll-area,
.q-tab-panels,
.absolute-bottom {
position: absolute;
z-index: 1;
}
</style>