From b097983f1b896e2e6cb03e4c599c2030dddd76d2 Mon Sep 17 00:00:00 2001 From: wuzhuorong <973204353@qq.com> Date: Tue, 16 Jun 2026 11:25:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E6=96=B0=E5=A2=9E=E6=91=84?= =?UTF-8?q?=E5=83=8F=E5=A4=B4=E7=AE=A1=E7=90=86=E4=B8=8E=E8=A7=84=E5=88=99?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/layouts/MainLayout.vue | 6 +- apps/web/src/router/index.js | 16 +- apps/web/src/views/CameraManagement.vue | 683 +++++++++++++++++ apps/web/src/views/RuleConfiguration.vue | 903 +++++++++++++++++++++++ 4 files changed, 1606 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/views/CameraManagement.vue create mode 100644 apps/web/src/views/RuleConfiguration.vue diff --git a/apps/web/src/layouts/MainLayout.vue b/apps/web/src/layouts/MainLayout.vue index 57e68fc..c070691 100644 --- a/apps/web/src/layouts/MainLayout.vue +++ b/apps/web/src/layouts/MainLayout.vue @@ -99,7 +99,9 @@ import { WarningFilled, Bell, Fold, - Expand + Expand, + Connection, + SetUp } from '@element-plus/icons-vue' import { useAlertStore } from '@/stores/alertStore' import { connectAlertSocket, disconnectAlertSocket } from '@/services/mqtt.client' @@ -111,6 +113,8 @@ const alertStore = useAlertStore() const menuItems = [ { path: '/', title: '模型检测', icon: VideoCameraFilled }, + { path: '/cameras', title: '摄像头管理', icon: Connection }, + { path: '/rules', title: '规则配置', icon: SetUp }, { path: '/alerts', title: '预警列表', icon: WarningFilled } ] diff --git a/apps/web/src/router/index.js b/apps/web/src/router/index.js index 2f7d5d2..7b5e69d 100644 --- a/apps/web/src/router/index.js +++ b/apps/web/src/router/index.js @@ -1,6 +1,8 @@ import { createRouter, createWebHistory } from 'vue-router' import Home from '@/views/Home.vue' import AlertList from '@/views/AlertList.vue' +import CameraManagement from '@/views/CameraManagement.vue' +import RuleConfiguration from '@/views/RuleConfiguration.vue' import Layout from '@/layouts/MainLayout.vue' const routes = [ @@ -14,6 +16,18 @@ const routes = [ component: Home, meta: { title: '模型检测', icon: 'VideoCamera', keepAlive: true } }, + { + path: '/cameras', + name: 'CameraManagement', + component: CameraManagement, + meta: { title: '摄像头管理', icon: 'Connection', keepAlive: true } + }, + { + path: '/rules', + name: 'RuleConfiguration', + component: RuleConfiguration, + meta: { title: '规则配置', icon: 'SetUp', keepAlive: true } + }, { path: '/alerts', name: 'AlertList', @@ -29,4 +43,4 @@ const router = createRouter({ routes }) -export default router \ No newline at end of file +export default router diff --git a/apps/web/src/views/CameraManagement.vue b/apps/web/src/views/CameraManagement.vue new file mode 100644 index 0000000..ea77f2d --- /dev/null +++ b/apps/web/src/views/CameraManagement.vue @@ -0,0 +1,683 @@ + + + + + + + + + + {{ stat.label }} + {{ stat.value }} + + + + + + + + + + + + + + + + + + + + + + + + + + 刷新 + + + + 全部启动 + + + + 全部停止 + + + + 添加摄像头 + + + + + + + + + + + + + + + + {{ statusLabel(stream.status) }} + + {{ stream.stream_id }} + + + + + 启动 + + + + 停止 + + + + 配置 + + + + + + 移除 + + + + + + + {{ stream.rtsp_url }} + + + + + {{ stream.config?.model_id || '-' }} + + + + 置信度 {{ formatNumber(stream.config?.confidence) }} + + + + {{ stream.frame_count || 0 }} 帧 + + + + {{ formatLastFrame(stream.last_frame_at) }} + + + + {{ stream.error_message }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 = 每帧检测,N = 每 N+1 帧检测一次 + + + + + 取消 + + {{ editingStreamId ? '保存' : '添加' }} + + + + + + + + + diff --git a/apps/web/src/views/RuleConfiguration.vue b/apps/web/src/views/RuleConfiguration.vue new file mode 100644 index 0000000..26e040c --- /dev/null +++ b/apps/web/src/views/RuleConfiguration.vue @@ -0,0 +1,903 @@ + + + + + + + + LLM 二次判断 + + {{ llmStatus.enabled ? '已启用' : '未启用' }} + + + 熔断: {{ circuitLabel }} + + + + + + 刷新 + + + + 紧急停用 + + + + 重新启用 + + + + + + 重置统计 + + + + + + + + + Provider + {{ llmStatus.provider }} + {{ llmStatus.model || '-' }} + + + 融合策略 + {{ fusionLabel }} + + YOLO {{ formatRatio(llmStatus.fusion?.yolo_weight) }} / + LLM {{ formatRatio(llmStatus.fusion?.llm_weight) }} + + + + 触发阈值 + + {{ llmStatus.triggers?.min_consecutive_hits }} 连续帧 + + + avg≥{{ formatRatio(llmStatus.triggers?.min_avg_confidence) }} · + 冷却{{ llmStatus.triggers?.cooldown_seconds }}s + + + + 今日调用 + {{ todayCost?.call_count ?? 0 }} 次 + + 成功 {{ todayCost?.success_count ?? 0 }} / + 失败 {{ todayCost?.failure_count ?? 0 }} + + + + 今日费用 + ${{ formatCost(todayCost?.cost_usd) }} + + 预算 + {{ todayCost?.budget_usd ? `$${formatCost(todayCost.budget_usd)}` : '∞' }} + + + + + + + 最近错误率 + + {{ formatRatio(llmStatus.cost?.recent_error_rate) }} + + + 阈值 {{ formatRatio(llmStatus.cost?.error_rate_threshold) }} + + + + + + + 当前不会调用 LLM,原因:{{ llmStatus.cost.block_reason }} + + + + + + + + + + + + + + + + + + + 刷新 + + + + 热重载 + + + + 新增规则 + + + + + + + + + + + + + + + {{ severityLabel(rule.severity) }} + + {{ rule.name }} + + {{ eventTypeLabel(rule.event_type) }} + + handleToggle(rule, v)" + /> + + + + + 编辑 + + + + + + 删除 + + + + + + + {{ rule.description }} + + + + + min_conf ≥ {{ formatRatio(rule.min_confidence) }} + + + + min_area ≥ {{ rule.min_bbox_area || 0 }} + + + + 限定: {{ rule.allowed_sources.join(', ') }} + + + + 标签: {{ rule.required_labels.join(', ') }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 单位:像素²,0 表示不限 + + + + + + + + + + + + + + + + + + 取消 + + {{ editingName ? '保存' : '创建' }} + + + + + + + + +