2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00
2026-06-10 11:46:45 +08:00

local_alert

本地告警页面

Project Setup

npm install

Compile and Hot-Reload for Development

npm run dev

Type-Check, Compile and Minify for Production

npm run build

依赖包

    "@jiaminghi/data-view": "^2.10.0",
    "@kjgl77/datav-vue3": "^1.7.4",
    "ant-design-vue": "^4.2.6",
    "axios": "^1.7.3",
    "dayjs": "^1.11.13",
    "echarts": "^5.5.1",
    "element-plus": "^2.7.8",
    "file-saver": "^2.0.5",
    "jsmpeg": "^1.0.0",
    "json2csv": "^5.0.7",
    "lodash": "^4.17.21",
    "mitt": "^3.0.1",
    "papaparse": "^5.4.1",
    "pinia": "^2.2.6",
    "vue": "^3.4.29",
    "vue-router": "^4.4.0"
  • @jiaminghi/data-view:DataV
  • @kjgl77/datav-vue3/dist/style.css
  • ant-design-vue: 没用上
  • axios:异步
  • dayjs日期截取
  • echarts:仪表盘
  • element-plus: 组件
  • file-saver: 文件加载
  • jsmpeg视频播放本地加载静态文件
  • json2csv表格导出弃用
  • http-proxy-middleware: 请求跨域
  • lodash
  • mite: Bus线程通信
  • papaparse表格csv导出
  • pinia没用上
  • jszip:下载打包
  • qs:静态资源请求
  • vue:框架
  • vue-router:路由

目录结构

│  .gitignore
│  env.d.ts
│  index.html
│  LICENSE
│  package-lock.json
│  package.json
│  README.md
│  SScode.md
│  tsconfig.app.json
│  tsconfig.json
│  tsconfig.node.json
│  vite.config.ts
│  
├─.vscode
│      extensions.json
│      
├─dist
│  │  bg05.png
│  │  icon.ico
│  │  index.html
│  │  login-bg.png
│  │  xlogo.png
│  │  
│  ├─assets
│  │      
│  └─static
│      └─jsmpeg-master
│          │  
│          └─src
│              │  
│              └─wasm
│                      
├─node_modules
│                      
└─src
    │  App.vue
    │  main.ts
    │  
    ├─assets
    │      global.css
    │      viewListStyle.css
    │      
    ├─bk
    │      CenterBottom告警分布.vue
    │      CenterTop警戒点位.vue
    │      DataStatics新数据统计.vue
    │      DataStatistics原始版.vue
    │      LeftMiddle点位告警数量.vue
    │      LeftTop告警数据统计.vue
    │      RightTop类型分布.vue
    │      StaticData图表简易版.vue
    │      告警列表(letf-bottom).vue
    │      告警数量分布问题代码.vue
    │      时间段内告警类型数量.vue
    │      时间段告警数量分布.vue
    │      点播页面原版.vue
    │      设置页面点播墙组件代码.vue
    │      
    ├─components
    │  │  AlertChart.vue
    │  │  Cameras.vue
    │  │  Channel.vue
    │  │  GlobalDialog.vue
    │  │  Layout.vue
    │  │  Settings.vue
    │  │  Statistics.vue
    │  │  
    │  └─Max
    │          CenterBottom.vue
    │          CenterTop.vue
    │          LeftBottom.vue
    │          LeftMiddle.vue
    │          LeftTop.vue
    │          RightTop.vue
    │          
    ├─html
    │      AlertManagement.vue
    │      CameraRules.vue
    │      DataStatistics.vue
    │      Home.vue
    │      LoginView.vue
    │      Test.vue
    │      UserList.vue
    │      ViewList.vue
    │      
    ├─icons
    │      CameraAll.vue
    │      CameraOffline.vue
    │      CameraOnline.vue
    │      EventAll.vue
    │      EventClosed.vue
    │      EventPending.vue
    │      
    ├─router
    │      index.ts
    │      
    ├─stores
    │      globalTimerStore.ts
    │      
    ├─types
    │      CameraData.ts
    │      RuleData.ts
    │      
    └─utils
            axios-config.ts
            boxApi.ts
            eventBus.ts
            message_channel.js
            misc.ts
            superbox.js
            Superbox.ts
            superboxApi.ts
            useGlobalWebSocket.ts

Src文件说明

目录分解

