- 后端:新增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>
119 lines
4.2 KiB
Vue
119 lines
4.2 KiB
Vue
<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>
|