Files
DeEarthX-V3/front/src/component/Setting.vue
2026-01-01 20:51:59 +08:00

248 lines
6.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts" setup>
import { ref, watch } from 'vue';
import { message } from 'ant-design-vue';
// 配置接口定义
interface AppConfig {
mirror: {
bmclapi: boolean;
mcimirror: boolean;
};
filter: {
hashes: boolean;
dexpub: boolean;
mixins: boolean;
};
oaf: boolean; // 操作完成后打开目录
}
// 设置项接口
interface SettingItem {
key: string;
name: string;
description: string;
path: string;
defaultValue: boolean;
}
// 设置分类接口
interface SettingCategory {
id: string;
title: string;
icon: string;
bgColor: string;
textColor: string;
items: SettingItem[];
}
// 配置状态
const config = ref<AppConfig>({
mirror: { bmclapi: false, mcimirror: false },
filter: { hashes: false, dexpub: false, mixins: false },
oaf: false
});
// 设置分类和选项数组
const settings: SettingCategory[] = [
{
id: 'filter',
title: '模组筛选设置',
icon: '🧩',
bgColor: 'bg-emerald-100',
textColor: 'text-emerald-800',
items: [
{
key: 'hashes',
name: '哈希过滤',
description: '过滤不必要的客户端模组(哈希过滤法)',
path: 'filter.hashes',
defaultValue: false
},
{
key: 'dexpub',
name: 'DePIS过滤',
description: '过滤 DeEarth Public Info Services 平台中记录的客户端文件',
path: 'filter.dexpub',
defaultValue: false
},
{
key: 'mixins',
name: 'Mixin过滤',
description: '过滤 Client Mixin 相关文件',
path: 'filter.mixins',
defaultValue: false
}
]
},
{
id: 'mirror',
title: '下载源设置',
icon: '⬇️',
bgColor: 'bg-cyan-100',
textColor: 'text-cyan-800',
items: [
{
key: 'mcimirror',
name: 'MCIM镜像源',
description: '使用 MCIM 镜像源加速下载',
path: 'mirror.mcimirror',
defaultValue: false
},
{
key: 'bmclapi',
name: 'BMCLAPI镜像源',
description: '使用 BMCLAPI 镜像源加速下载',
path: 'mirror.bmclapi',
defaultValue: false
}
]
},
{
id: 'system',
title: '系统管理设置',
icon: '🛠️',
bgColor: 'bg-purple-100',
textColor: 'text-purple-800',
items: [
{
key: 'oaf',
name: '操作完成后打开目录',
description: '服务端制作完成后自动打开目录',
path: 'oaf',
defaultValue: false
}
]
}
];
// 获取配置值
function getConfigValue(path: string): boolean {
const keys = path.split('.');
let value = config.value;
for (const key of keys) {
// @ts-expect-error - 动态访问对象属性
value = value[key];
}
// 确保返回值是boolean类型
if (typeof value === 'boolean') {
return value;
}
// 如果类型不是boolean返回默认值false
console.warn(`Config value at path "${path}" is not a boolean:`, value);
return false;
}
// 设置配置值
function setConfigValue(path: string, value: boolean): void {
const keys = path.split('.');
let obj = config.value;
// 遍历到倒数第二个key
for (let i = 0; i < keys.length - 1; i++) {
// @ts-expect-error - 动态访问对象属性
obj = obj[keys[i]];
}
// 设置最后一个key的值
// @ts-expect-error - 动态访问对象属性
obj[keys[keys.length - 1]] = value;
}
// 从后端加载配置
async function loadConfig() {
try {
const response = await fetch('http://localhost:37019/config/get', {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
if (response.ok) {
config.value = await response.json();
}
} catch (error) {
console.error('加载配置失败:', error);
message.error('加载配置失败');
}
}
// 保存配置到后端
async function saveConfig(newConfig: AppConfig) {
try {
const response = await fetch('http://localhost:37019/config/post', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newConfig)
});
if (response.ok) {
message.success('配置已保存');
}
} catch (error) {
console.error('保存配置失败:', error);
message.error('保存配置失败');
}
}
// 初始化时加载配置
loadConfig();
// 监听配置变化并保存
let isInitialLoad = true;
watch(config, (newValue) => {
if (isInitialLoad) {
isInitialLoad = false;
return;
}
saveConfig(newValue);
}, { deep: true });
</script>
<template>
<div class="tw:h-full tw:w-full tw:p-4 tw:overflow-auto tw:bg-gray-50">
<div class="tw:max-w-2xl tw:mx-auto">
<!-- 标题区域 -->
<div class="tw:text-center tw:mb-8">
<h1 class="tw:text-4xl tw:font-bold tw:tracking-tight">
<span class="tw:bg-gradient-to-r tw:from-emerald-500 tw:to-cyan-500 tw:bg-clip-text tw:text-transparent">
DeEarth X
</span>
<span class="tw:text-gray-800">设置</span>
</h1>
<p class="tw:text-gray-500 tw:mt-2">让你的 DeEarthX V3 更加适合你自己!</p>
</div>
<!-- 动态渲染设置卡片 -->
<div
v-for="category in settings"
:key="category.id"
class="tw:bg-white tw:rounded-lg tw:shadow-md tw:p-6 tw:mb-6"
>
<h2 class="tw:text-xl tw:font-semibold tw:text-gray-800 tw:mb-4 tw:flex tw:items-center">
<span :class="[category.bgColor, category.textColor, 'tw:w-8 tw:h-8 tw:rounded-full tw:flex tw:items-center tw:justify-center tw:mr-3']">
{{ category.icon }}
</span>
{{ category.title }}
</h2>
<div class="tw:grid tw:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 tw:gap-4">
<div
v-for="item in category.items"
:key="item.key"
class="tw:flex tw:items-center tw:justify-between tw:p-3 tw:border tw:border-gray-100 tw:rounded-md tw:hover:bg-gray-50"
>
<div>
<p class="tw:text-gray-700 tw:font-medium">{{ item.name }}</p>
<p class="tw:text-xs tw:text-gray-500">{{ item.description }}</p>
</div>
<a-switch
:checked="getConfigValue(item.path)"
@change="setConfigValue(item.path, $event)"
:checked-children="'开'"
:un-checked-children="'关'"
/>
</div>
</div>
</div>
</div>
</div>
</template>