└─src
    │  App.vue
    │  main.ts
    │  
    ├─assets
    │      global.css
    │      viewListStyle.css
    │      
    ├─bk
    │      CenterBottom告警分布.vue
    │      CenterTop警戒点位.vue
    │      DataStatics新数据统计.vue
    │      DataStatistics原始版.vue
    │      LeftMiddle点位告警数量.vue
    │      LeftTop告警数据统计.vue
    │      RightTop类型分布.vue
    │      StaticData图表简易版.vue
    │      告警列表(letf-bottom).vue
    │      告警数量分布问题代码.vue
    │      时间段内告警类型数量.vue
    │      时间段告警数量分布.vue
    │      点播页面原版.vue
    │      设置页面点播墙组件代码.vue
    │      
    ├─components
    │  │  AlertChart.vue
    │  │  Cameras.vue
    │  │  Channel.vue
    │  │  GlobalDialog.vue
    │  │  Layout.vue
    │  │  Settings.vue
    │  │  Statistics.vue
    │  │  
    │  └─Max
    │          CenterBottom.vue
    │          CenterTop.vue
    │          LeftBottom.vue
    │          LeftMiddle.vue
    │          LeftTop.vue
    │          RightTop.vue
    │          
    ├─html
    │      AlertManagement.vue
    │      CameraRules.vue
    │      DataStatistics.vue
    │      Home.vue
    │      LoginView.vue
    │      Test.vue
    │      UserList.vue
    │      ViewList.vue
    │      
    ├─icons
    │      CameraAll.vue
    │      CameraOffline.vue
    │      CameraOnline.vue
    │      EventAll.vue
    │      EventClosed.vue
    │      EventPending.vue
    │      
    ├─router
    │      index.ts
    │      
    ├─stores
    │      globalTimerStore.ts
    │      
    ├─types
    │      CameraData.ts
    │      RuleData.ts
    │      
    └─utils
            axios-config.ts
            boxApi.ts
            eventBus.ts
            message_channel.js
            misc.ts
            superbox.js
            Superbox.ts
            superboxApi.ts
            useGlobalWebSocket.ts

根目录

└─src
    │  App.vue
    │  main.ts
    ├─assets
    │      
    ├─bk
    │      
    ├─components
    │  │  
    │  └─Max
    │          
    ├─html
    │      
    ├─icons
    │      
    ├─router
    │      
    ├─stores
    │      
    ├─types
    │      
    └─utils

App.vue(关键)

  • 在index.html中可见
    <div id="app"></div>

页面的app为页面主体框架结构所有组件仿照类似嵌套方式申明和使用其下囊括页面布局的其他页面和子页面组件 相当于整体布局的一个载体(根父组件)

<template>
  <div id="app">
      <router-view></router-view>
  </div>
</template>

<script lang="ts">
import { provide } from 'vue';

export default {
  name: 'App',
  // setup() {
  		//定义响应式数据
  // }
};
</script>

<style scoped>
/* 添加你的样式 */
</style>

作为父页面不可避免需要向其下子组件传递参数可通过导入vue中的provide方法直接传递多层次的子组件信息子组件inject获取信息当然在vue3中数据的变化需要用reactive包裹数据创建响应式变化。

main.ts(关键)

对于app组件的挂载和改改父组件的依赖使用和申明需要在这里定义使用当一些新的外部组件引用逻辑正确但是显示异常可检查是否在根文件中引用

路由Route

└─src
    ├─router
    │      index.ts
  • 看门狗(to,form,next)
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
const routes = [
  {
  	    path: '/',
    	name: '',
    	component: ,
    	children: []
  
  }
const router = createRouter({
  history: createWebHashHistory(),
  routes
});
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token');
  if (to.matched.some(record => record.meta.requiresAuth) && !token) {
    next({ name: 'Login' });
  } else {
    next();
  }
});
export default router;


登录

  • 页面拦截

简易拦截alertToken作为判断条件拦截对象当然数据请求需要交互验证。

// 导航守卫,检查登录状态
router.beforeEach((to, from, next) => {
    const token = localStorage.getItem('alertToken'); // 检查 token 是否存在,作为是否登录的依据
    if (to.matched.some(record => record.meta.requiresAuth)) {
        // 该路由需要认证
        if (!token) {
            // 如果没有 token重定向到登录页面
            next({
                path: '/login',
                query: { redirect: to.fullPath } // 将当前路径传递给登录页面,登录后可以重定向回来
            });
        } else {
            // 已登录,继续访问
            next();
        }
    } else {
        // 不需要认证,继续访问
        next();
    }
});

本地告警首页子页面ViewList布局

image-20241030162011722

image-20241031164625119

image-20251201110453175

告警规则设置

