mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
refactor: 模块管理支持内置工具展示
将邮件配置、IP 安全、审计日志等系统功能从固定菜单移至模块管理页面,以内置工具形式统一展示
This commit is contained in:
35
frontend/src/config/builtin-tools.ts
Normal file
35
frontend/src/config/builtin-tools.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Mail, Shield, AlertTriangle } from 'lucide-vue-next'
|
||||
import type { LucideIcon } from 'lucide-vue-next'
|
||||
|
||||
export interface BuiltinTool {
|
||||
name: string
|
||||
description: string
|
||||
href: string
|
||||
icon: LucideIcon
|
||||
}
|
||||
|
||||
export const BUILTIN_TOOLS: BuiltinTool[] = [
|
||||
{
|
||||
name: '邮件配置',
|
||||
description: '配置 SMTP 邮件服务,管理邮件模板和发送设置',
|
||||
href: '/admin/email',
|
||||
icon: Mail,
|
||||
},
|
||||
{
|
||||
name: 'IP 安全',
|
||||
description: '管理 IP 黑白名单,控制系统访问权限',
|
||||
href: '/admin/ip-security',
|
||||
icon: Shield,
|
||||
},
|
||||
{
|
||||
name: '审计日志',
|
||||
description: '查看系统操作日志,追踪安全事件与变更记录',
|
||||
href: '/admin/audit-logs',
|
||||
icon: AlertTriangle,
|
||||
},
|
||||
]
|
||||
|
||||
/** href → display name mapping for breadcrumbs */
|
||||
export const BUILTIN_TOOL_BREADCRUMBS: Record<string, string> = Object.fromEntries(
|
||||
BUILTIN_TOOLS.map(t => [t.href, t.name])
|
||||
)
|
||||
@@ -363,7 +363,6 @@ import {
|
||||
Megaphone,
|
||||
Menu,
|
||||
X,
|
||||
Mail,
|
||||
Puzzle,
|
||||
Zap,
|
||||
FileUp,
|
||||
@@ -372,6 +371,7 @@ import {
|
||||
} from 'lucide-vue-next'
|
||||
|
||||
import GithubIcon from '@/components/icons/GithubIcon.vue'
|
||||
import { BUILTIN_TOOL_BREADCRUMBS } from '@/config/builtin-tools'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -507,9 +507,6 @@ const navigation = computed(() => {
|
||||
const systemItems: { name: string; href: string; icon: LucideIcon }[] = [
|
||||
{ name: '公告管理', href: '/admin/announcements', icon: Megaphone },
|
||||
{ name: '缓存监控', href: '/admin/cache-monitoring', icon: Gauge },
|
||||
{ name: 'IP 安全', href: '/admin/ip-security', icon: Shield },
|
||||
{ name: '审计日志', href: '/admin/audit-logs', icon: AlertTriangle },
|
||||
{ name: '邮件配置', href: '/admin/email', icon: Mail },
|
||||
]
|
||||
|
||||
// 动态添加已激活模块的菜单项
|
||||
@@ -597,6 +594,15 @@ const breadcrumbs = computed((): BreadcrumbItem[] => {
|
||||
]
|
||||
}
|
||||
|
||||
// Special case: built-in tools under module management
|
||||
if (BUILTIN_TOOL_BREADCRUMBS[route.path]) {
|
||||
return [
|
||||
{ label: '系统' },
|
||||
{ label: '模块管理', href: '/admin/modules' },
|
||||
{ label: BUILTIN_TOOL_BREADCRUMBS[route.path] }
|
||||
]
|
||||
}
|
||||
|
||||
// Find section and page from navigation
|
||||
for (const group of navigation.value) {
|
||||
const activeItem = group.items.find(item => isNavActive(item.href))
|
||||
|
||||
@@ -32,6 +32,57 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- 内置工具 -->
|
||||
<div
|
||||
v-if="filteredBuiltinTools.length > 0"
|
||||
class="mb-8"
|
||||
>
|
||||
<h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-4">
|
||||
内置工具
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5">
|
||||
<div
|
||||
v-for="tool in filteredBuiltinTools"
|
||||
:key="tool.name"
|
||||
class="group relative border rounded-2xl p-6 transition-all duration-200 hover:shadow-lg border-border bg-card hover:border-primary/20 cursor-pointer"
|
||||
@click="router.push(tool.href)"
|
||||
>
|
||||
<div class="flex items-start gap-4 mb-3">
|
||||
<div class="w-11 h-11 rounded-xl flex items-center justify-center shrink-0 transition-colors bg-primary/15 text-primary">
|
||||
<component
|
||||
:is="tool.icon"
|
||||
class="w-5 h-5"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 pt-1">
|
||||
<h4 class="font-semibold text-base truncate">
|
||||
{{ tool.name }}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-sm text-muted-foreground leading-relaxed line-clamp-2 min-h-[2.5rem]">
|
||||
{{ tool.description }}
|
||||
</p>
|
||||
<div class="mt-5 pt-4 border-t border-border/50 flex items-center justify-end">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="gap-1.5"
|
||||
@click.stop="router.push(tool.href)"
|
||||
>
|
||||
<Settings class="w-3.5 h-3.5" />
|
||||
管理
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 扩展模块 -->
|
||||
<h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-4">
|
||||
扩展模块
|
||||
</h3>
|
||||
|
||||
<!-- 模块卡片网格 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5">
|
||||
<div
|
||||
@@ -130,7 +181,7 @@
|
||||
|
||||
<!-- 搜索无结果 -->
|
||||
<div
|
||||
v-if="filteredModules.length === 0 && searchQuery && !loading"
|
||||
v-if="filteredModules.length === 0 && filteredBuiltinTools.length === 0 && searchQuery && !loading"
|
||||
class="text-center py-16"
|
||||
>
|
||||
<Search class="w-12 h-12 mx-auto text-muted-foreground/50 mb-4" />
|
||||
@@ -163,6 +214,7 @@ import Input from '@/components/ui/input.vue'
|
||||
import { PageHeader, PageContainer } from '@/components/layout'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { useModuleStore } from '@/stores/modules'
|
||||
import { BUILTIN_TOOLS } from '@/config/builtin-tools'
|
||||
import { log } from '@/utils/logger'
|
||||
import { getErrorMessage } from '@/types/api-error'
|
||||
|
||||
@@ -174,6 +226,15 @@ const loading = ref(false)
|
||||
const toggling = ref<Record<string, boolean>>({})
|
||||
const searchQuery = ref('')
|
||||
|
||||
// 过滤后的内置工具
|
||||
const filteredBuiltinTools = computed(() => {
|
||||
if (!searchQuery.value.trim()) return BUILTIN_TOOLS
|
||||
const query = searchQuery.value.toLowerCase()
|
||||
return BUILTIN_TOOLS.filter(
|
||||
t => t.name.toLowerCase().includes(query) || t.description.toLowerCase().includes(query)
|
||||
)
|
||||
})
|
||||
|
||||
// 获取分类图标
|
||||
function getCategoryIcon(category: string) {
|
||||
const icons: Record<string, any> = {
|
||||
|
||||
Reference in New Issue
Block a user