| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- <template>
- <div class="app-shell">
- <aside class="sidebar">
- <div class="brand">Windows 监控</div>
- <el-menu :default-active="activeView" background-color="#1f2937" text-color="#d1d5db" active-text-color="#fff" @select="activeView = $event">
- <el-menu-item index="dashboard">仪表盘</el-menu-item>
- <el-menu-item index="pending">待确认中心</el-menu-item>
- <el-menu-item index="services">Windows 服务</el-menu-item>
- <el-menu-item index="processes">Windows 进程</el-menu-item>
- <el-menu-item index="tags">标签管理</el-menu-item>
- <el-menu-item index="settings">系统设置</el-menu-item>
- <el-sub-menu index="ai">
- <template #title>AI 配置</template>
- <el-menu-item index="ai-providers">AI 服务商管理</el-menu-item>
- <el-menu-item index="ai-models">AI 模型管理</el-menu-item>
- <el-menu-item index="ai-test">AI 服务测试</el-menu-item>
- </el-sub-menu>
- <el-sub-menu index="automation">
- <template #title>自动化</template>
- <el-menu-item index="automation-actions">自动化操作</el-menu-item>
- <el-menu-item index="automation-workflows">自动化工作流</el-menu-item>
- <el-menu-item index="automation-screens">已识别界面</el-menu-item>
- <el-menu-item index="automation-errors">自动化错误记录</el-menu-item>
- </el-sub-menu>
- <el-menu-item index="sensors">传感器信息</el-menu-item>
- <el-menu-item index="smart">硬盘 SMART</el-menu-item>
- <el-menu-item index="scans">扫描历史</el-menu-item>
- </el-menu>
- </aside>
- <main class="main">
- <div class="topbar">
- <div>
- <div class="page-title">{{ title }}</div>
- <div class="muted">{{ subtitle }}</div>
- </div>
- <el-button type="primary" :loading="scanning" @click="runScan">执行扫描</el-button>
- </div>
- <section v-if="activeView === 'dashboard'">
- <div class="metrics">
- <div class="metric"><div class="metric-label">服务总数</div><div class="metric-value">{{ dashboard.service_total || 0 }}</div></div>
- <div class="metric"><div class="metric-label">进程总数</div><div class="metric-value">{{ dashboard.process_total || 0 }}</div></div>
- <div class="metric"><div class="metric-label">待确认服务</div><div class="metric-value">{{ dashboard.pending_services || 0 }}</div></div>
- <div class="metric"><div class="metric-label">待确认进程</div><div class="metric-value">{{ dashboard.pending_processes || 0 }}</div></div>
- <div class="metric"><div class="metric-label">本次未出现</div><div class="metric-value">{{ (dashboard.missing_services || 0) + (dashboard.missing_processes || 0) }}</div></div>
- </div>
- <div class="panel">
- <el-descriptions title="最近扫描" :column="2" border>
- <el-descriptions-item label="状态">{{ dashboard.latest_scan?.status || '-' }}</el-descriptions-item>
- <el-descriptions-item label="开始时间">{{ dashboard.latest_scan?.started_at || '-' }}</el-descriptions-item>
- <el-descriptions-item label="服务数量">{{ dashboard.latest_scan?.services_found ?? '-' }}</el-descriptions-item>
- <el-descriptions-item label="进程数量">{{ dashboard.latest_scan?.processes_found ?? '-' }}</el-descriptions-item>
- </el-descriptions>
- </div>
- </section>
- <section v-if="activeView === 'services'">
- <ItemTable type="service" ref="serviceTable" />
- </section>
- <section v-if="activeView === 'processes'">
- <ItemTable type="process" ref="processTable" />
- </section>
- <section v-if="activeView === 'pending'">
- <el-tabs v-model="pendingTab">
- <el-tab-pane label="待确认服务" name="services">
- <ItemTable type="service" confirm-status="PENDING" ref="pendingServiceTable" />
- </el-tab-pane>
- <el-tab-pane label="待确认进程" name="processes">
- <ItemTable type="process" confirm-status="PENDING" ref="pendingProcessTable" />
- </el-tab-pane>
- </el-tabs>
- </section>
- <section v-if="activeView === 'tags'">
- <TagManager />
- </section>
- <section v-if="activeView === 'settings'">
- <SystemSettingsView ref="systemSettingsView" />
- </section>
- <section v-if="activeView === 'ai-providers'">
- <AiProviderManager ref="aiProviderManager" />
- </section>
- <section v-if="activeView === 'ai-models'">
- <AiModelManager ref="aiModelManager" />
- </section>
- <section v-if="activeView === 'ai-test'">
- <AiTestView ref="aiTestView" />
- </section>
- <section v-if="activeView === 'automation-actions'">
- <AutomationActionView ref="automationActionView" />
- </section>
- <section v-if="activeView === 'automation-workflows'">
- <AutomationWorkflowView ref="automationWorkflowView" />
- </section>
- <section v-if="activeView === 'automation-screens'">
- <AutomationScreensView ref="automationScreensView" />
- </section>
- <section v-if="activeView === 'automation-errors'">
- <AutomationErrorsView ref="automationErrorsView" />
- </section>
- <section v-if="activeView === 'sensors'">
- <SensorView />
- </section>
- <section v-if="activeView === 'smart'">
- <SmartView />
- </section>
- <section v-if="activeView === 'scans'" class="panel">
- <el-table :data="scans.items" border stripe>
- <el-table-column prop="id" label="ID" width="80" />
- <el-table-column prop="status" label="状态" width="110" />
- <el-table-column prop="started_at" label="开始时间" min-width="180" />
- <el-table-column prop="finished_at" label="完成时间" min-width="180" />
- <el-table-column prop="services_found" label="服务" width="90" />
- <el-table-column prop="processes_found" label="进程" width="90" />
- <el-table-column prop="new_services" label="新增服务" width="100" />
- <el-table-column prop="new_processes" label="新增进程" width="100" />
- <el-table-column prop="error_message" label="错误" min-width="180" />
- </el-table>
- </section>
- </main>
- </div>
- </template>
- <script setup>
- import { computed, nextTick, onMounted, ref, watch } from 'vue'
- import { ElMessage } from 'element-plus'
- import { api } from './api'
- import AiModelManager from './components/AiModelManager.vue'
- import AiProviderManager from './components/AiProviderManager.vue'
- import AiTestView from './components/AiTestView.vue'
- import AutomationActionView from './components/AutomationActionView.vue'
- import AutomationErrorsView from './components/AutomationErrorsView.vue'
- import AutomationScreensView from './components/AutomationScreensView.vue'
- import AutomationWorkflowView from './components/AutomationWorkflowView.vue'
- import ItemTable from './components/ItemTable.vue'
- import SensorView from './components/SensorView.vue'
- import SmartView from './components/SmartView.vue'
- import SystemSettingsView from './components/SystemSettingsView.vue'
- import TagManager from './components/TagManager.vue'
- const activeView = ref('dashboard')
- const pendingTab = ref('services')
- const dashboard = ref({})
- const scans = ref({ items: [] })
- const scanning = ref(false)
- const serviceTable = ref(null)
- const processTable = ref(null)
- const pendingServiceTable = ref(null)
- const pendingProcessTable = ref(null)
- const aiProviderManager = ref(null)
- const aiModelManager = ref(null)
- const aiTestView = ref(null)
- const systemSettingsView = ref(null)
- const automationActionView = ref(null)
- const automationWorkflowView = ref(null)
- const automationScreensView = ref(null)
- const automationErrorsView = ref(null)
- const title = computed(() => ({
- dashboard: '仪表盘',
- pending: '待确认中心',
- services: 'Windows 服务',
- processes: 'Windows 进程',
- tags: '标签管理',
- settings: '系统设置',
- 'ai-providers': 'AI 服务商管理',
- 'ai-models': 'AI 模型管理',
- 'ai-test': 'AI 服务测试',
- 'automation-actions': '自动化操作',
- 'automation-workflows': '自动化工作流',
- 'automation-screens': '已识别界面',
- 'automation-errors': '自动化错误记录',
- sensors: '传感器信息',
- smart: '硬盘 SMART',
- scans: '扫描历史',
- })[activeView.value])
- const subtitle = computed(() => {
- if (String(activeView.value).startsWith('automation')) {
- return '通过 AI 视觉识别 Windows 界面,执行自动化动作,并沉淀可复用工作流。'
- }
- return '采集 Windows 服务和进程,确认可信状态,并整理给 AI 分析的数据。'
- })
- async function loadDashboard() {
- const { data } = await api.get('/api/dashboard')
- dashboard.value = data
- }
- async function loadScans() {
- const { data } = await api.get('/api/scans')
- scans.value = data
- }
- async function refreshCurrent() {
- await loadDashboard()
- if (activeView.value === 'scans') await loadScans()
- await nextTick()
- serviceTable.value?.load()
- processTable.value?.load()
- pendingServiceTable.value?.load()
- pendingProcessTable.value?.load()
- aiProviderManager.value?.load()
- aiModelManager.value?.refreshAll()
- aiTestView.value?.loadOptions()
- systemSettingsView.value?.load()
- automationActionView.value?.loadOptions()
- automationWorkflowView.value?.load()
- automationScreensView.value?.load()
- automationErrorsView.value?.load()
- }
- async function runScan() {
- scanning.value = true
- try {
- const { data } = await api.post('/api/scans/run')
- ElMessage.success(`扫描完成:服务 ${data.services_found},进程 ${data.processes_found}`)
- await refreshCurrent()
- } catch (error) {
- ElMessage.error(error.response?.data?.detail || '扫描失败')
- } finally {
- scanning.value = false
- }
- }
- watch(activeView, async (view) => {
- if (view === 'dashboard') await loadDashboard()
- if (view === 'scans') await loadScans()
- if (view === 'settings') await systemSettingsView.value?.load()
- if (view === 'automation-workflows') await automationWorkflowView.value?.load()
- if (view === 'automation-screens') await automationScreensView.value?.load()
- if (view === 'automation-errors') await automationErrorsView.value?.load()
- })
- onMounted(refreshCurrent)
- </script>
|