界面接口列表

    private readonly apiLogin: string = "/auth/login";
    	-  public async login
    		- (username: string, password: string, cookieLess: boolean = false): Promise<any>
    		
    private readonly apiLogout: string = "/auth/logout";
    	- public async logout
    		- (token: string | null = null): Promise<any>
    	
    	
    private readonly apiAdduser: string = "/auth/adduser";
    	- public async addUser
    		- (username: string, password: string, email: string = "", token: string | null = null): Promise<any>
    		
    private readonly apiRmuser: string = "/auth/rmuser";
    	- public async rmUser
    		- (username: string, token: string | null = null): Promise<any> 
    		
    private readonly apiAllusers: string = "/auth/allusers";
    	- public async getAllUsers
			- (token: string | null = null): Promise<any>
			
    private readonly apiCameras: string = "/cameras";
    	- public async getCameras
    		- (limit: number, offset: number, token: string | null = null): Promise<any>
    		
    private readonly apiEvents: string = "/events";
    	- public async getEvents
    		- (token: string | null = null, pageSize: number = 20, currentPage: number = 1): Promise<any>
    		
    	- public async getEventsByParams
        	-	(
                token: string | null = null,
                pageSize: number = 20,
                currentPage: number = 1,
                timeBefore: string | null = null,
                timeAfter: string | null = null,
                types: string | null = null,
                camera_id: number | null = null,
                status?: 'pending' | 'closed' | null
                ): Promise<any> 
             
		- public async setEventStatus
			- (eventId: number, status: string, remark: string | null = null, token: string | null = null): Promise<any> 
			
    private readonly apiAlgorithms: string = "/algorithms";
    	- public async getAlgorithms
    		- (token: string | null = null): Promise<any>
    		
    private readonly apiResetUser: string = "/auth/resetuser";
    	- public async resetUser
    		- (username: string, password: string, email: string, token: string | null = null): Promise<any>
    		
    private readonly apiResetPassword: string = "/auth/reset_password";
    	- public async resetPassword
    		- (newPassword: string, token: string | null = null): Promise<any> 
    		
    private readonly apiAllCameras: string = "/camera/cameras/get_all";
    	- public async getAllCameras
    		- (token: string | null = null): Promise<any>
    		
    private readonly superCamera: string = "/camera/cameras";
    	- public async getCameraById
    		- (token: string | null = null, cameraId: number): Promise<any>
    	
    	- public async updateCamera
    		- (token: string | null = null, cameraId: number, jsonData: CameraData): Promise<any>
    		
    	- public async startCameraStream
    		- (token: string | null = null, cameraId: number): Promise<any>
    	
    	- public async stopCameraStream
    		- (token: string | null = null, cameraId: number): Promise<any> 
    		
    private readonly superRule: string = "/rules";
    	- public async updateRule
    		- (token: string | null = null, rules: RuleData[]): Promise<any[]>
    		
    private readonly superEvents: string = "/event/events";
    	- public async delEvents
    		- (token: string | null = null, eventIds: number[]): Promise<{ id: number, success: boolean, message?: string }[]> 
    		
    	- public async getEventById
    		- (id: number, token: string | null = null): Promise<any>
    	
  • 摄像实例
const cameraId = 1; // 示例摄像头 ID
const token = "your-auth-token";
const cameraJson = {
    "id": 1,
    "name": "421枪机",
    "uri": "rtsp://admin:1234qwer@192.168.28.102:554/Streaming/Channels/202",
    "mode": "on",
    "status": "online",
    "detect_params": { "threshold": 0.5 },
    "default_params": {},
    "should_push": false,
    "config_params": {},
    "sampling": false,
    "note": {},
    "snapshot": "http://127.0.0.1:8000/media/cameras/1/snapshot.jpg",
    "remote_id": -1,
    "raw_address": "0b8342ec52e62d01dd3273f583d326ec",
    "ip": "admin:1234qwer@192.168.28.102:554",
    "port": 8082,
    "rules": [] // 包含的 rules 会被排除
};
await apiInstance.updateCamera(token, cameraId, cameraJson);

  • 规则实例
const cameraId = 1; // 示例摄像头 ID
const token = "your-auth-token";
const cameraJson = {
    "id": 1,
    "name": "421枪机",
    "uri": "rtsp://admin:1234qwer@192.168.28.102:554/Streaming/Channels/202",
    "mode": "on",
    "status": "online",
    "detect_params": { "threshold": 0.5 },
    "default_params": {},
    "should_push": false,
    "config_params": {},
    "sampling": false,
    "note": {},
    "snapshot": "http://127.0.0.1:8000/media/cameras/1/snapshot.jpg",
    "remote_id": -1,
    "raw_address": "0b8342ec52e62d01dd3273f583d326ec",
    "ip": "admin:1234qwer@192.168.28.102:554",
    "port": 8082,
    "rules": [] // 包含的 rules 会被排除
};
await apiInstance.updateCamera(token, cameraId, cameraJson);

