新增AIoT边缘智能模块:摄像头ROI配置、算法管理、配置推送

- 后端:新增aiot模块(bean/dao/service/controller),支持ROI区域CRUD、
  算法注册表管理、ROI-算法绑定、配置推送到FastAPI边缘端、变更日志
- 前端:新增摄像头配置页(列表+ROI子页面)、算法配置页、Canvas绘图组件
  (矩形/多边形)、动态算法参数编辑器、ZLM截图作为ROI编辑背景
- 数据库:新建4张表(wvp_ai_roi/algorithm/roi_algo_bind/config_log)
  字段与FastAPI端SQLite兼容,含2个预置算法
- 路由裁剪:隐藏无关菜单(地图/部标/推流/录制计划等)
- 修复cameraId含/导致REST路径解析错误(改用query参数)
- 新增ai.service配置项(边缘端地址/超时/开关)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 08:59:20 +08:00
parent 6c471cdfd7
commit d7bf969694
44 changed files with 2943 additions and 12 deletions

View File

@@ -0,0 +1,118 @@
<template>
<div class="algorithm-config-page">
<div class="page-header">
<h3>算法配置管理</h3>
<el-button size="small" type="warning" icon="el-icon-refresh" @click="handleSync">从边缘端同步</el-button>
</div>
<el-table :data="algorithmList" border stripe style="width: 100%; margin-top: 15px" v-loading="loading">
<el-table-column prop="algoCode" label="算法编码" min-width="130"></el-table-column>
<el-table-column prop="algoName" label="算法名称" min-width="130"></el-table-column>
<el-table-column prop="targetClass" label="目标类别" width="100"></el-table-column>
<el-table-column prop="description" label="描述" min-width="200"></el-table-column>
<el-table-column label="状态" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isActive"
:active-value="1"
:inactive-value="0"
size="mini"
@change="handleToggle(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column prop="syncTime" label="同步时间" min-width="160"></el-table-column>
<el-table-column label="参数模板" width="100">
<template slot-scope="scope">
<el-button size="mini" @click="showSchema(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog title="参数模板" :visible.sync="schemaDialogVisible" width="600px">
<el-table :data="schemaTableData" border size="small">
<el-table-column prop="name" label="参数名" min-width="150"></el-table-column>
<el-table-column prop="type" label="类型" width="80"></el-table-column>
<el-table-column prop="default" label="默认值" width="120">
<template slot-scope="scope">
{{ typeof scope.row.default === 'object' ? JSON.stringify(scope.row.default) : scope.row.default }}
</template>
</el-table-column>
<el-table-column prop="min" label="最小值" width="80"></el-table-column>
</el-table>
<div slot="footer">
<el-button size="small" @click="schemaDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'AlgorithmConfig',
data() {
return {
loading: false,
algorithmList: [],
schemaDialogVisible: false,
schemaTableData: []
}
},
mounted() {
this.loadData()
},
methods: {
loadData() {
this.loading = true
this.$store.dispatch('aiAlgorithm/queryAlgorithmList').then(data => {
this.algorithmList = data || []
}).catch(() => {
this.$message.error('加载失败')
}).finally(() => {
this.loading = false
})
},
handleToggle(row) {
this.$store.dispatch('aiAlgorithm/toggleAlgorithmActive', [row.id, row.isActive]).then(() => {
this.$message.success('更新成功')
}).catch(() => {
this.$message.error('更新失败')
row.isActive = row.isActive === 1 ? 0 : 1
})
},
handleSync() {
this.$confirm('确定从边缘端同步算法列表?', '提示', { type: 'info' }).then(() => {
this.loading = true
this.$store.dispatch('aiAlgorithm/syncAlgorithmsFromEdge').then(() => {
this.$message.success('同步成功')
this.loadData()
}).catch(err => {
this.$message.error(err.message || '同步失败请检查AI服务是否启用')
}).finally(() => {
this.loading = false
})
}).catch(() => {})
},
showSchema(row) {
try {
const schema = JSON.parse(row.paramSchema)
this.schemaTableData = Object.keys(schema).map(key => ({
name: key,
type: schema[key].type || '-',
default: schema[key].default !== undefined ? schema[key].default : '-',
min: schema[key].min !== undefined ? schema[key].min : '-'
}))
} catch (e) {
this.schemaTableData = []
}
this.schemaDialogVisible = true
}
}
}
</script>
<style scoped>
.algorithm-config-page { padding: 15px; }
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
.page-header h3 { margin: 0; }
</style>