Feat: add dark bg img mode

This commit is contained in:
unitwk 2024-01-15 20:37:44 +08:00
parent 6c89c30948
commit 72d40f2643
9 changed files with 305 additions and 22 deletions

3
common/global.d.ts vendored
View File

@ -145,6 +145,9 @@ export interface IMapData<T> {
export interface IPageLayoutConfig {
page: string;
items: ILayoutCard[];
theme?: {
backgroundImage: string;
};
}
export interface ILayoutCardParams {

View File

@ -2,14 +2,32 @@
import AppConfigProvider from "./components/AppConfigProvider.vue";
import { RouterView } from "vue-router";
import AppHeader from "./components/AppHeader.vue";
import { onMounted } from "vue";
import { onMounted, ref } from "vue";
import { useAppConfigStore } from "@/stores/useAppConfigStore";
import InputDialogProvider from "./components/InputDialogProvider.vue";
import { Button, Select, Input, Table } from "ant-design-vue";
import MyselfInfoDialog from "./components/MyselfInfoDialog.vue";
import { closeAppLoading } from "./tools/dom";
import { useLayoutConfigStore } from "./stores/useLayoutConfig";
const { isDarkTheme } = useAppConfigStore();
const { isDarkTheme, setTheme } = useAppConfigStore();
const { getSettingsConfig } = useLayoutConfigStore();
const hasBgImage = ref(false);
function setBackground(url: string) {
const body = document.querySelector("body");
if (body) {
body.style.backgroundImage = `url(${url})`;
body.style.backgroundSize = "cover";
body.style.backgroundPosition = "center";
body.style.backgroundRepeat = "no-repeat";
isDarkTheme()
? body.classList.add("app-dark-extend-theme")
: body.classList.add("app-light-extend-theme");
}
hasBgImage.value = true;
}
if (isDarkTheme()) {
document.body.classList.add("app-dark-theme");
@ -22,12 +40,15 @@ if (isDarkTheme()) {
});
onMounted(async () => {
const frontendSettings = await getSettingsConfig();
if (frontendSettings?.theme?.backgroundImage)
setBackground(frontendSettings.theme.backgroundImage);
closeAppLoading();
});
</script>
<template>
<AppConfigProvider>
<AppConfigProvider :has-bg-image="hasBgImage">
<div class="global-app-container">
<AppHeader></AppHeader>
<RouterView :key="$route.fullPath" />

View File

@ -0,0 +1,161 @@
.app-light-extend-theme {
--background-color-white: #ffffffae;
.card-panel {
backdrop-filter: blur(10px);
}
}
.app-dark-extend-theme {
--level-1-bg-color: #000000af;
--level-2-bg-color: #0000006b;
--background-color-white: var(--level-1-bg-color);
.card-panel {
backdrop-filter: blur(10px);
}
.menu-body {
.left-menu {
background-color: var(--level-2-bg-color) !important;
}
}
.action-btn-item {
background-color: var(--level-2-bg-color) !important;
}
.ant-table-thead,
.ant-table {
background-color: var(--level-2-bg-color) !important;
}
// --color-red-1: rgba(42, 18, 21, 0.8);
// --color-red-2: rgba(67, 20, 24, 0.8);
// --color-red-3: rgba(88, 24, 28, 0.8);
// --color-red-4: rgba(121, 26, 31, 0.8);
// --color-red-5: rgba(166, 29, 36, 0.8);
// --color-red-6: rgba(211, 32, 41, 0.8);
// --color-red-7: rgba(232, 71, 73, 0.8);
// --color-red-8: rgba(243, 115, 115, 0.8);
// --color-red-9: rgba(248, 159, 154, 0.8);
// --color-red-10: rgba(250, 200, 195, 0.8);
// --color-volcano-1: rgba(43, 22, 17, 0.8);
// --color-volcano-2: rgba(68, 29, 18, 0.8);
// --color-volcano-3: rgba(89, 39, 22, 0.8);
// --color-volcano-4: rgba(124, 49, 24, 0.8);
// --color-volcano-5: rgba(170, 62, 25, 0.8);
// --color-volcano-6: rgba(216, 74, 27, 0.8);
// --color-volcano-7: rgba(232, 112, 64, 0.8);
// --color-volcano-8: rgba(243, 147, 106, 0.8);
// --color-volcano-9: rgba(248, 182, 146, 0.8);
// --color-volcano-10: rgba(250, 212, 188, 0.8);
// --color-orange-1: rgba(43, 29, 17, 0.8);
// --color-orange-2: rgba(68, 42, 17, 0.8);
// --color-orange-3: rgba(89, 56, 21, 0.8);
// --color-orange-4: rgba(124, 74, 21, 0.8);
// --color-orange-5: rgba(170, 98, 21, 0.8);
// --color-orange-6: rgba(216, 122, 22, 0.8);
// --color-orange-7: rgba(232, 154, 60, 0.8);
// --color-orange-8: rgba(243, 183, 101, 0.8);
// --color-orange-9: rgba(248, 207, 141, 0.8);
// --color-orange-10: rgba(250, 227, 183, 0.8);
// --color-gold-1: rgba(43, 33, 17, 0.8);
// --color-gold-2: rgba(68, 49, 17, 0.8);
// --color-gold-3: rgba(89, 66, 20, 0.8);
// --color-gold-4: rgba(124, 89, 20, 0.8);
// --color-gold-5: rgba(170, 119, 20, 0.8);
// --color-gold-6: rgba(216, 150, 20, 0.8);
// --color-gold-7: rgba(232, 179, 57, 0.8);
// --color-gold-8: rgba(243, 204, 98, 0.8);
// --color-gold-9: rgba(248, 223, 139, 0.8);
// --color-gold-10: rgba(250, 237, 181, 0.8);
// --color-yellow-1: rgba(43, 38, 17, 0.8);
// --color-yellow-2: rgba(68, 59, 17, 0.8);
// --color-yellow-3: rgba(89, 80, 20, 0.8);
// --color-yellow-4: rgba(124, 110, 20, 0.8);
// --color-yellow-5: rgba(170, 149, 20, 0.8);
// --color-yellow-6: rgba(216, 189, 20, 0.8);
// --color-yellow-7: rgba(232, 214, 57, 0.8);
// --color-yellow-8: rgba(243, 234, 98, 0.8);
// --color-yellow-9: rgba(248, 244, 139, 0.8);
// --color-yellow-10: rgba(250, 250, 181, 0.8);
// --color-lime-1: rgba(31, 38, 17, 0.8);
// --color-lime-2: rgba(46, 60, 16, 0.8);
// --color-lime-3: rgba(62, 79, 19, 0.8);
// --color-lime-4: rgba(83, 109, 19, 0.8);
// --color-lime-5: rgba(111, 148, 18, 0.8);
// --color-lime-6: rgba(139, 187, 17, 0.8);
// --color-lime-7: rgba(169, 209, 52, 0.8);
// --color-lime-8: rgba(201, 231, 81, 0.8);
// --color-lime-9: rgba(228, 248, 143, 0.8);
// --color-lime-10: rgba(240, 250, 181, 0.8);
// --color-green-1: rgba(22, 35, 18, 0.8);
// --color-green-2: rgba(29, 55, 18, 0.8);
// --color-green-3: rgba(39, 73, 25, 0.8);
// --color-green-4: rgba(48, 99, 23, 0.8);
// --color-green-5: rgba(60, 134, 24, 0.8);
// --color-green-6: rgba(73, 170, 25, 0.8);
// --color-green-7: rgba(106, 190, 57, 0.8);
// --color-green-8: rgba(143, 212, 100, 0.8);
// --color-green-9: rgba(178, 229, 139, 0.8);
// --color-green-10: rgba(213, 242, 187, 0.8);
// --color-cyan-1: rgba(17, 33, 35, 0.8);
// --color-cyan-2: rgba(17, 53, 54, 0.8);
// --color-cyan-3: rgba(20, 72, 72, 0.8);
// --color-cyan-4: rgba(20, 98, 98, 0.8);
// --color-cyan-5: rgba(19, 133, 133, 0.8);
// --color-cyan-6: rgba(19, 168, 168, 0.8);
// --color-cyan-7: rgba(51, 188, 183, 0.8);
// --color-cyan-8: rgba(86, 209, 201, 0.8);
// --color-cyan-9: rgba(132, 226, 216, 0.8);
// --color-cyan-10: rgba(178, 241, 232, 0.8);
// --color-blue-1: rgba(17, 26, 44, 0.8);
// --color-blue-2: rgba(17, 37, 69, 0.8);
// --color-blue-3: rgba(21, 50, 91, 0.8);
// --color-blue-4: rgba(21, 65, 126, 0.8);
// --color-blue-5: rgba(21, 84, 173, 0.8);
// --color-blue-6: rgba(22, 104, 220, 0.8);
// --color-blue-7: rgba(60, 137, 232, 0.8);
// --color-blue-8: rgba(105, 169, 243, 0.8);
// --color-blue-9: rgba(141, 197, 248, 0.8);
// --color-blue-10: rgba(183, 220, 250, 0.8);
// --color-geekblue-1: rgba(19, 22, 41, 0.8);
// --color-geekblue-2: rgba(22, 29, 64, 0.8);
// --color-geekblue-3: rgba(28, 39, 85, 0.8);
// --color-geekblue-4: rgba(32, 49, 117, 0.8);
// --color-geekblue-5: rgba(38, 62, 160, 0.8);
// --color-geekblue-6: rgba(43, 74, 202, 0.8);
// --color-geekblue-7: rgba(82, 115, 224, 0.8);
// --color-geekblue-8: rgba(127, 159, 243, 0.8);
// --color-geekblue-9: rgba(168, 193, 248, 0.8);
// --color-geekblue-10: rgba(210, 224, 250, 0.8);
// --color-purple-1: rgba(26, 19, 37, 0.8);
// --color-purple-2: rgba(36, 22, 58, 0.8);
// --color-purple-3: rgba(48, 28, 76, 0.8);
// --color-purple-4: rgba(62, 32, 94, 0.8);
// --color-purple-5: rgba(81, 37, 143, 0.8);
// --color-purple-6: rgba(100, 42, 181, 0.8);
// --color-purple-7: rgba(133, 78, 202, 0.8);
// --color-purple-8: rgba(171, 122, 224, 0.8);
// --color-purple-9: rgba(204, 168, 240, 0.8);
// --color-purple-10: rgba(235, 215, 250, 0.8);
// --color-magenta-1: rgba(41, 19, 33, 0.8);
// --color-magenta-2: rgba(64, 22, 49, 0.8);
// --color-magenta-3: rgba(85, 28, 59, 0.8);
// --color-magenta-4: rgba(117, 32, 79, 0.8);
// --color-magenta-5: rgba(160, 38, 105, 0.8);
// --color-magenta-6: rgba(203, 43, 131, 0.8);
// --color-magenta-7: rgba(224, 82, 156, 0.8);
// --color-magenta-8: rgba(243, 127, 183, 0.8);
// --color-magenta-9: rgba(248, 168, 204, 0.8);
// --color-magenta-10: rgba(250, 210, 227, 0.8);
// --color-gray-13: rgba(255, 255, 255, 0.8);
// --color-gray-12: rgba(250, 250, 250, 0.8);
// --color-gray-11: rgba(245, 245, 245, 0.8);
// --color-gray-10: rgba(240, 240, 240, 0.8);
// --color-gray-9: rgba(217, 217, 217, 0.8);
// --color-gray-8: rgba(191, 191, 191, 0.8);
// --color-gray-7: rgba(140, 140, 140, 0.8);
// --color-gray-6: rgba(89, 89, 89, 0.8);
// --color-gray-5: rgba(67, 67, 67, 0.8);
// --color-gray-4: rgba(38, 38, 38, 0.8);
// --color-gray-3: rgba(31, 31, 31, 0.8);
// --color-gray-2: rgba(20, 20, 20, 0.8);
// --color-gray-1: rgba(0, 0, 0, 0.8);
}

View File

@ -11,7 +11,7 @@ defineProps<{
<template>
<div class="actions-button w-100">
<a-col :span="24">
<div class="btn w-100 flex" @click="click">
<div class="action-btn-item w-100 flex" @click="click">
<div>
<component :is="icon || LinkOutlined" />
</div>
@ -24,7 +24,7 @@ defineProps<{
</template>
<style scoped lang="scss">
.btn {
.action-btn-item {
padding: 20px 12px;
border: 1px solid var(--color-gray-3);
background-color: var(--color-gray-2);

View File

@ -4,6 +4,7 @@ import "@/assets/tools.scss";
import "@/assets/variables.scss";
import "@/assets/variables-dark.scss";
import "@/assets/global.scss";
import "@/assets/bg-extend-theme.scss";
import "./initLib";

View File

@ -1,9 +1,10 @@
import { ref } from "vue";
import type { LayoutWithRouter, LayoutCard } from "@/types";
import { useRouterParams } from "@/hooks/useRouterParams";
import { getAllLayoutConfig } from "@/config/originLayoutConfig";
import { getAllLayoutConfig, setAllLayoutConfig } from "@/config/originLayoutConfig";
import { createGlobalState } from "@vueuse/core";
import { resetLayoutConfig, setLayoutConfig } from "@/services/apis/layout";
import type { IPageLayoutConfig } from "../../../common/global";
export const useLayoutConfigStore = createGlobalState(() => {
const { currentRoutePath } = useRouterParams();
@ -70,7 +71,26 @@ export const useLayoutConfigStore = createGlobalState(() => {
return await resetLayoutConfig().execute();
};
const getSettingsConfig = async () => {
return getAllLayoutConfig().find((v) => v.page === "__settings__");
};
const setSettingsConfig = async (config: IPageLayoutConfig) => {
const layout = getAllLayoutConfig();
const curIndex = layout.findIndex((v) => v.page === "__settings__");
if (curIndex >= 0) {
layout[curIndex] = config;
} else {
layout.push(config);
}
setAllLayoutConfig(layout);
await saveGlobalLayoutConfig();
setTimeout(() => window.location.reload(), 200);
};
return {
setSettingsConfig,
getSettingsConfig,
resetGlobalLayoutConfig,
getPageLayoutConfig,
deleteLayoutItem,

View File

@ -10,6 +10,7 @@ import {
BookOutlined,
GithubOutlined,
LockOutlined,
PicLeftOutlined,
ProjectOutlined,
QuestionCircleOutlined
} from "@ant-design/icons-vue";
@ -17,6 +18,8 @@ import {
import { settingInfo, setSettingInfo } from "@/services/apis";
import Loading from "@/components/Loading.vue";
import { computed } from "vue";
import { useUploadFileDialog } from "@/components/fc";
import { useLayoutConfigStore } from "../stores/useLayoutConfig";
defineProps<{
card: LayoutCard;
@ -24,8 +27,13 @@ defineProps<{
const { execute, isReady } = settingInfo();
const { execute: submitExecute, isLoading: submitIsLoading } = setSettingInfo();
const { getSettingsConfig, setSettingsConfig } = useLayoutConfigStore();
const formData = ref<Settings>();
interface MySettings extends Settings {
bgUrl?: string;
}
const formData = ref<MySettings>();
const submit = async () => {
if (formData.value) {
@ -49,6 +57,11 @@ const menus = [
key: "baseInfo",
icon: ProjectOutlined
},
{
title: t("外观设置"),
key: "ui",
icon: PicLeftOutlined
},
{
title: t("TXT_CODE_9c3ca8f"),
key: "security",
@ -111,9 +124,26 @@ const isZhCN = computed(() => {
return getCurrentLang().toLowerCase() === "zh_cn";
});
const uploadBackground = async () => {
if (formData.value) formData.value.bgUrl = await useUploadFileDialog();
};
const handleSaveBgUrl = async (url?: string) => {
const cfg = await getSettingsConfig();
if (!cfg?.theme) {
return reportError(t("配置文件版本不正确,无法设置背景图,请尝试重启面板或重置自定义布局!"));
}
cfg.theme.backgroundImage = url ?? formData.value?.bgUrl ?? "";
await setSettingsConfig(cfg);
};
onMounted(async () => {
const res = await execute();
const cfg = await getSettingsConfig();
formData.value = res.value!;
if (cfg?.theme?.backgroundImage) {
formData.value.bgUrl = cfg.theme.backgroundImage;
}
});
</script>
@ -161,20 +191,6 @@ onMounted(async () => {
/>
</a-form-item>
<a-form-item>
<a-typography-title :level="5">{{ t("TXT_CODE_b5b33dd4") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("TXT_CODE_c26e5fb7") }}
</a-typography-text>
</a-typography-paragraph>
<a-textarea
v-model:value="formData.loginInfo"
:rows="4"
:placeholder="t('TXT_CODE_4ea93630')"
/>
</a-form-item>
<a-form-item v-if="isCN()">
<a-typography-title :level="5">{{ t("TXT_CODE_b2767aa2") }}</a-typography-title>
<a-typography-paragraph type="secondary">
@ -208,6 +224,60 @@ onMounted(async () => {
</div>
</template>
<template #ui>
<div :style="{ maxHeight: card.height, overflowY: 'auto' }">
<a-typography-title :level="4" class="mb-24">
{{ t("外观设置") }}
</a-typography-title>
<div style="text-align: left">
<a-form :model="formData" layout="vertical">
<a-form-item>
<a-typography-title :level="5">{{ t("TXT_CODE_b5b33dd4") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{ t("TXT_CODE_c26e5fb7") }}
</a-typography-text>
</a-typography-paragraph>
<a-textarea
v-model:value="formData.loginInfo"
:rows="4"
:placeholder="t('TXT_CODE_4ea93630')"
/>
</a-form-item>
<div class="button mb-24">
<a-button type="primary" :loading="submitIsLoading" @click="submit()">
{{ t("TXT_CODE_abfe9512") }}
</a-button>
</div>
<a-form-item>
<a-typography-title :level="5">{{ t("界面背景图片") }}</a-typography-title>
<a-typography-paragraph>
<a-typography-text type="secondary">
{{
t(
"上传背景图片后,面板将设置深色主题且模糊半透明,你可以随时再切换回来。"
)
}}
</a-typography-text>
</a-typography-paragraph>
<a-typography-paragraph>
<a-input
v-model:value="formData.bgUrl"
style="max-width: 320px"
:placeholder="t('TXT_CODE_4ea93630')"
/>
<a-button class="ml-6" @click="() => uploadBackground()">上传</a-button>
</a-typography-paragraph>
<a-button type="primary" class="mr-6" @click="handleSaveBgUrl()">保存</a-button>
<a-button danger @click="handleSaveBgUrl('')">重置</a-button>
</a-form-item>
</a-form>
</div>
</div>
</template>
<template #security>
<div :style="{ maxHeight: card.height, overflowY: 'auto' }">
<a-typography-title :level="4" class="mb-24">

View File

@ -1,6 +1,6 @@
{
"name": "mcsmanager-panel",
"version": "10.0.0",
"version": "10.0.1",
"daemonVersion": "4.0.0",
"description": "Provide MCSManager with the ability to connect and control all Daemons, and provide API services for the front end.",
"scripts": {

View File

@ -63,6 +63,13 @@ export enum LayoutCardHeight {
function getDefaultFrontendLayoutConfig(): IPageLayoutConfig[] {
return [
{
page: "__settings__",
items: [],
theme: {
backgroundImage: ""
}
},
{
page: "/",
items: [