单条camera实例部分内容
{
        "id": 1,
        "name": "421枪机",
 
        "mode": "on",
       

        "rules": [{规则1json数据},{规则2json数据}]
}

单条rule实例部分
 {
        "id": 3,
        "camera": 1,
        "name": "人员逗留",
        "mode": "schedule",
        "algo": "personnel_staying",
        "params": {},
        "params_base": "",
        "unique_id": "7ce99a51-0ee4-4251-a754-bd897d671303",
        "event_types": {
            "personnel_staying": "人员逗留"
        },
        "schedule": {
            "type": "weekly",
            "time_slots": [
                [
                    5,
                    1415
                ]
            ],
            "week_day": "Monday"
        }
    }
  • 时间段规则设置

添加时间段schedule的设置组件显示开始时间点和结束时间数据格式化方式为将代表累计分钟的数字转换为时间点每60分钟为1小时数字范围在0到1440实例[56,65]代表0:56到1:05组件显示将数字组转换为时间段请求时将组件时间段显示为数字组。

时间段结束时间点不能大于开始时间点,多时间段添加不能有重合部分。

设置规则只有在rule.mode为schedule时才可设置时间段携带参数日期类型和多个时间段数字组合在未保存切换rule。mode模式时间段不会因为隐藏组件而清空数值始终显示开始设定好的默认值当提交时处于时间段模式至少得设置一个时间段数组否则无法保存若处在schedule情况下保存携带参数请求若rule.mode处于on或者off,代表没有时间段设置那么schedule下的所有参数及时原来有值也需要伴随请求清空默认值,具体如下:

1.在rule.mode为schedule模式添加时间段time_slots的组件添加时间段类型输入框值默认为daily不可修改

2.开始时间和结束时间的组件,时间通过分钟数转换为格式化的时间(小时:分钟有删除按钮可删除临时的时间段设置使用数字范围0-1440单个时间点代表0点到设置的时间点累计的分钟数字

3.时间段的校验,结束时间不能小于开始时间,多时间段之间不能有重叠。

4.如果 rule.mode 为 schedule则必须包含至少一个时间段如果 rule.mode 是 on 或 off清空所有时间段和时间段类型

  • 静态数据实例
"camera": { 
        "id": 1,
        "name": "421枪机",
        "mode": "on",
        "status": "online",
        "rules": [
            {
                "id": 1,

                "camera": 1,
                "name": "入侵test2",
                "mode": "schedule",
                "algo": "intrude",
                "schedule": {
                    "type": "daily",
                    "time_slots": [
                        [
                            118,
                            898
                        ],
                        [
                            0,
                            60
                        ]
                    ]
                },
            },
            {
                "id": 3,
                "camera": 1,
                "name": "人员逗留",
                "mode": "schedule",
                "algo": "personnel_staying",
                "schedule": {
                    "type": "daily",
                    "time_slots": [
                        [
                            180,
                            420
                        ]
                    ]
                },
            }
        ],
        "snapshot": "http://192.168.28.33:8000/media/cameras/1/snapshot.jpg",
    }

日志

2024.11.21

  • 本地打包

  • 服务器页面备份

  • 服务器迭代,覆盖

  • 版本提交云端

  • 更新内容

    • 1.弹窗仅图片显示AlertManagementLeftBottomApp
    • 2.通道点播Setting,Channel
      • 摄像列表
      • 搜索/在线状态过滤
    • 3.通道规则设置(Channel,CameraRules)
      • 规则开关
      • 时间设置
  • 下阶段

    • 1.弹窗模式按钮
      • 交互式开关(已有,点击响应)
      • 响应式开关(###
    • 2.光影效果
      • 声音联动(提示音)
      • 交互(首页)
    • 3.用户设定不可更改项
    • 测试调整(遗留代码冗余调整)

2024.11.22

  • 弹窗模式开关
    • 交互式开关(点击触发弹窗)
    • 响应式开关(触发对话框)
  • 弹窗现实
    • 格式化类型
    • 格式化时间
    • 现实时间
    • 弹窗布局调整
  • 控制台日志处理(部分)

2024.11.26

  • 对话框大图显示
  • 删除告警按钮
  • 主页定时刷新
  • 布局滚动查看调整
  • 用户删除限制

2024.12.3

  • 告警设置
    • 消息队列设置
    • 声音设置
    • 弹窗动画添加
    • 弹窗队列添加错误重试机制2s*5次
Description
本地告警本地项目前端工程
Readme OSL-3.0 5.7 MiB
Languages
Vue 54%
JavaScript 22.9%
C 13%
TypeScript 8.9%
CSS 0.6%
Other 0.6%