lvkun996 hace 2 años
padre
commit
383bd48dc9

+ 52 - 19
src/api/cvs/aiboxCloud.ts

@@ -1,16 +1,22 @@
 import request from '@/service/request'
 
+const jlyResponeType = 'ai-json'
+
 export const getFlow = (clientId: string) => {
   return request({
     url: `/aiBox/control/stream/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    params: { page: 1, pageSize: 10 },
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
 export const addFlow = (clientId: string, data: CVS.AiBox.Flow) => {
   return request({
     url: `/aiBox/control/stream/${clientId}`,
-    method: 'GET',
+    method: 'POST',
     data
   })
 }
@@ -23,9 +29,9 @@ export const updateFlow = (clientId: string, data: CVS.AiBox.Flow) => {
   })
 }
 
-export const delFlow = (clientId: string) => {
+export const delFlow = (clientId: string, num: number) => {
   return request({
-    url: `/aiBox/control/stream/${clientId}`,
+    url: `/aiBox/control/stream/${clientId}?num=${num}`,
     method: 'DELETE'
   })
 }
@@ -33,14 +39,17 @@ export const delFlow = (clientId: string) => {
 export const getTask = (clientId: string) => {
   return request({
     url: `/aiBox/control/task/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
 export const addTask = (clientId: string, data: any) => {
   return request({
     url: `/aiBox/control/task/${clientId}`,
-    method: 'GET',
+    method: 'POST',
     data
   })
 }
@@ -53,20 +62,20 @@ export const updateTask = (clientId: string, data: any) => {
   })
 }
 
-export const delTask = (clientId: string) => {
+export const delTask = (clientId: string, num: number) => {
   return request({
-    url: `/aiBox/control/task/${clientId}`,
+    url: `/aiBox/control/task/${clientId}?num=${num}`,
     method: 'DELETE'
   })
 }
 
-export const startTask = (clientId: string, taskNum: string) => {
+export const startTask = (clientId: string, taskNum: number) => {
   return request({
     url: `/aiBox/control/task/start/${clientId}?taskNum=${taskNum}`,
     method: 'POST'
   })
 }
-export const stopTask = (clientId: string, taskNum: string) => {
+export const stopTask = (clientId: string, taskNum: number) => {
   return request({
     url: `/aiBox/control/task/stop/${clientId}?taskNum=${taskNum}`,
     method: 'POST'
@@ -75,14 +84,20 @@ export const stopTask = (clientId: string, taskNum: string) => {
 export const getTaskImg = (clientId: string, num: string) => {
   return request({
     url: `/aiBox/control/task/img/${clientId}?num=${num}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
 export const getTaskArea = (clientId: string, num: string) => {
   return request({
     url: `/aiBox/control/task/area/${clientId}?num=${num}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
@@ -97,14 +112,20 @@ export const addTaskArea = (clientId: string, data: any) => {
 export const getAig = (clientId: string) => {
   return request({
     url: `/aiBox/control/aig/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
 export const getArg = (clientId: string) => {
   return request({
     url: `/aiBox/control/arg/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
@@ -118,7 +139,10 @@ export const updateArg = (clientId: string) => {
 export const getPLan = (clientId: string) => {
   return request({
     url: `/aiBox/control/plan/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
@@ -130,7 +154,7 @@ export const addPLan = (clientId: string, data: any) => {
   })
 }
 
-export const delPLan = (clientId: string, num: string) => {
+export const delPLan = (clientId: string, num: number) => {
   return request({
     url: `/aiBox/control/plan/${clientId}?num=${num}`,
     method: 'DELETE'
@@ -140,14 +164,20 @@ export const delPLan = (clientId: string, num: string) => {
 export const getSys = (clientId: string) => {
   return request({
     url: `/aiBox/control/dev/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
 export const getMeta = (clientId: string) => {
   return request({
     url: `/aiBox/control/meta/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }
 
@@ -168,6 +198,9 @@ export const calibrationTime = (clientId: string, timestamp: string) => {
 export const getNet = (clientId: string) => {
   return request({
     url: `/aiBox/control/net/${clientId}`,
-    method: 'GET'
+    method: 'GET',
+    Headers: {
+      jlyResponeType
+    }
   })
 }

+ 88 - 7
src/controller/cvs/aiboxCloudController.ts

@@ -1,14 +1,18 @@
 
 // aibox云端
 
-import { addFlow, getFlow, getTask, updateFlow } from '@/api/cvs/aiboxCloud'
+import { addFlow, getFlow, getTask, updateFlow, delFlow, addTask, updateTask, delTask, startTask, stopTask, getPLan, addPLan, delPLan, getAig } from '@/api/cvs/aiboxCloud'
 import { message } from 'ant-design-vue'
 
 export class AiboxCloudController {
-  static clientId = '123457'
+  static clientId = 'JL-ZTAUYTUUMDD6A493D'
 
   static async flow () {
-    return await getFlow(AiboxCloudController.clientId)
+    const data: any = await getFlow(AiboxCloudController.clientId)
+    return {
+      ...data,
+      data: JSON.parse(data?.data).data ? JSON.parse(data?.data).data.map(item => JSON.parse(item)) : []
+    }
   }
 
   static async addFlow (data: CVS.AiBox.Flow) {
@@ -21,12 +25,89 @@ export class AiboxCloudController {
     code === 200 ? message.success('修改视频流成功') : message.error(msg)
   }
 
-  static async delflow () {
-    const { code, msg } = await getFlow(AiboxCloudController.clientId)
+  static async delflow (streamNum: number) {
+    const { code, msg } = await delFlow(AiboxCloudController.clientId, streamNum)
     code === 200 ? message.success('删除视频流成功') : message.error(msg)
   }
 
-  static async getTask () {
-    return await getTask(AiboxCloudController.clientId)
+  static async task () {
+    const data: any = await getTask(AiboxCloudController.clientId)
+    const _data = JSON.parse(data?.data).data
+    return {
+      ...data,
+      data: _data
+        ? _data.map((item) => {
+          const _item = JSON.parse(item as unknown as string)
+          return {
+            ..._item,
+            taskAbility: _item.taskAbility.includes(',') ? _item.taskAbility.split(',') : [_item.taskAbility]
+          }
+        })
+        : []
+    }
+  }
+
+  static async addTask (data: any) {
+    const { msg, code } = await addTask(AiboxCloudController.clientId, {
+      ...data,
+      taskAbility: data.taskAbility.join(',')
+    })
+    code === 200 ? message.success('新增成功') : message.error(msg)
+  }
+
+  static async updateTask (data: any) {
+    const { msg, code } = await updateTask(AiboxCloudController.clientId, {
+      ...data,
+      taskAbility: data.taskAbility.join(',')
+    })
+    code === 200 ? message.success('新增成功') : message.error(msg)
+  }
+
+  static async delTask (num: number) {
+    const { code, msg } = await delTask(AiboxCloudController.clientId, num)
+    code === 200 ? message.success('删除成功') : message.error(msg)
+  }
+
+  static async updateTaskStatus (status: 'start' | 'stop', taskNum: number) {
+    const { code, msg } = status === 'start' ? await startTask(AiboxCloudController.clientId, taskNum) : await stopTask(AiboxCloudController.clientId, taskNum)
+    code === 200 ? message.success(status === 'start' ? '启动成功' : '停止成功') : message.error(msg)
+  }
+
+  static async plan () {
+    const data = await getPLan(AiboxCloudController.clientId)
+    const _data = JSON.parse(JSON.parse(data.data).data)
+    return {
+      ...data,
+      data: _data ? _data.map(item => JSON.parse(item)) : []
+    }
+  }
+
+  static async addPlan (data: any) {
+    const { msg, code } = await addPLan(AiboxCloudController.clientId, data)
+    code === 200 ? message.success('新增成功') : message.error(msg)
+  }
+
+  static async updatePlan (data: any) {
+    const { msg, code } = await addPLan(AiboxCloudController.clientId, data)
+    code === 200 ? message.success('新增成功') : message.error(msg)
+  }
+
+  static async delPlan (num: number) {
+    const { code, msg } = await delPLan(AiboxCloudController.clientId, num)
+    code === 200 ? message.success('删除成功') : message.error(msg)
+  }
+
+  static async aig () {
+    const data = await getAig(AiboxCloudController.clientId)
+    console.log(JSON.parse(JSON.parse(data.data).data).data)
+
+    // const _data = JSON.parse(JSON.parse(data.data).data).map(item => {
+    //   const targetTask = curTask.taskAbility.find(task => item.aigonum === task.aigonum)
+    //   return {
+    //     ...item,
+    //     isSelect: curTask.taskAbility.map(task => task.aigonum).includes(item.aigonum),
+    //     setparam: targetTask && targetTask.setparam ? targetTask.setparam : item.setparam
+    //   }
+    // })
   }
 }

+ 139 - 138
src/controller/cvs/aiboxController.ts

@@ -1,138 +1,139 @@
-import {
-  addAiBoxForward,
-  aiboxLevelUp,
-  delAiBoxForward,
-  dimensionAiBox,
-  getAiBoxEvent,
-  getAiBoxForward,
-  getAiBoxList,
-  getAiBoxPage,
-  getStream,
-  getSys,
-  getTaskByClientId,
-  getWarnOssUrl,
-  reboot,
-  refreshStream,
-  refreshSys,
-  refreshTask,
-  updateAiBoxForward
-} from '@/api/cvs/aibox'
-import { updateForward } from '@/api/iot/rule'
-import { message } from 'ant-design-vue'
-
-export class AiboxController {
-  static eventType: {EventType: CVS.AiBox.eventType, EventName: string}[] = [
-    { EventType: '0', EventName: '人脸识别' },
-    { EventType: '1', EventName: '人流统计' },
-    { EventType: '2', EventName: '明烟明火' },
-    { EventType: '3', EventName: '抽烟打电话' },
-    { EventType: '4', EventName: '口罩检测' },
-    { EventType: '5', EventName: '安全帽检测' },
-    { EventType: '6', EventName: '越线监测' },
-    { EventType: '7', EventName: '区域围栏' },
-    { EventType: '8', EventName: '反光衣检测' },
-    { EventType: '9', EventName: '电动车检测' }
-  ]
-
-  static eventTypeMap = new Map([
-    ['0', '人脸识别'],
-    ['1', '人流统计'],
-    ['2', '明烟明火'],
-    ['3', '抽烟打电话'],
-    ['4', '口罩检测'],
-    ['5', '安全帽检测'],
-    ['6', '越线监测'],
-    ['7', '区域围栏'],
-    ['8', '反光衣检测'],
-    ['9', '电动车检测']
-  ])
-
-  static async page (params: COMMON.API.QueryParams & {name?: string, state: 'OFFLINE' | 'ONLINE'}) {
-    return await getAiBoxPage(params)
-  }
-
-  static async list () {
-    const { code, data } = await getAiBoxList()
-    if (code === 200) {
-      return data
-    }
-  }
-
-  static async dimension (data: Partial<CVS.AiBox.AiBox>) {
-    const { code, msg } = await dimensionAiBox(data)
-    code === 200 ? message.success('修改成功') : message.error(msg)
-  }
-
-  static async levelUp (params: {devId: string, aiId: string, version: string, file: any}) {
-    const { code, data } = await aiboxLevelUp(params)
-    code === 200 && data ? message.success('升级成功') : message.error('升级失败')
-  }
-
-  static async taskById (clientId: string) {
-    const { code, data } = await getTaskByClientId(clientId)
-    if (code === 200) {
-      return data
-    }
-  }
-
-  static async refreshTask (clientId: string) {
-    await refreshTask(clientId)
-  }
-
-  static async stream (clientId: string) {
-    const { code, data } = await getStream(clientId)
-    if (code === 200) {
-      return data
-    }
-  }
-
-  static async refreshStream (clientId: string) {
-    await refreshStream(clientId)
-  }
-
-  static async sys (clientId: string) {
-    const { code, data } = await getSys(clientId)
-    if (code === 200) {
-      return data
-    }
-  }
-
-  static async warnOssUrl () {
-    const { code, data } = await getWarnOssUrl()
-    if (code === 200) {
-      return data
-    }
-  }
-
-  static async refreshSys (clientId: string) {
-    await refreshSys(clientId)
-  }
-
-  static async reboot (clientId: string) {
-    const { code, msg } = await reboot(clientId)
-    code === 200 ? message.success('重启成功') : message.error(msg)
-  }
-
-  static async event (params: {devId: string, eventType: CVS.AiBox.eventType, start: string, end: string}) {
-    return await getAiBoxEvent(params)
-  }
-
-  static async forward () {
-    return await getAiBoxForward()
-  }
-
-  static async addForward (data: CVS.AiBox.Forward) {
-    const { code, msg } = await addAiBoxForward(data)
-    code === 200 ? message.success('新增成功') : message.error(msg)
-  }
-
-  static async updateForward (data: CVS.AiBox.Forward) {
-    const { code, msg } = await updateAiBoxForward(data)
-    code === 200 ? message.success('修改成功') : message.error(msg)
-  }
-
-  static async delForward (id: string, _data: CVS.AiBox.Forward) {
-    const { code, msg, data } = await delAiBoxForward(id, _data)
-    code === 200 && data ? message.success('删除成功') : message.error('删除失败')
-  }
-}
+import {
+  addAiBoxForward,
+  aiboxLevelUp,
+  delAiBoxForward,
+  dimensionAiBox,
+  getAiBoxEvent,
+  getAiBoxForward,
+  getAiBoxList,
+  getAiBoxPage,
+  getStream,
+  getSys,
+  getTaskByClientId,
+  getWarnOssUrl,
+  reboot,
+  refreshStream,
+  refreshSys,
+  refreshTask,
+  updateAiBoxForward
+} from '@/api/cvs/aibox'
+import { getAig } from '@/api/cvs/aiboxCloud'
+import { updateForward } from '@/api/iot/rule'
+import { message } from 'ant-design-vue'
+
+export class AiboxController {
+  static eventType: {EventType: CVS.AiBox.eventType, EventName: string}[] = [
+    { EventType: '0', EventName: '人脸识别' },
+    { EventType: '1', EventName: '人流统计' },
+    { EventType: '2', EventName: '明烟明火' },
+    { EventType: '3', EventName: '抽烟打电话' },
+    { EventType: '4', EventName: '口罩检测' },
+    { EventType: '5', EventName: '安全帽检测' },
+    { EventType: '6', EventName: '越线监测' },
+    { EventType: '7', EventName: '区域围栏' },
+    { EventType: '8', EventName: '反光衣检测' },
+    { EventType: '9', EventName: '电动车检测' }
+  ]
+
+  static eventTypeMap = new Map([
+    ['0', '人脸识别'],
+    ['1', '人流统计'],
+    ['2', '明烟明火'],
+    ['3', '抽烟打电话'],
+    ['4', '口罩检测'],
+    ['5', '安全帽检测'],
+    ['6', '越线监测'],
+    ['7', '区域围栏'],
+    ['8', '反光衣检测'],
+    ['9', '电动车检测']
+  ])
+
+  static async page (params: COMMON.API.QueryParams & {name?: string, state: 'OFFLINE' | 'ONLINE'}) {
+    return await getAiBoxPage(params)
+  }
+
+  static async list () {
+    const { code, data } = await getAiBoxList()
+    if (code === 200) {
+      return data
+    }
+  }
+
+  static async dimension (data: Partial<CVS.AiBox.AiBox>) {
+    const { code, msg } = await dimensionAiBox(data)
+    code === 200 ? message.success('修改成功') : message.error(msg)
+  }
+
+  static async levelUp (params: {devId: string, aiId: string, version: string, file: any}) {
+    const { code, data } = await aiboxLevelUp(params)
+    code === 200 && data ? message.success('升级成功') : message.error('升级失败')
+  }
+
+  static async taskById (clientId: string) {
+    const { code, data } = await getTaskByClientId(clientId)
+    if (code === 200) {
+      return data
+    }
+  }
+
+  static async refreshTask (clientId: string) {
+    await refreshTask(clientId)
+  }
+
+  static async stream (clientId: string) {
+    const { code, data } = await getStream(clientId)
+    if (code === 200) {
+      return data
+    }
+  }
+
+  static async refreshStream (clientId: string) {
+    await refreshStream(clientId)
+  }
+
+  static async sys (clientId: string) {
+    const { code, data } = await getSys(clientId)
+    if (code === 200) {
+      return data
+    }
+  }
+
+  static async warnOssUrl () {
+    const { code, data } = await getWarnOssUrl()
+    if (code === 200) {
+      return data
+    }
+  }
+
+  static async refreshSys (clientId: string) {
+    await refreshSys(clientId)
+  }
+
+  static async reboot (clientId: string) {
+    const { code, msg } = await reboot(clientId)
+    code === 200 ? message.success('重启成功') : message.error(msg)
+  }
+
+  static async event (params: {devId: string, eventType: CVS.AiBox.eventType, start: string, end: string}) {
+    return await getAiBoxEvent(params)
+  }
+
+  static async forward () {
+    return await getAiBoxForward()
+  }
+
+  static async addForward (data: CVS.AiBox.Forward) {
+    const { code, msg } = await addAiBoxForward(data)
+    code === 200 ? message.success('新增成功') : message.error(msg)
+  }
+
+  static async updateForward (data: CVS.AiBox.Forward) {
+    const { code, msg } = await updateAiBoxForward(data)
+    code === 200 ? message.success('修改成功') : message.error(msg)
+  }
+
+  static async delForward (id: string, _data: CVS.AiBox.Forward) {
+    const { code, msg, data } = await delAiBoxForward(id, _data)
+    code === 200 && data ? message.success('删除成功') : message.error('删除失败')
+  }
+}

+ 32 - 0
src/pages/cvs/edge/abilityList.ts

@@ -0,0 +1,32 @@
+export const abilityList = [
+  { value: '01', label: '明烟明火检测' },
+  { value: '02', label: '反光衣检测' },
+  { value: '03', label: '安全帽检测' },
+  { value: '04', label: '无消防器材' },
+  { value: '05', label: '街道垃圾检测' },
+  { value: '06', label: '垃圾桶满溢检测' },
+  { value: '07', label: '占道经营检测' },
+  { value: '08', label: '小动物检测' },
+  { value: '09', label: '电瓶车进电梯识别' },
+  { value: '10', label: '区域车辆禁停' },
+  { value: '11', label: '非机动车停放' },
+  { value: '12', label: '打架检测' },
+  { value: '13', label: '人员摔倒监测' },
+  { value: '14', label: '人数监控' },
+  { value: '15', label: '人流统计' },
+  { value: '16', label: '越线监测' },
+  { value: '17', label: '区域入侵' },
+  { value: '18', label: '人员拥挤检测' },
+  { value: '19', label: '长袖检测' },
+  { value: '20', label: '工服检测' },
+  { value: '21', label: '进入检测' },
+  { value: '22', label: '离开检测' },
+  { value: '23', label: '出现检测' },
+  { value: '24', label: '翻越围栏' },
+  { value: '25', label: '离岗检测' },
+  { value: '26', label: '睡岗检测' },
+  { value: '27', label: '口罩检测' },
+  { value: '28', label: '抽烟打电话' },
+  { value: '29', label: '人脸识别' },
+  { value: '30', label: '人脸抓拍' }
+]

+ 126 - 1
src/pages/cvs/edge/aiTask.vue

@@ -1,7 +1,132 @@
 <template>
-  aitask
+  <a-card title="任务管理"  >
+    <table-pro
+      :service='AiboxCloudController.task'
+      :columns="columns"
+      ref="tableProDom"
+      @add="openModal('add')"
+    >
+    <template #render="{ column, record }">
+        <template v-if="column.key === 'taskAbility'">
+          <a-tag :key="item.value" v-for="item in abilityList.filter( able => record.taskAbility.includes(able.value))"  >
+            {{item.label}}
+          </a-tag>
+        </template>
+        <template v-if="column.key === 'taskState'">
+          <a-tag :color="taskStateMap.get(record.taskState)?.color" >
+            {{taskStateMap.get(record.taskState)?.label}}
+          </a-tag>
+        </template>
+        <template v-if="column.key === 'action'">
+          <a-space>
+            <a  @click="updateTaskStatus('start', record.taskNum)" >启动任务</a>
+            <a  @click="updateTaskStatus('stop', record.taskNum)" >停止任务</a>
+            <a @click="openModal('update', record)" >编辑</a>
+            <!-- <a @click="openDisposeModal(record)" >配置区域</a> -->
+            <a-popconfirm
+              title="确定要删除这个任务吗"
+              ok-text="Yes"
+              cancel-text="No"
+              @confirm="delTask(record.taskNum)"
+            >
+              <a >删除</a>
+            </a-popconfirm>
+          </a-space>
+        </template>
+    </template>
+    </table-pro>
+  </a-card>
+
+  <RealView
+    :title="state.opraState === 'add' ? '新增任务' : '编辑任务'"
+    :open="state.visible"
+    @cancel='state.visible = false'
+    @ok='submit'
+  >
+    <add-form ref="addFormRef" :opra-state="state.opraState"  :item-data="state.taskState" />
+  </RealView>
 </template>
 <script lang='ts'  setup >
+import { AiboxCloudController } from '@/controller'
+import { computed, onMounted, reactive, ref } from 'vue'
+import { RealView } from '@/components/RealView/index'
+import AddForm from './components/add.vue'
+
+const columns = [
+  {
+    title: '任务编号',
+    dataIndex: 'taskNum',
+    key: 'taskNum'
+  },
+  {
+    title: '任务名称',
+    dataIndex: 'taskID',
+    key: 'taskID'
+  },
+  {
+    title: '任务流',
+    dataIndex: 'taskStream',
+    key: 'taskStream'
+  },
+  {
+    title: '算法配置',
+    dataIndex: 'taskAbility',
+    key: 'taskAbility'
+  },
+  {
+    title: '任务描述',
+    dataIndex: 'taskDescribe',
+    key: 'taskDescribe'
+  },
+  {
+    title: '任务状态',
+    dataIndex: 'taskState',
+    key: 'taskState'
+  },
+  {
+    title: '操作',
+    dataIndex: 'action',
+    key: 'action'
+  }
+]
+
+const tableProDom = ref()
+
+const addFormRef = ref()
+
+const state = reactive<{
+  loading: boolean,
+  visible: boolean,
+  dataSource: any,
+  opraState: 'add' | 'update',
+  taskState: any
+}>({
+  loading: false,
+  visible: false,
+  dataSource: [],
+  opraState: 'add',
+  taskState: {}
+})
+
+const openModal = (type: 'add' | 'update', record = {}) => {
+  state.opraState = type
+  state.visible = true
+  state.taskState = record
+}
+
+const submit = () => {
+  addFormRef.value.submit()
+}
+
+const updateTaskStatus = async (status: 'start' | 'stop', taskNum: number) => {
+  await AiboxCloudController.updateTaskStatus(status, taskNum)
+  tableProDom.value.reload()
+}
+
+const delTask = async (taskNum: number) => {
+  await AiboxCloudController.delTask(taskNum)
+  tableProDom.value.reload()
+}
 
 </script>
 <style lang='less' scoped >

+ 239 - 0
src/pages/cvs/edge/components/add.vue

@@ -0,0 +1,239 @@
+<template>
+  <a-card title="添加任务"  >
+    <a-form
+    :label-col="{ span: 6 }"
+    :wrapper-col="{ span: 14 }"
+  >
+    <a-form-item
+      label="任务名称"
+      v-bind="validateInfos.taskID"
+    >
+      <a-input  v-model:value="taskState.taskID" />
+    </a-form-item>
+    <a-form-item
+      label="任务流"
+      v-bind="validateInfos.taskStream"
+    >
+      <a-select
+        v-model:value="taskState.taskStream"
+      >
+        <a-select-option
+          v-for="item in state.videDataSource"
+          :key="item.streamID"
+          :value="item.streamNum"
+        >
+          {{item.streamID}}
+        </a-select-option>
+      </a-select>
+    </a-form-item>
+    <a-form-item
+      label="任务描述"
+      v-bind="validateInfos.taskDescribe"
+    >
+      <a-input  v-model:value="taskState.taskDescribe" />
+    </a-form-item>
+    <a-form-item
+      label="工作模版"
+      v-bind="validateInfos.taskPlan"
+    >
+      <a-select
+        v-model:value="taskState.taskPlan"
+      >
+        <a-select-option
+          v-for="item in state.planDataSource"
+          :key="item.planNum"
+          :value="item.planNum"
+        >
+          {{item.planName}}
+        </a-select-option>
+      </a-select>
+    </a-form-item>
+    <a-form-item
+      label="上报地址"
+      v-bind="validateInfos.taskUploadAddr"
+    >
+      <a-input  v-model:value="taskState.taskUploadAddr" />
+    </a-form-item>
+    <a-form-item
+      label="国标通道编号"
+      v-bind="validateInfos.taskGB28121Addr"
+    >
+      <a-input  v-model:value="taskState.taskGB28121Addr" />
+    </a-form-item>
+    <a-form-item
+      label="算法设置"
+      v-bind="validateInfos.taskAbility"
+    >
+      <a-checkbox-group :value="taskState.taskAbility" style="width: 100%" @change="onChangeAbility">
+        <a-row>
+          <a-col :span="8" v-for="item in abilityList" :key="item.value" >
+            <a-checkbox :value="item.value">{{item.label}}</a-checkbox>
+          </a-col>
+        </a-row>
+      </a-checkbox-group>
+    </a-form-item>
+    <a-form-item
+      label="区域车辆禁停配置"
+      v-bind="validateInfos.taskCarConf"
+      v-if="taskState.taskAbility.includes('10')"
+    >
+      <a-input-number addon-before="停靠时长(分)" v-model:value="taskState.taskCarConf" />
+    </a-form-item>
+    <a-form-item
+      label="拥挤度设置"
+      v-bind="validateInfos.taskCongestionConf"
+      v-if="taskState.taskAbility.includes('18')"
+    >
+      <a-input-number addon-after="人"  v-model:value="taskState.taskCongestionConf" />
+    </a-form-item>
+    <a-form-item
+      label="离岗检测配置"
+      v-bind="validateInfos.taskDepartureTime"
+      v-if="taskState.taskAbility.includes('25')"
+    >
+    <a-input-group size="large">
+      <a-row :gutter="8">
+        <a-col :span="8">
+          <a-input-number  addon-before="超时时间(秒)"  v-model:value="taskState.taskDepartureTime" />
+        </a-col>
+        <a-col :span="8">
+          <a-input-number  addon-before="要求在岗人数"  v-model:value="taskState.taskDeparturePeople" />
+        </a-col>
+      </a-row>
+    </a-input-group>
+    </a-form-item>
+    <a-form-item
+      label="工服选择"
+      v-bind="validateInfos.taskWork"
+      v-if="taskState.taskAbility.includes('20')"
+    >
+    <a-select
+        v-model:value="taskState.taskWork"
+      >
+        <a-select-option
+          v-for="item in state.workDataSource"
+          :key="item.workclothesName"
+          :value="item.workclothesName"
+        >
+          {{item.workclothesName}}
+        </a-select-option>
+      </a-select>
+    </a-form-item>
+    <a-form-item
+      label="人脸识别配置"
+      v-bind="validateInfos.taskSimilarityThreshold"
+      v-if="taskState.taskAbility.includes('29')"
+    >
+    <a-input-group size="large">
+      <a-row :gutter="8">
+        <a-col :span="8">
+          <a-input-number  v-model:value="taskState.taskSimilarityThreshold" addon-before="相似度阈值"/>
+        </a-col>
+        <a-col :span="8">
+          <a-input-number  v-model:value="taskState.taskStrangerThreshold" addon-before="陌生人阈值"/>
+        </a-col>
+      </a-row>
+    </a-input-group>
+    </a-form-item>
+  </a-form>
+  </a-card>
+</template>
+<script lang='ts'  setup >
+import { onMounted, reactive, watch } from 'vue'
+import { Form, message } from 'ant-design-vue'
+import { AiboxCloudController } from '@/controller'
+import { abilityList } from '../abilityList'
+
+const IProps = defineProps<{
+  opraState: 'add' | 'update',
+  itemData: any
+}>()
+
+const state = reactive({
+  videDataSource: [],
+  planDataSource: [],
+  workDataSource: []
+})
+
+const taskState = reactive({
+  taskID: '',
+  taskStream: '',
+  taskDescribe: '',
+  taskPlan: '',
+  taskUploadAddr: '',
+  taskGB28121Addr: '',
+  taskAbility: [],
+  taskSimilarityThreshold: 0.45,
+  taskStrangerThreshold: 0.45
+})
+
+const useForm = Form.useForm
+
+const { resetFields, validate, validateInfos } = useForm(taskState, reactive({
+  taskID: [{ required: true, message: '请输入任务名称' }],
+  taskStream: [{ required: true, message: '请输入任务流' }],
+  taskDescribe: [{ required: true, message: '请输入任务描述' }],
+  taskPlan: [{ required: true, message: '请选择工作模板' }],
+  taskUploadAddr: [{ required: true, message: '请输入上班地址' }],
+  taskGB28121Addr: [{ required: true, message: '请输入国标通道编号' }],
+  taskAbility: [{ required: true, message: '请选择3个以内的算法' }]
+}))
+
+const submit = () => {
+  return new Promise((resolve) => {
+    validate().then(async () => {
+      IProps.opraState === 'add' ? await AiboxCloudController.addTask(taskState) : await AiboxCloudController.updateTask(taskState)
+      resolve(true)
+    })
+  })
+}
+
+defineExpose({
+  submit
+})
+
+watch(
+  () => IProps.opraState,
+  () => {
+    if (IProps.opraState === 'update') {
+      resetFields(IProps.itemData)
+    }
+  },
+  {
+    immediate: true
+  }
+)
+const onChangeAbility = (record: string[]) => {
+  if (record.length >= 4) {
+    message.error('最多选择三个算法')
+    return
+  }
+  taskState.taskAbility = record
+}
+
+const getFlow = async () => {
+  const { data } = await AiboxCloudController.flow()
+  state.videDataSource = data
+}
+
+const getPlan = async () => {
+  const { data } = await PlanController.page()
+  state.planDataSource = data
+}
+
+const getOtherWork = async () => {
+  const { data } = await OtherController.otherArg('work')
+  state.workDataSource = data
+}
+
+onMounted(() => {
+  getFlow()
+  // getPlan()
+  // getOtherWork()
+  AiboxCloudController.aig()
+})
+
+</script>
+<style lang='less' scoped >
+
+</style>

+ 118 - 2
src/pages/cvs/edge/flow.vue

@@ -3,6 +3,8 @@
     <table-pro
       :service="AiboxCloudController.flow"
       :columns="columns"
+      ref="tableProDom"
+      @add="openModal('add')"
     >
       <template #search >
         <a-space>
@@ -31,9 +33,75 @@
     </template>
     </table-pro>
   </a-card>
+
+  <modal-pro
+  :label="modalTitle"
+  :open="state.visible"
+  destroyOnClose
+  @cancel="state.visible = false"
+  @ok="ok"
+>
+  <a-form
+    :label-col="{ span: 6 }"
+    :wrapper-col="{ span: 14 }"
+  >
+    <a-form-item
+      label="视频流ID"
+      v-bind="validateInfos.streamID"
+    >
+      <a-input  v-model:value="videoDetailState.streamID" />
+    </a-form-item>
+
+    <a-form-item
+      label="视频流"
+      v-bind="validateInfos.streamName"
+    >
+      <a-input   v-model:value="videoDetailState.streamName" />
+    </a-form-item>
+    <a-form-item
+      label="视频描述"
+      v-bind="validateInfos.streamDescribe"
+    >
+      <a-input v-model:value="videoDetailState.streamDescribe" />
+    </a-form-item>
+    <a-form-item
+      label="RTSP本地代理"
+    >
+      <a-switch v-model:checked="videoDetailState.rtspEnable" checked-children="开" un-checked-children="关" />
+    </a-form-item>
+    <a-form-item
+      label="转发到国标服务"
+    >
+      <a-switch v-model:checked="videoDetailState.gbEnable" checked-children="开" un-checked-children="关" />
+    </a-form-item>
+    <a-form-item
+      label="国标通道编号"
+    >
+      <a-input v-model:value="videoDetailState.gbChannel" />
+    </a-form-item>
+    <a-form-item
+      label="转发到国标服务"
+    >
+      <a-input v-model:value="videoDetailState.deviceSerialCode" />
+    </a-form-item>
+    <a-form-item
+      label="是否轮训"
+    >
+    <a-checkbox v-model:checked="videoDetailState.isFor">是否轮询</a-checkbox>
+    </a-form-item>
+    <a-form-item
+      label="轮询时间"
+      v-if="videoDetailState.isFor"
+    >
+      <a-input-number v-model:value="videoDetailState.polling" min="0"  addon-after="分钟"></a-input-number>
+    </a-form-item>
+  </a-form>
+</modal-pro>
 </template>
 <script lang='ts'  setup >
 import { AiboxCloudController } from '@/controller'
+import { computed, onMounted, reactive, ref } from 'vue'
+import { Form } from 'ant-design-vue'
 
 const columns = [
   {
@@ -73,11 +141,59 @@ const columns = [
   }
 ]
 
-const openModal = (type: 'add' | 'update', Record) => {
+const tableProDom = ref()
+
+const modalTitle = computed(() => state.opraState === 'add' ? '新增视频流' : '编辑视频流')
+
+const state = reactive({
+  opraState: 'add',
+  loading: false,
+  visible: false,
+  dataSource: []
+})
+
+const videoDetailState = reactive<CVS.AiBox.Flow>({
+  streamNum: '',
+  streamID: '',
+  streamName: '',
+  deviceSerialCode: '',
+  rtspEnable: false,
+  gbEnable: false,
+  gbChannel: '',
+  streamDescribe: '',
+  isFor: false,
+  polling: '1'
+})
+
+const useForm = Form.useForm
 
+const { resetFields, validate, validateInfos } = useForm(videoDetailState, reactive({
+  streamID: [{ required: true, message: '请输入视频流ID' }],
+  streamName: [{ required: true, message: '请输入视频流名称' }],
+  streamDescribe: [{ required: true, message: '请输入视频描述' }]
+}))
+
+const ok = () => {
+  console.log(videoDetailState)
+  validate().then(async () => {
+    state.opraState === 'add' ? await AiboxCloudController.addFlow(videoDetailState) : await AiboxCloudController.updateFlow(videoDetailState)
+    state.visible = false
+    tableProDom.value.reload()
+  }).catch(err => {
+    console.log('error', err)
+  })
+}
+
+const openModal = (type: 'add' | 'update', record = {}) => {
+  state.opraState = type
+  state.visible = true
+  resetFields(record)
 }
 
-const delFlow = (streamNum: number) => {}
+const delFlow = async (streamNum: number) => {
+  await AiboxCloudController.delflow(streamNum)
+  tableProDom.value.reload()
+}
 
 </script>
 <style lang='less' scoped >

+ 3 - 1
src/pages/cvs/edge/plan.vue

@@ -1,5 +1,7 @@
 <template>
-plan
+<a-card title="计划模板" >
+
+</a-card>
 </template>
 <script lang='ts'  setup >
 

+ 4 - 1
vue.config.js

@@ -14,7 +14,10 @@ module.exports = defineConfig({
     headers: {
       'Access-Control-Allow-Origin': '*'
     },
-    port: 10800
+    port: 10800,
+    client: {
+      overlay: false
+    }
   },
   pluginOptions: {
     'style-resources-loader': {