ソースを参照

feat: pull new fear

unknown 8 ヶ月 前
コミット
b293fe9b7a

+ 146 - 0
src/api/interface/demo/AlgorithmConfigTrack.ts

@@ -0,0 +1,146 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface AlgorithmConfigTrackVO extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id: string | number
+
+  /**
+   * 类型
+   */
+  type: string
+
+  /**
+   * 父id
+   */
+  parentId: string | number
+
+  /**
+   * 分系统
+   */
+  subsystem: string
+
+  /**
+   * 算法名称
+   */
+  algorithmName: string
+
+  /**
+   * 算法地址
+   */
+  algorithmAddress: string
+
+  /**
+   * 参数配置
+   */
+  parameterConfig: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * 系统
+   */
+  system: string
+}
+
+export interface AlgorithmConfigTrackForm {
+  /**
+   * 主键ID
+   */
+  id?: string | number
+
+  /**
+   * 类型
+   */
+  type?: string
+
+  /**
+   * 父id
+   */
+  parentId?: string | number
+
+  /**
+   * 分系统
+   */
+  subsystem?: string
+
+  /**
+   * 算法名称
+   */
+  algorithmName?: string
+
+  /**
+   * 算法地址
+   */
+  algorithmAddress?: string
+
+  /**
+   * 参数配置
+   */
+  parameterConfig?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 乐观锁
+   */
+  version?: number
+
+  /**
+   * 系统
+   */
+  system?: string
+}
+
+export interface AlgorithmConfigTrackQuery extends PageQuery {
+  /**
+   * 类型
+   */
+  type?: string
+
+  /**
+   * 父id
+   */
+  parentId?: string | number
+
+  /**
+   * 分系统
+   */
+  subsystem?: string
+
+  /**
+   * 算法名称
+   */
+  algorithmName?: string
+
+  /**
+   * 算法地址
+   */
+  algorithmAddress?: string
+
+  /**
+   * 参数配置
+   */
+  parameterConfig?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 系统
+   */
+  system?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 131 - 0
src/api/interface/demo/AlgorithmModelTrack.ts

@@ -0,0 +1,131 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface AlgorithmModelTrackVO extends BaseEntity {
+  /**
+   * 主键ID
+   */
+  id: string | number
+
+  /**
+   * 算法
+   */
+  algorithmId: string | number
+
+  /**
+   * 模型名称
+   */
+  modelName: string
+
+  /**
+   * 模型
+   */
+  modelAddress: string
+
+  /**
+   * 训练样本数
+   */
+  sampleNumber: number
+
+  /**
+   * 训练循环次数
+   */
+  cycleEpoch: number
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * 系统
+   */
+  system: string
+}
+
+export interface AlgorithmModelTrackForm {
+  /**
+   * 主键ID
+   */
+  id?: string | number
+
+  /**
+   * 算法
+   */
+  algorithmId?: string | number
+
+  /**
+   * 模型名称
+   */
+  modelName?: string
+
+  /**
+   * 模型
+   */
+  modelAddress?: string
+
+  /**
+   * 训练样本数
+   */
+  sampleNumber?: number
+
+  /**
+   * 训练循环次数
+   */
+  cycleEpoch?: number
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 乐观锁
+   */
+  version?: number
+
+  /**
+   * 系统
+   */
+  system?: string
+}
+
+export interface AlgorithmModelTrackQuery extends PageQuery {
+  /**
+   * 算法
+   */
+  algorithmId?: string | number
+
+  /**
+   * 模型名称
+   */
+  modelName?: string
+
+  /**
+   * 模型
+   */
+  modelAddress?: string
+
+  /**
+   * 训练样本数
+   */
+  sampleNumber?: number
+
+  /**
+   * 训练循环次数
+   */
+  cycleEpoch?: number
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 系统
+   */
+  system?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 221 - 0
src/api/interface/demo/DataSeq.ts

@@ -0,0 +1,221 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface DataSeqVO extends BaseEntity {
+  /**
+   * id
+   */
+  id: string | number
+
+  /**
+   * 名称
+   */
+  name: string
+
+  /**
+   * 数据类型
+   */
+  dataType: string
+
+  /**
+   * 文件类型
+   */
+  fileType: string
+
+  /**
+   * 目标类型
+   */
+  objectType: string
+
+  /**
+   * 目标子类型
+   */
+  objectSubtype: string
+
+  /**
+   * 批次号
+   */
+  batchNum: string
+
+  /**
+   * 场景
+   */
+  scene: string
+
+  /**
+   * 数据源
+   */
+  dataSource: string
+
+  /**
+   * 采集时间
+   */
+  gatherTime: string
+
+  /**
+   * 采集地点
+   */
+  gatherSpot: string
+
+  /**
+   * 图片url
+   */
+  url: string
+
+  /**
+   * 日志
+   */
+  log: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+}
+
+export interface DataSeqForm {
+  /**
+   * id
+   */
+  id?: string | number
+
+  /**
+   * 名称
+   */
+  name?: string
+
+  /**
+   * 数据类型
+   */
+  dataType?: string
+
+  /**
+   * 文件类型
+   */
+  fileType?: string
+
+  /**
+   * 目标类型
+   */
+  objectType?: string
+
+  /**
+   * 目标子类型
+   */
+  objectSubtype?: string
+
+  /**
+   * 批次号
+   */
+  batchNum?: string
+
+  /**
+   * 场景
+   */
+  scene?: string
+
+  /**
+   * 数据源
+   */
+  dataSource?: string
+
+  /**
+   * 采集时间
+   */
+  gatherTime?: string
+
+  /**
+   * 采集地点
+   */
+  gatherSpot?: string
+
+  /**
+   * 图片url
+   */
+  url?: string
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 乐观锁
+   */
+  version?: number
+}
+
+export interface DataSeqQuery extends PageQuery {
+  /**
+   * 名称
+   */
+  name?: string
+
+  /**
+   * 数据类型
+   */
+  dataType?: string
+
+  /**
+   * 文件类型
+   */
+  fileType?: string
+
+  /**
+   * 目标类型
+   */
+  objectType?: string
+
+  /**
+   * 目标子类型
+   */
+  objectSubtype?: string
+
+  /**
+   * 批次号
+   */
+  batchNum?: string
+
+  /**
+   * 场景
+   */
+  scene?: string
+
+  /**
+   * 数据源
+   */
+  dataSource?: string
+
+  /**
+   * 采集时间
+   */
+  gatherTime?: string
+
+  /**
+   * 采集地点
+   */
+  gatherSpot?: string
+
+  /**
+   * 图片url
+   */
+  url?: string
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 237 - 0
src/api/interface/demo/TargetDetection.ts

@@ -0,0 +1,237 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+
+export interface TargetDetectionVO extends BaseEntity {
+  /**
+   * ID
+   */
+  id: string | number
+
+  /**
+   * 任务名称
+   */
+  name: string
+
+  /**
+   * 状态
+   0:未开始
+   1:进行中
+   2:完成
+   3:失败
+   4:中断
+   */
+  status: string
+
+  /**
+   * 开始时间
+   */
+  startTime: string
+
+  /**
+   * 结束时间
+   */
+  endTime: string
+
+  /**
+   * 耗时
+   */
+  costSecond: number
+
+  /**
+   * 日志
+   */
+  log: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * $column.columnComment
+   */
+  url: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath: string
+
+  /**
+   * 输出路径
+   */
+  outputPath: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath: string
+
+  /**
+   * 模型的id
+   */
+  algorithmModelId: string | number
+}
+
+export interface TargetDetectionForm {
+  /**
+   * ID
+   */
+  id?: string | number
+
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+   * 状态
+   0:未开始
+   1:进行中
+   2:完成
+   3:失败
+   4:中断
+   */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  version?: number
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath?: string
+
+  /**
+   * 模型的id
+   */
+  algorithmModelId?: string | number
+}
+
+export interface TargetDetectionQuery extends PageQuery {
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+   * 状态
+   0:未开始
+   1:进行中
+   2:完成
+   3:失败
+   4:中断
+   */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath?: string
+
+  /**
+   * 模型的id
+   */
+  algorithmModelId?: string | number
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 206 - 0
src/api/interface/demo/toInfrared.ts

@@ -0,0 +1,206 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface ToInfraredVO extends BaseEntity {
+  /**
+   * ID
+   */
+  id: string | number
+
+  /**
+   * 任务名称
+   */
+  name: string
+
+  /**
+    * 状态
+    0:未开始
+    1:进行中
+    2:完成
+    3:失败
+    4:中断
+        */
+  status: string
+
+  /**
+   * 开始时间
+   */
+  startTime: string
+
+  /**
+   * 结束时间
+   */
+  endTime: string
+
+  /**
+   * 耗时
+   */
+  costSecond: number
+
+  /**
+   * 日志
+   */
+  log: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * $column.columnComment
+   */
+  url: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath: string
+
+  /**
+   * 输出路径
+   */
+  outputPath: string
+}
+
+export interface ToInfraredForm {
+  /**
+   * ID
+   */
+  id?: string | number
+
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+        * 状态
+0:未开始
+1:进行中
+2:完成
+3:失败
+4:中断
+        */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  version?: number
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+}
+
+export interface ToInfraredQuery extends PageQuery {
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+        * 状态
+0:未开始
+1:进行中
+2:完成
+3:失败
+4:中断
+        */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 221 - 0
src/api/interface/demo/trackSequence.ts

@@ -0,0 +1,221 @@
+import { PageQuery, BaseEntity } from '@/api/interface/index'
+export interface TrackSequenceVO extends BaseEntity {
+  /**
+   * ID
+   */
+  id: string | number
+
+  /**
+   * 任务名称
+   */
+  name: string
+
+  /**
+    * 状态
+        0:未开始
+        1:进行中
+        2:完成
+        3:失败
+        4:中断
+    */
+  status: string
+
+  /**
+   * 开始时间
+   */
+  startTime: string
+
+  /**
+   * 结束时间
+   */
+  endTime: string
+
+  /**
+   * 耗时
+   */
+  costSecond: number
+
+  /**
+   * 日志
+   */
+  log: string
+
+  /**
+   * 备注
+   */
+  remarks: string
+
+  /**
+   * $column.columnComment
+   */
+  url: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath: string
+
+  /**
+   * 输出路径
+   */
+  outputPath: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath: string
+}
+
+export interface TrackSequenceForm {
+  /**
+   * ID
+   */
+  id?: string | number
+
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+        * 状态
+0:未开始
+1:进行中
+2:完成
+3:失败
+4:中断
+        */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  version?: number
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath?: string
+}
+
+export interface TrackSequenceQuery extends PageQuery {
+  /**
+   * 任务名称
+   */
+  name?: string
+
+  /**
+        * 状态
+0:未开始
+1:进行中
+2:完成
+3:失败
+4:中断
+        */
+  status?: string
+
+  /**
+   * 开始时间
+   */
+  startTime?: string
+
+  /**
+   * 结束时间
+   */
+  endTime?: string
+
+  /**
+   * 耗时
+   */
+  costSecond?: number
+
+  /**
+   * 日志
+   */
+  log?: string
+
+  /**
+   * 备注
+   */
+  remarks?: string
+
+  /**
+   * $column.columnComment
+   */
+  url?: string
+
+  /**
+   * $column.columnComment
+   */
+  inputOssId?: string | number
+
+  /**
+   * 输入路径
+   */
+  inputPath?: string
+
+  /**
+   * 输出路径
+   */
+  outputPath?: string
+
+  /**
+   * zip文件输出路径
+   */
+  zipFilePath?: string
+
+  /**
+   * 日期范围参数
+   */
+  params?: any
+}

+ 74 - 0
src/api/modules/demo/AlgorithmConfigTrack.ts

@@ -0,0 +1,74 @@
+import http from '@/api'
+import { AlgorithmConfigTrackVO, AlgorithmConfigTrackForm, AlgorithmConfigTrackQuery } from '@/api/interface/demo/AlgorithmConfigTrack'
+/**
+ * @name 查询算法配置列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listAlgorithmConfigTrackApi = (query: AlgorithmConfigTrackQuery) => {
+  return http.get<AlgorithmConfigTrackVO[]>('/demo/AlgorithmConfigTrack/list', query, { loading: true })
+}
+
+/**
+ * @name 查询算法配置详细
+ * @param id id
+ * @returns returns
+ */
+export const getAlgorithmConfigTrackApi = (id: string | number) => {
+  return http.get<AlgorithmConfigTrackVO>(`/demo/AlgorithmConfigTrack/${id}`)
+}
+
+/**
+ * @name 新增算法配置
+ * @param data data
+ * @returns returns
+ */
+export const addAlgorithmConfigTrackApi = (data: AlgorithmConfigTrackForm) => {
+  return http.post<any>('/demo/AlgorithmConfigTrack', data, { loading: false })
+}
+
+/**
+ * @name 修改算法配置
+ * @param data data
+ * @returns returns
+ */
+export const updateAlgorithmConfigTrackApi = (data: AlgorithmConfigTrackForm) => {
+  return http.put<any>('/demo/AlgorithmConfigTrack', data, { loading: false })
+}
+
+/**
+ * @name 删除算法配置
+ * @param id id
+ * @returns returns
+ */
+export const delAlgorithmConfigTrackApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/AlgorithmConfigTrack/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/AlgorithmConfigTrack/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importAlgorithmConfigTrackDataApi = (data: any) => {
+  return http.post('/demo/AlgorithmConfigTrack/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportAlgorithmConfigTrackApi = (data: any) => {
+  return http.downloadPost('/demo/AlgorithmConfigTrack/export', data)
+}
+
+export const enumAlgorithmConfigTrackApi = () => {
+  return http.get('/demo/AlgorithmConfigTrack/enums')
+}

+ 74 - 0
src/api/modules/demo/AlgorithmModelTrack.ts

@@ -0,0 +1,74 @@
+import http from '@/api'
+import { AlgorithmModelTrackVO, AlgorithmModelTrackForm, AlgorithmModelTrackQuery } from '@/api/interface/demo/AlgorithmModelTrack'
+/**
+ * @name 查询算法模型配置列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listAlgorithmModelTrackApi = (query: AlgorithmModelTrackQuery) => {
+  return http.get<AlgorithmModelTrackVO[]>('/demo/AlgorithmModelTrack/list', query, { loading: true })
+}
+
+/**
+ * @name 查询算法模型配置详细
+ * @param id id
+ * @returns returns
+ */
+export const getAlgorithmModelTrackApi = (id: string | number) => {
+  return http.get<AlgorithmModelTrackVO>(`/demo/AlgorithmModelTrack/${id}`)
+}
+
+/**
+ * @name 新增算法模型配置
+ * @param data data
+ * @returns returns
+ */
+export const addAlgorithmModelTrackApi = (data: AlgorithmModelTrackForm) => {
+  return http.post<any>('/demo/AlgorithmModelTrack', data, { loading: false })
+}
+
+/**
+ * @name 修改算法模型配置
+ * @param data data
+ * @returns returns
+ */
+export const updateAlgorithmModelTrackApi = (data: AlgorithmModelTrackForm) => {
+  return http.put<any>('/demo/AlgorithmModelTrack', data, { loading: false })
+}
+
+/**
+ * @name 删除算法模型配置
+ * @param id id
+ * @returns returns
+ */
+export const delAlgorithmModelTrackApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/AlgorithmModelTrack/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/AlgorithmModelTrack/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importAlgorithmModelTrackDataApi = (data: any) => {
+  return http.post('/demo/AlgorithmModelTrack/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportAlgorithmModelTrackApi = (data: any) => {
+  return http.downloadPost('/demo/AlgorithmModelTrack/export', data)
+}
+
+export const enumAlgorithmModelTrackApi = (): any => {
+  return http.get('/demo/AlgorithmModelTrack/enums')
+}

+ 86 - 0
src/api/modules/demo/DataSeq.ts

@@ -0,0 +1,86 @@
+import http from '@/api'
+import { DataSeqVO, DataSeqForm, DataSeqQuery } from '@/api/interface/demo/DataSeq'
+/**
+ * @name 查询数据管理列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listDataSeqApi = (query: DataSeqQuery) => {
+  return http.get<DataSeqVO[]>('/demo/DataSeq/list', query, { loading: true })
+}
+
+/**
+ * @name 查询数据管理详细
+ * @param id id
+ * @returns returns
+ */
+export const getDataSeqApi = (id: string | number) => {
+  return http.get<DataSeqVO>(`/demo/DataSeq/${id}`)
+}
+
+/**
+ * @name 新增数据管理
+ * @param data data
+ * @returns returns
+ */
+export const addDataSeqApi = (data: DataSeqForm) => {
+  return http.post<any>('/demo/DataSeq', data, { loading: false })
+}
+
+/**
+ * @name 修改数据管理
+ * @param data data
+ * @returns returns
+ */
+export const updateDataSeqApi = (data: DataSeqForm) => {
+  return http.put<any>('/demo/DataSeq', data, { loading: false })
+}
+
+/**
+ * @name 删除数据管理
+ * @param id id
+ * @returns returns
+ */
+export const delDataSeqApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/DataSeq/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/DataSeq/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importDataSeqDataApi = (data: any) => {
+  return http.post('/demo/DataSeq/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportDataSeqApi = (data: any) => {
+  return http.downloadPost('/demo/DataSeq/export', data)
+}
+
+/**
+ * @name 导入数据集
+ * @returns returns
+ */
+export const batchAdDataSeqApi = (data: any) => {
+  return http.post('/demo/DataSeq/batchAdd', data)
+}
+
+export const getAllImagesApi = (ossId: any) => {
+  return http.get('/demo/DataSeq/getAllImages/' + ossId)
+}
+
+export const getImagesApi = (inputOdssId: any, subsystem: any, ifInput: any, dir: any) => {
+  return http.get(`/demo/DataSeq/getImages/${inputOdssId}/${subsystem}/${ifInput}/${dir}`)
+}

+ 87 - 0
src/api/modules/demo/TargetDetection.ts

@@ -0,0 +1,87 @@
+import http from '@/api'
+import { TargetDetectionVO, TargetDetectionForm, TargetDetectionQuery } from '@/api/interface/demo/TargetDetection'
+
+/**
+ * @name 查询目标检测列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listTargetDetectionApi = (query: TargetDetectionQuery) => {
+  return http.get<TargetDetectionVO[]>('/demo/TargetDetection/list', query, { loading: true })
+}
+
+/**
+ * @name 查询目标检测详细
+ * @param id id
+ * @returns returns
+ */
+export const getTargetDetectionApi = (id: string | number) => {
+  return http.get<TargetDetectionVO>(`/demo/TargetDetection/${id}`)
+}
+
+/**
+ * @name 新增目标检测
+ * @param data data
+ * @returns returns
+ */
+export const addTargetDetectionApi = (data: TargetDetectionForm) => {
+  return http.post<any>('/demo/TargetDetection', data, { loading: false })
+}
+
+/**
+ * @name 修改目标检测
+ * @param data data
+ * @returns returns
+ */
+export const updateTargetDetectionApi = (data: TargetDetectionForm) => {
+  return http.put<any>('/demo/TargetDetection', data, { loading: false })
+}
+
+/**
+ * @name 删除目标检测
+ * @param id id
+ * @returns returns
+ */
+export const delTargetDetectionApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/TargetDetection/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/TargetDetection/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importTargetDetectionDataApi = (data: any) => {
+  return http.post('/demo/TargetDetection/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportTargetDetectionApi = (data: any) => {
+  return http.downloadPost('/demo/TargetDetection/export', data)
+}
+
+export const startTargetDetectionApi = (id: string | number) => {
+  return http.get<any>(`/demo/TargetDetection/start/${id}`)
+}
+
+export const stopTargetDetectionApi = (id: string | number) => {
+  return http.get('/demo/TargetDetection/stop/' + id)
+}
+
+/**
+ * @name 下载压缩包
+ * @returns returns
+ */
+export const dowloadTargetDetectionApi = (id: string | number): Promise<any> => {
+  return http.downloadGet('/demo/TargetDetection/zip/' + id)
+}

+ 86 - 0
src/api/modules/demo/toInfrared.ts

@@ -0,0 +1,86 @@
+import http from '@/api'
+import { ToInfraredVO, ToInfraredForm, ToInfraredQuery } from '@/api/interface/demo/toInfrared'
+/**
+ * @name 查询可见光转红外列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listToInfraredApi = (query: ToInfraredQuery) => {
+  return http.get<ToInfraredVO[]>('/demo/toInfrared/list', query, { loading: true })
+}
+
+/**
+ * @name 查询可见光转红外详细
+ * @param id id
+ * @returns returns
+ */
+export const getToInfraredApi = (id: string | number) => {
+  return http.get<ToInfraredVO>(`/demo/toInfrared/${id}`)
+}
+
+/**
+ * @name 新增可见光转红外
+ * @param data data
+ * @returns returns
+ */
+export const addToInfraredApi = (data: ToInfraredForm) => {
+  return http.post<any>('/demo/toInfrared', data, { loading: false })
+}
+
+/**
+ * @name 修改可见光转红外
+ * @param data data
+ * @returns returns
+ */
+export const updateToInfraredApi = (data: ToInfraredForm) => {
+  return http.put<any>('/demo/toInfrared', data, { loading: false })
+}
+
+/**
+ * @name 删除可见光转红外
+ * @param id id
+ * @returns returns
+ */
+export const delToInfraredApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/toInfrared/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/toInfrared/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importToInfraredDataApi = (data: any) => {
+  return http.post('/demo/toInfrared/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportToInfraredApi = (data: any) => {
+  return http.downloadPost('/demo/toInfrared/export', data)
+}
+
+export const startToInfraredApi = (id: string | number) => {
+  return http.get('/demo/toInfrared/start/' + id)
+}
+
+export const stopToInfraredApi = (id: string | number) => {
+  return http.get('/demo/toInfrared/stop/' + id)
+}
+
+/**
+ * @name 下载压缩包
+ * @returns returns
+ */
+export const dowloadToInfraredApi = (id: string | number): Promise<any> => {
+  return http.downloadGet('/demo/toInfrared/zip/' + id)
+}

+ 86 - 0
src/api/modules/demo/trackSequence.ts

@@ -0,0 +1,86 @@
+import http from '@/api'
+import { TrackSequenceVO, TrackSequenceForm, TrackSequenceQuery } from '@/api/interface/demo/trackSequence'
+/**
+ * @name 查询注视轨迹序列列表
+ * @param query 参数
+ * @returns 返回列表
+ */
+export const listTrackSequenceApi = (query: TrackSequenceQuery) => {
+  return http.get<TrackSequenceVO[]>('/demo/trackSequence/list', query, { loading: true })
+}
+
+/**
+ * @name 查询注视轨迹序列详细
+ * @param id id
+ * @returns returns
+ */
+export const getTrackSequenceApi = (id: string | number) => {
+  return http.get<TrackSequenceVO>(`/demo/trackSequence/${id}`)
+}
+
+/**
+ * @name 新增注视轨迹序列
+ * @param data data
+ * @returns returns
+ */
+export const addTrackSequenceApi = (data: TrackSequenceForm) => {
+  return http.post<any>('/demo/trackSequence', data, { loading: false })
+}
+
+/**
+ * @name 修改注视轨迹序列
+ * @param data data
+ * @returns returns
+ */
+export const updateTrackSequenceApi = (data: TrackSequenceForm) => {
+  return http.put<any>('/demo/trackSequence', data, { loading: false })
+}
+
+/**
+ * @name 删除注视轨迹序列
+ * @param id id
+ * @returns returns
+ */
+export const delTrackSequenceApi = (id: string | number | Array<string | number>) => {
+  return http.delete<any>(`/demo/trackSequence/${id}`)
+}
+
+/**
+ * @name 下载模板
+ * @returns returns
+ */
+export const importTemplateApi = () => {
+  return http.downloadPost('/demo/trackSequence/importTemplate', {})
+}
+
+/**
+ * @name 导入数据
+ * @returns returns
+ */
+export const importTrackSequenceDataApi = (data: any) => {
+  return http.post('/demo/trackSequence/importData', data)
+}
+
+/**
+ * @name 导出数据
+ * @returns returns
+ */
+export const exportTrackSequenceApi = (data: any) => {
+  return http.downloadPost('/demo/trackSequence/export', data)
+}
+
+export const startTrackSequenceApi = (id: string | number) => {
+  return http.get('/demo/trackSequence/start/' + id)
+}
+
+export const stopTrackSequenceApi = (id: string | number) => {
+  return http.get('/demo/trackSequence/stop/' + id)
+}
+
+/**
+ * @name 下载压缩包
+ * @returns returns
+ */
+export const dowloadTrackSequenceApi = (id: string | number): Promise<any> => {
+  return http.downloadGet('/demo/trackSequence/zip/' + id)
+}

+ 10 - 6
src/components/FormDialog/index.vue

@@ -27,11 +27,13 @@ import { ref, ComputedRef, computed, reactive } from 'vue'
 import ProFrom from '@/components/ProForm/index.vue'
 import { ElMessage } from 'element-plus'
 import FileUpload from '@/components/Upload/File.vue'
+
 // import mittBus from '@/utils/mittBus'
 
 interface EmitEvent {
   (e: 'update'): void
 }
+
 const emits = defineEmits<EmitEvent>()
 
 const videoUploadRef = ref<InstanceType<typeof FileUpload> | null>(null)
@@ -70,7 +72,7 @@ const _options: ComputedRef<ProForm.FormOptions> = computed(() => {
   return Object.assign(form, parameter.value.formOptions)
 })
 
-const modelAddr = ref('')
+const modelAddr = ref(null)
 const setModelAddr = res => {
   //console.log("setModelAddr res:")
   console.log(res)
@@ -89,11 +91,13 @@ const handleSubmit = () => {
   if (!formEl) return
   formEl.validate(valid => {
     if (valid) {
-      const _params = { ...formModel, ...parameter.value.model }
-      if (!_params.algorithmId) {
-        _params.algorithmId = algorithmModelId.value
+      let data = {}
+      if (algorithmModelId.value) {
+        data = { ...formModel, ...parameter.value.model, algorithmId: algorithmModelId.value }
+      } else {
+        data = { ...formModel, ...parameter.value.model }
       }
-      parameter.value.api!(_params).then(res => {
+      parameter.value.api!(data).then(res => {
         if (res.code == 200) {
           proFormRef.value?.resetForm(formEl)
           ElMessage.success('操作成功')
@@ -134,7 +138,7 @@ const handleCancel = () => {
 let algorithmModelId = ref(0)
 
 // 接收父组件参数
-const openDialog = (params: FormParameterProps, algoModelId) => {
+const openDialog = (params: FormParameterProps, algoModelId = null) => {
   algorithmModelId.value = algoModelId
   parameter.value = { ...parameter.value, ...params }
   _options.value.disabled = !parameter.value.isEdit

+ 1 - 3
src/components/Upload/File.vue

@@ -187,12 +187,10 @@ const uploadSuccess = (response: any | undefined, uploadFile: UploadFile) => {
 // 上传结束处理
 const uploadedSuccessfully = () => {
   if (number.value > 0 && uploadList.value.length === number.value) {
-    console.log(_fileList.value)
     _fileList.value = _fileList.value.filter(f => f.url !== undefined).concat(uploadList.value)
-    console.log(_fileList.value)
     uploadList.value = []
     number.value = 0
-    emit('update:modelValue', _fileList.value.length > 0 ? _fileList.value[0].ossId : '')
+    emit('update:modelValue', listToString(_fileList.value))
     tryHideFullScreenLoading()
   }
   // 监听表单验证

+ 34 - 0
src/utils/status.ts

@@ -0,0 +1,34 @@
+const statusEnums: EnumProps[] = [
+  {
+    label: '未开始',
+    value: '0',
+    disabled: false,
+    tagType: 'default'
+  },
+  {
+    label: '进行中',
+    value: '1',
+    disabled: false,
+    tagType: 'primary'
+  },
+  {
+    label: '完成',
+    value: '2',
+    disabled: false,
+    tagType: 'success'
+  },
+  {
+    label: '失败',
+    value: '3',
+    disabled: false,
+    tagType: 'danger'
+  },
+  {
+    label: '已中断',
+    value: '4',
+    disabled: false,
+    tagType: 'default'
+  }
+]
+
+export default statusEnums

+ 269 - 0
src/views/demo/AlgorithmConfigTrack/index.vue

@@ -0,0 +1,269 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listAlgorithmConfigTrackApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:AlgorithmConfigTrack:add']" icon="CirclePlus" @click="openDialog(1, '算法任务配置新增')">
+          新增
+        </el-button>
+        <el-button type="primary" v-auth="['demo:AlgorithmConfigTrack:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
+        <el-button type="primary" v-auth="['demo:AlgorithmConfigTrack:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>
+        <el-button
+          type="danger"
+          v-auth="['demo:AlgorithmConfigTrack:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-auth="['demo:AlgorithmConfigTrack:query']" @click="openDialog(3, '算法任务配置查看', scope.row)">
+          查看
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          icon="EditPen"
+          v-auth="['demo:AlgorithmConfigTrack:edit']"
+          @click="openDialog(2, '算法任务配置编辑', scope.row)"
+        >
+          编辑
+        </el-button>
+        <el-button type="primary" link icon="Delete" v-auth="['demo:AlgorithmConfigTrack:remove']" @click="deleteAlgorithmConfigTrack(scope.row)">
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="AlgorithmConfigTrack">
+import { ref, reactive } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listAlgorithmConfigTrackApi,
+  delAlgorithmConfigTrackApi,
+  addAlgorithmConfigTrackApi,
+  updateAlgorithmConfigTrackApi,
+  importTemplateApi,
+  importAlgorithmConfigTrackDataApi,
+  exportAlgorithmConfigTrackApi,
+  getAlgorithmConfigTrackApi
+} from '@/api/modules/demo/AlgorithmConfigTrack'
+import { enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除算法任务配置信息
+const deleteAlgorithmConfigTrack = async (params: any) => {
+  await useHandleData(delAlgorithmConfigTrackApi, params.id, '删除【' + params.id + '】算法任务配置')
+  proTable.value?.getTableList()
+}
+
+// 批量删除算法任务配置信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delAlgorithmConfigTrackApi, ids, '删除所选算法任务配置信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出算法任务配置列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出算法任务配置数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportAlgorithmConfigTrackApi, '算法任务配置列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加算法任务配置
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '算法任务配置',
+    tempApi: importTemplateApi,
+    importApi: importAlgorithmConfigTrackDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getAlgorithmConfigTrackApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addAlgorithmConfigTrackApi : updateAlgorithmConfigTrackApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: '主键ID' },
+  {
+    prop: 'type',
+    label: '类型',
+    tag: true,
+    enum: enumsAlgorithmType,
+    search: {
+      el: 'select'
+    },
+    width: 120
+  },
+  //   {
+  //     prop: 'parentId',
+  //     label: '父id',
+  //     search: {
+  //       el: 'input'
+  //     },
+  //     width: 120
+  //   },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'algorithmName',
+    label: '算法名称',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'algorithmAddress',
+    label: '算法地址',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'parameterConfig',
+    label: '参数配置',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    }
+  },
+  //   {
+  //     prop: 'system',
+  //     label: '系统',
+  //     search: {
+  //       el: 'input'
+  //     }
+  //   },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '类型',
+      prop: 'type',
+      rules: [{ required: true, message: '算法类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        enum: enumsAlgorithmType,
+        placeholder: '请选择算法类型'
+      }
+    },
+    // {
+    //   label: '父id',
+    //   prop: 'parentId',
+    //   rules: [{ required: true, message: '父id不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入父id'
+    //   }
+    // },
+    {
+      label: '分系统',
+      prop: 'subsystem',
+      rules: [{ required: true, message: '分系统不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        enum: enumsSubSystem,
+        placeholder: '请选择分系统'
+      }
+    },
+    {
+      label: '算法名称',
+      prop: 'algorithmName',
+      rules: [{ required: true, message: '算法名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入算法名称'
+      }
+    },
+    {
+      label: '算法地址',
+      prop: 'algorithmAddress',
+      rules: [{ required: true, message: '算法地址不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入算法地址'
+      }
+    },
+    {
+      label: '参数配置',
+      prop: 'parameterConfig',
+      rules: [{ required: true, message: '参数配置不能为空', trigger: 'blur' }],
+      compOptions: {
+        type: 'textarea',
+        clearable: true,
+        placeholder: '请输入内容'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+    // {
+    //   label: '系统',
+    //   prop: 'system',
+    //   rules: [{ required: true, message: '系统不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入系统'
+    //   }
+    // }
+  ]
+}
+</script>

+ 315 - 0
src/views/demo/AlgorithmModelTrack/index.vue

@@ -0,0 +1,315 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listAlgorithmModelTrackApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:AlgorithmModelTrack:add']" icon="CirclePlus" @click="openDialog(1, '算法模型配置新增')">
+          新增
+        </el-button>
+        <!-- <el-button type="primary" v-auth="['demo:AlgorithmModelTrack:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
+        <el-button type="primary" v-auth="['demo:AlgorithmModelTrack:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
+        <el-button
+          type="danger"
+          v-auth="['demo:AlgorithmModelTrack:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-auth="['demo:AlgorithmModelTrack:query']" @click="openDialog(3, '算法模型配置查看', scope.row)">
+          查看
+        </el-button>
+        <!-- <el-button
+          type="primary"
+          link
+          icon="EditPen"
+          v-auth="['demo:AlgorithmModelTrack:edit']"
+          @click="openDialog(2, '算法模型配置编辑', scope.row)"
+        >
+          编辑
+        </el-button> -->
+        <el-button type="primary" link icon="Delete" v-auth="['demo:AlgorithmModelTrack:remove']" @click="deleteAlgorithmModelTrack(scope.row)">
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="AlgorithmModelTrack">
+import { ref, reactive, onMounted } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listAlgorithmModelTrackApi,
+  delAlgorithmModelTrackApi,
+  addAlgorithmModelTrackApi,
+  updateAlgorithmModelTrackApi,
+  importTemplateApi,
+  importAlgorithmModelTrackDataApi,
+  exportAlgorithmModelTrackApi,
+  getAlgorithmModelTrackApi
+} from '@/api/modules/demo/AlgorithmModelTrack'
+
+import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import { AlgorithmType, SubSystem, enumsModelStatus, enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除算法模型配置信息
+const deleteAlgorithmModelTrack = async (params: any) => {
+  await useHandleData(delAlgorithmModelTrackApi, params.id, '删除【' + params.id + '】算法模型配置')
+  proTable.value?.getTableList()
+}
+
+// 批量删除算法模型配置信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delAlgorithmModelTrackApi, ids, '删除所选算法模型配置信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出算法模型配置列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出算法模型配置数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportAlgorithmModelTrackApi, '算法模型配置列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加算法模型配置
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '算法模型配置',
+    tempApi: importTemplateApi,
+    importApi: importAlgorithmModelTrackDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getAlgorithmModelTrackApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addAlgorithmModelTrackApi : updateAlgorithmModelTrackApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: 'ID' },
+  {
+    prop: 'modelName',
+    label: '模型名称',
+    search: {
+      el: 'input'
+    },
+    minWidth: 150
+  },
+  {
+    prop: 'algorithmType',
+    label: '算法',
+    search: {
+      el: 'input'
+    },
+    minWidth: 200
+  },
+  {
+    prop: 'type',
+    label: '类型',
+    tag: true,
+    enum: enumsAlgorithmType,
+    search: {
+      el: 'select'
+    },
+    width: 120
+  },
+  //   {
+  //     prop: 'parentId',
+  //     label: '父id',
+  //     search: {
+  //       el: 'input'
+  //     },
+  //     width: 120
+  //   },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'modelStatus',
+    label: '模型状态',
+    tag: true,
+    enum: enumsModelStatus,
+    search: {
+      el: 'select'
+    },
+    width: 120
+  },
+  //   {
+  //     prop: 'sampleNumber',
+  //     label: '训练样本数',
+  //     search: {
+  //       el: 'input'
+  //     },
+  //     width: 120
+  //   },
+  //   {
+  //     prop: 'cycleEpoch',
+  //     label: '训练循环次数',
+  //     search: {
+  //       el: 'input'
+  //     },
+  //     width: 120
+  //   },
+  {
+    prop: 'modelAddress',
+    label: '模型',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    },
+    width: 200
+  },
+  //   {
+  //     prop: 'system',
+  //     label: '系统',
+  //     search: {
+  //       el: 'input'
+  //     },
+  //     width: 120
+  //   },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+
+const enumsAlgorithmConfigTrack = ref<any>([])
+
+onMounted(async () => {
+  const result: any = await enumAlgorithmConfigTrackApi()
+  // console.log(result)
+  // console.log(result['data'])
+  for (let item of result['data']) {
+    // console.log(item)
+    // console.log(item['type'])
+    // console.log(item['subsystem'])
+    // console.log(AlgorithmType[item['type']])
+    // console.log(SubSystem[item['subsystem']])
+    // console.log(AlgorithmType)
+    // console.log(SubSystem)
+    // console.log('-------------------')
+    item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+  }
+
+  enumsAlgorithmConfigTrack.value = result['data']
+  return result['data']
+})
+
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '算法',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请输入算法',
+        enum: enumsAlgorithmConfigTrack
+      }
+    },
+    {
+      label: '模型名称',
+      prop: 'modelName',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型',
+      prop: 'modelInputOssId',
+      rules: [{ required: false, message: '模型文件不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['pt', 'zip'],
+        placeholder: '请上传模型文件'
+      }
+    },
+    // {
+    //   label: '训练样本数',
+    //   prop: 'sampleNumber',
+    //   rules: [{ required: true, message: '训练样本数不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入训练样本数'
+    //   }
+    // },
+    // {
+    //   label: '训练循环次数',
+    //   prop: 'cycleEpoch',
+    //   rules: [{ required: true, message: '训练循环次数不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入训练循环次数'
+    //   }
+    // },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+    // {
+    //   label: '系统',
+    //   prop: 'system',
+    //   rules: [{ required: true, message: '系统不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入系统'
+    //   }
+    // }
+  ]
+}
+</script>

+ 342 - 0
src/views/demo/DataSeq/index.vue

@@ -0,0 +1,342 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listDataSeqApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:DataSeq:add']" icon="CirclePlus" @click="openDialog(1, '数据集新增')"> 新增 </el-button>
+        <!-- <el-button type="primary" v-auth="['demo:DataSeq:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
+        <el-button type="primary" v-auth="['demo:DataSeq:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
+        <el-button
+          type="danger"
+          v-auth="['demo:DataSeq:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-auth="['demo:DataSeq:query']" @click="openDialog(3, '数据管理查看', scope.row)">
+          查看
+        </el-button>
+        <el-button type="primary" link icon="View" v-auth="['demo:DataSeq:query']" @click="preview(scope.row)"> 预览</el-button>
+        <!-- <el-button type="primary" link icon="EditPen" v-auth="['demo:DataSeq:edit']" @click="openDialog(2, '数据管理编辑', scope.row)">
+          编辑
+        </el-button> -->
+        <el-button type="primary" link icon="Delete" v-auth="['demo:DataSeq:remove']" @click="deleteDataSeq(scope.row)"> 删除 </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <!-- <ImportExcel ref="dialogRef" /> -->
+    <PreviewImages :visible="dialogVisible" :urls="imageUrls" @close="dialogVisible = false" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="DataSeq">
+import { ref, reactive } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listDataSeqApi,
+  delDataSeqApi,
+  addDataSeqApi,
+  updateDataSeqApi,
+  importTemplateApi,
+  importDataSeqDataApi,
+  exportDataSeqApi,
+  getDataSeqApi,
+  getAllImagesApi
+} from '@/api/modules/demo/DataSeq'
+import { enumsSubSystem } from '../utils'
+import PreviewImages from '@/views/demo/components/PreviewImages.vue'
+const dialogVisible = ref(false)
+const imageUrls = ref([])
+const preview = async row => {
+  console.log('showImages')
+  const data: any = await getAllImagesApi(row.inputOssId)
+  imageUrls.value = data.data
+  dialogVisible.value = true
+}
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除数据管理信息
+const deleteDataSeq = async (params: any) => {
+  await useHandleData(delDataSeqApi, params.id, '删除【' + params.id + '】数据管理')
+  proTable.value?.getTableList()
+}
+
+// 批量删除数据管理信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delDataSeqApi, ids, '删除所选数据管理信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出数据管理列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出数据管理数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportDataSeqApi, '数据管理列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加数据管理
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '数据管理',
+    tempApi: importTemplateApi,
+    importApi: importDataSeqDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getDataSeqApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addDataSeqApi : updateDataSeqApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: 'id' },
+  {
+    prop: 'name',
+    label: '名称',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    search: {
+      el: 'select'
+    },
+    width: 120
+  },
+  {
+    prop: 'objectType',
+    label: '目标类型',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'objectSubtype',
+    label: '目标子类型',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'batchNum',
+    label: '批次号',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'scene',
+    label: '场景',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'dataSource',
+    label: '数据源',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'gatherSpot',
+    label: '采集地点',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'filePath',
+    label: '文件路径',
+    search: {
+      el: 'input'
+    }
+  },
+  {
+    prop: 'unzipPath',
+    label: '解压路径',
+    search: {
+      el: 'input'
+    }
+  },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '名称',
+      prop: 'name',
+      rules: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入名称'
+      }
+    },
+    {
+      label: '分系统',
+      prop: 'subsystem',
+      rules: [{ required: true, message: '分系统不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        enum: enumsSubSystem,
+        placeholder: '请选择分系统'
+      }
+    },
+    {
+      label: '批次号',
+      prop: 'batchNum',
+      rules: [{ required: true, message: '批次号不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入批次号'
+      }
+    },
+    {
+      label: '上传文件',
+      prop: 'inputOssId',
+      rules: [{ required: true, message: '数据集文件不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集文件'
+      }
+    },
+    // {
+    //   label: '文件类型',
+    //   prop: 'fileType',
+    //   rules: [{ required: true, message: '文件类型不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入文件类型'
+    //   }
+    // },
+    {
+      label: '目标类型',
+      prop: 'objectType',
+      rules: [{ required: false, message: '目标类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入目标类型'
+      }
+    },
+    {
+      label: '目标子类型',
+      prop: 'objectSubtype',
+      rules: [{ required: false, message: '目标子类型不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入目标子类型'
+      }
+    },
+    {
+      label: '场景',
+      prop: 'scene',
+      rules: [{ required: false, message: '场景不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入场景'
+      }
+    },
+    {
+      label: '数据源',
+      prop: 'dataSource',
+      rules: [{ required: false, message: '数据源不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入数据源'
+      }
+    },
+    {
+      label: '采集时间',
+      prop: 'gatherTime',
+      rules: [{ required: false, message: '采集时间不能为空', trigger: 'change' }],
+      compOptions: {
+        elTagName: 'date-picker',
+        type: 'date',
+        placeholder: '请选择采集时间'
+      }
+    },
+    {
+      label: '采集地点',
+      prop: 'gatherSpot',
+      rules: [{ required: false, message: '采集地点不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入采集地点'
+      }
+    },
+    // {
+    //   label: '图片url',
+    //   prop: 'url',
+    //   rules: [{ required: true, message: '图片url不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     placeholder: '请输入图片url'
+    //   }
+    // },
+    // {
+    //   label: '日志',
+    //   prop: 'log',
+    //   rules: [{ required: true, message: '日志不能为空', trigger: 'blur' }],
+    //   compOptions: {
+    //     type: 'textarea',
+    //     clearable: true,
+    //     placeholder: '请输入内容'
+    //   }
+    // },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 464 - 0
src/views/demo/TargetDetection/index.vue

@@ -0,0 +1,464 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listTargetDetectionApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:TargetDetection:add']" icon="CirclePlus" @click="openDialog(1, '目标检测新增')"> 新增 </el-button>
+        <!--        <el-button type="primary" v-auth="['demo:TargetDetection:import']" icon="Upload" plain @click="batchAdd">-->
+        <!--          导入-->
+        <!--        </el-button>-->
+        <!--        <el-button type="primary" v-auth="['demo:TargetDetection:export']" icon="Download" plain @click="downloadFile">-->
+        <!--          导出-->
+        <!--        </el-button>-->
+        <el-button
+          type="danger"
+          v-auth="['demo:TargetDetection:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
+          <!--@click="openStartDialog(scope.row)"  -->
+          模型
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:trackSequence:start']"
+          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
+          @click="startTargetDetection(scope.row)"
+        >
+          开始
+        </el-button>
+        <el-popconfirm title="确定终止此任务吗?" v-if="scope.row.status == '1'" @confirm="stopTargetDetect(scope.row)">
+          <template #reference>
+            <el-button type="primary" link icon="Delete">终止</el-button>
+          </template>
+        </el-popconfirm>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:trackSequence:download']"
+          v-if="scope.row.status == '2'"
+          @click="dowloadTargetDetection(scope.row)"
+        >
+          下载
+        </el-button>
+        <!--        <el-button-->
+        <!--          type="primary"-->
+        <!--          link-->
+        <!--          icon="View"-->
+        <!--          v-auth="['demo:TargetDetection:query']"-->
+        <!--          @click="openDialog(3, '目标检测查看', scope.row)"-->
+        <!--        >-->
+        <!--          查看-->
+        <!--        </el-button>-->
+        <!--        <el-button-->
+        <!--          type="primary"-->
+        <!--          link-->
+        <!--          icon="EditPen"-->
+        <!--          v-auth="['demo:TargetDetection:edit']"-->
+        <!--          @click="openDialog(2, '目标检测编辑', scope.row)"-->
+        <!--        >-->
+        <!--          编辑-->
+        <!--        </el-button>-->
+        <el-button type="primary" link icon="Delete" v-auth="['demo:TargetDetection:remove']" @click="deleteTargetDetection(scope.row)">
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="TargetDetection">
+import { ref, reactive, onMounted } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listTargetDetectionApi,
+  delTargetDetectionApi,
+  addTargetDetectionApi,
+  updateTargetDetectionApi,
+  importTemplateApi,
+  importTargetDetectionDataApi,
+  exportTargetDetectionApi,
+  getTargetDetectionApi,
+  startTargetDetectionApi,
+  dowloadTargetDetectionApi,
+  stopTargetDetectionApi
+} from '@/api/modules/demo/TargetDetection'
+
+import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
+
+import { enumAlgorithmModelTrackApi, getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import { updateTrackSequenceApi } from '@/api/modules/demo/trackSequence'
+
+const stopTargetDetect = async (params: any) => {
+  const res: any = await stopTargetDetectionApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('终止任务成功!')
+  } else {
+    ElMessage.error('终止任务失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+
+import statusEnums from '@/utils/status'
+import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
+
+const dowloadTargetDetection = async (params: any) => {
+  await useDownload(dowloadTargetDetectionApi, params.name, params.id, true, '.zip')
+}
+
+const startTargetDetection = async (params: any) => {
+  const res: any = await startTargetDetectionApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('任务已开始,请等待完成!')
+  } else {
+    ElMessage.error('任务开始失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+
+const enumsAlgorithmConfigTrack = ref<any>([])
+onMounted(async () => {
+  const result = await enumAlgorithmConfigTrackApi()
+  // console.log(result)
+  // console.log(result['data'])
+  enumsAlgorithmConfigTrack.value = result['data']
+  return result['data']
+})
+
+const openModelDialog = async row => {
+  const algorithmModelId = row.algorithmModelId
+  const result: any = await getAlgorithmModelTrackApi(algorithmModelId)
+
+  // console.log(result.data)
+
+  setItemsOptionsModel()
+  const params = {
+    title: '模型',
+    width: 580,
+    isEdit: false,
+    itemsOptions: itemsOptions,
+    model: result.data,
+    api: updateTrackSequenceApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除目标检测信息
+const deleteTargetDetection = async (params: any) => {
+  await useHandleData(delTargetDetectionApi, params.id, '删除【' + params.id + '】目标检测')
+  proTable.value?.getTableList()
+}
+
+// 批量删除目标检测信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delTargetDetectionApi, ids, '删除所选目标检测信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出目标检测列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出目标检测数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportTargetDetectionApi, '目标检测列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加目标检测
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '目标检测',
+    tempApi: importTemplateApi,
+    importApi: importTargetDetectionDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getTargetDetectionApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addTargetDetectionApi : updateTargetDetectionApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: '主键ID', width: 180 },
+  {
+    prop: 'name',
+    label: '任务名称',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
+  {
+    prop: 'status',
+    label: '任务状态',
+    search: {
+      el: 'select'
+    },
+    tag: true,
+    enum: statusEnums,
+    width: 150
+  },
+  {
+    prop: 'type',
+    label: '类型',
+    tag: true,
+    enum: enumsAlgorithmType,
+    width: 120
+  },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    width: 200
+  },
+  {
+    prop: 'algorithmName',
+    label: '算法名称',
+    width: 200
+  },
+  {
+    prop: 'modelName',
+    label: '模型名称',
+    width: 200
+  },
+  // {
+  //   prop: 'algorithmModelId',
+  //   label: '模型',
+  //   search: {
+  //     el: 'input'
+  //   },
+  //   width: 150
+  // },
+  {
+    prop: 'startTime',
+    label: '开始时间',
+    width: 180
+  },
+  {
+    prop: 'endTime',
+    label: '结束时间',
+    width: 180
+  },
+  {
+    prop: 'costSecond',
+    label: '耗时',
+    width: 120
+  },
+  {
+    prop: 'log',
+    label: '日志',
+    width: 120
+  },
+  {
+    prop: 'outputPath',
+    label: '输出路径',
+    width: 120
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+
+const getImageDataList = ref<any>([])
+onMounted(async () => {
+  const qyery = {
+    subsystem: SubSystem__['目标检测'],
+    pageNum: 1,
+    pageSize: 25
+  }
+  const result: any = await listDataSeqApi(qyery)
+  const data = result['data']['list']
+  for (const item of data) {
+    getImageDataList.value.push({
+      value: item['inputOssId'],
+      label: item['name']
+    })
+  }
+})
+
+const enumsAlgorithmModelTrack = ref<any>([])
+
+onMounted(async () => {
+  const result: any = await enumAlgorithmModelTrackApi()
+  // console.log(result.data);
+  enumsAlgorithmModelTrack.value = []
+
+  for (const item of result.data) {
+    if (SubSystem[item['subsystem']] === '目标检测') {
+      item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
+      enumsAlgorithmModelTrack.value.push(item)
+    }
+  }
+})
+
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传数据集',
+        enum: getImageDataList,
+        clearable: true
+      }
+    },
+    {
+      label: '上传数据集',
+      prop: 'inputOssId',
+      rules: [{ required: true, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集'
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModelId',
+      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: enumsAlgorithmModelTrack
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const setItemsOptionsModel = () => {
+  itemsOptions = [
+    {
+      label: '算法ID',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        placeholder: '请输入算法'
+      }
+    },
+    {
+      label: '算法类型',
+      prop: 'algorithmType',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请输入算法',
+        enum: enumsAlgorithmConfigTrack
+      }
+    },
+    {
+      label: '算法参数',
+      prop: 'parameterConfig',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型ID',
+      prop: 'id',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型名称',
+      prop: 'modelName',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型保存路径',
+      prop: 'modelAddress',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+</script>

+ 137 - 0
src/views/demo/components/PreviewImages.vue

@@ -0,0 +1,137 @@
+<!--
+# @Date: 2024-10-11 14:37:11
+# @Author: WANGKANG
+# @Blog:
+# @Email:
+# @Filepath: src\views\demo\components\PreviewImages.vue
+# @Description: PreviewImages.vue
+# Copyright 2024 WANGKANG, All Rights Reserved.
+-->
+
+<template>
+  <el-dialog
+    v-model="dialogVisible"
+    :title="'预览 - 共' + currentImageUrls.length + '张 当前第' + (imageIdx + 1) + '张'"
+    width="80%"
+    @open="handleOpen"
+    :before-close="handleClose"
+  >
+    <el-form :inline="true">
+      <el-form-item label="帧率">
+        <el-select v-model="imageFps" placeholder="选择帧率" style="width: 200px" @change="changeFps">
+          <el-option label="0" value="0"></el-option>
+          <el-option label="5" value="5"></el-option>
+          <el-option label="15" value="15"></el-option>
+          <el-option label="30" value="30"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="跳转至">
+        <el-input v-model="newImageIdx" type="number" style="width: 100px" />
+        <el-button type="primary" @click="confirmNewImageIdx" style="margin-left: 10px">确认</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="image-dialog">
+      <el-image :src="currentImageUrls[imageIdx]" style="width: 40%"></el-image>
+    </div>
+    <div class="image-dialog-btn" v-if="imageFps == 0">
+      <el-button type="primary" @click="pre_picture" :disabled="imageIdx <= 0">上一个</el-button>
+      <el-button type="primary" @click="next_picture" :disabled="imageIdx >= currentImageUrls.length - 1">下一个</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ElMessageBox } from 'element-plus'
+import { ref, watch } from 'vue'
+
+const props = defineProps({
+  visible: {
+    type: Boolean, //接受的数据类型
+    default: false //接受默认数据
+  },
+  urls: {
+    type: Array,
+    default: () => []
+  }
+})
+
+watch(
+  () => props.visible,
+  val => {
+    dialogVisible.value = val
+  }
+)
+
+const handleOpen = () => {
+  currentImageUrls.value = props.urls
+  imageIdx.value = 0
+  imageFps.value = 0
+}
+
+const dialogVisible = ref(false)
+const imageFps = ref(0)
+const intervalChangeFps: any = ref()
+const imageIdx = ref(0)
+const currentImageUrls = ref<any[]>([])
+const newImageIdx = ref()
+
+const handleClose = (done: () => void) => {
+  console.log('handleClose')
+  if (intervalChangeFps.value) {
+    clearInterval(intervalChangeFps.value)
+  }
+  done()
+}
+
+const confirmNewImageIdx = () => {
+  const val = parseInt(newImageIdx.value)
+  if (val > 0 && val <= currentImageUrls.value.length) {
+    imageIdx.value = val - 1
+  } else {
+    ElMessageBox.alert('跳转索引有误,请检查!')
+  }
+}
+
+const changeFps = () => {
+  console.log('changeFps')
+  if (intervalChangeFps.value) {
+    clearInterval(intervalChangeFps.value)
+  }
+
+  if (imageFps.value == 0) {
+    return
+  }
+
+  intervalChangeFps.value = setInterval(() => {
+    next_picture()
+  }, 1000 / imageFps.value)
+}
+
+const next_picture = () => {
+  if (imageIdx.value < currentImageUrls.value.length - 1) {
+    imageIdx.value += 1
+  }
+}
+
+const pre_picture = () => {
+  if (imageIdx.value > 0) {
+    imageIdx.value -= 1
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.image-dialog {
+  display: flex;
+  justify-content: center;
+  .el-image {
+    margin-right: 20px;
+    margin-bottom: 20px;
+  }
+}
+.image-dialog-btn {
+  display: flex;
+  justify-content: center;
+  margin-top: 20px;
+}
+</style>

+ 525 - 0
src/views/demo/toInfrared/index.vue

@@ -0,0 +1,525 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listToInfraredApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:toInfrared:add']" icon="CirclePlus" @click="openDialog(1, '可见光转红外新增')"> 新增 </el-button>
+        <!-- <el-button type="primary" v-auth="['demo:toInfrared:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
+        <el-button type="primary" v-auth="['demo:toInfrared:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
+        <el-button
+          type="danger"
+          v-auth="['demo:toInfrared:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
+          <!--@click="openStartDialog(scope.row)"  -->
+          详情
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:ToInfrared:start']"
+          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
+          @click="startToInfrared(scope.row)"
+        >
+          <!--@click="openStartDialog(scope.row)"  -->
+          开始
+        </el-button>
+        <el-popconfirm title="确定终止此任务吗?" @confirm="stopToInfrared(scope.row)" v-if="scope.row.status == '1'">
+          <template #reference>
+            <el-button type="primary" link icon="Delete"> 终止</el-button>
+          </template>
+        </el-popconfirm>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:DataSeq:query']"
+          v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['预测/推理']"
+          @click="preview(scope.row)"
+        >
+          预览
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:ToInfrared:download']"
+          v-if="scope.row.status == '2'"
+          @click="dowloadToInfrared(scope.row)"
+        >
+          下载
+        </el-button>
+        <!-- <el-button type="primary" link icon="View" v-auth="['demo:toInfrared:query']" @click="openDialog(3, '查看', scope.row)"> 查看 </el-button> -->
+        <!-- <el-button type="primary" link icon="EditPen"v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button> -->
+        <el-button
+          type="primary"
+          link
+          icon="Delete"
+          v-auth="['demo:toInfrared:remove']"
+          @click="deleteToInfrared(scope.row)"
+          :disabled="scope.row.status == '1'"
+        >
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+    <PreviewImages :visible="dialogVisible" :urls="imageUrls" @close="dialogVisible = false" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="ToInfrared">
+import { ref, reactive, onMounted } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listToInfraredApi,
+  delToInfraredApi,
+  addToInfraredApi,
+  updateToInfraredApi,
+  importTemplateApi,
+  importToInfraredDataApi,
+  exportToInfraredApi,
+  startToInfraredApi,
+  stopToInfraredApi,
+  dowloadToInfraredApi,
+  getToInfraredApi
+} from '@/api/modules/demo/toInfrared'
+
+import { getImagesApi, listDataSeqApi } from '@/api/modules/demo/DataSeq'
+
+import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+import statusEnums from '@/utils/status'
+import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem, AlgorithmType2 } from '@/views/demo/utils'
+import PreviewImages from '@/views/demo/components/PreviewImages.vue'
+import { Row } from 'element-plus/es/components/table-v2/src/components'
+
+const dialogVisible = ref(false)
+const imageUrls = ref([])
+const preview = async row => {
+  console.log('showImages:', row.inputOssId)
+  const data: any = await getImagesApi(row.inputOssId, '_to_infrared', false, 'predict')
+  imageUrls.value = data.data
+  dialogVisible.value = true
+}
+
+const openModelDialog = async row => {
+  const algorithmModelId = row.algorithmModelId
+  const result: any = await getAlgorithmModelTrackApi(algorithmModelId)
+
+  // console.log(result.data)
+  setItemsOptionsModel()
+  const params = {
+    title: '模型',
+    width: 580,
+    isEdit: false,
+    itemsOptions: itemsOptions,
+    model: result.data,
+    api: updateToInfraredApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+const startToInfrared = async (params: any) => {
+  const res: any = await startToInfraredApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('任务已开始,请等待完成!')
+  } else {
+    ElMessage.error('任务开始失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+
+const stopToInfrared = async (params: any) => {
+  const res: any = await stopToInfraredApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('终止任务成功!')
+  } else {
+    ElMessage.error('终止任务失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+const dowloadToInfrared = async (params: any) => {
+  if (params.type == AlgorithmType2['训练']) {
+    await useDownload(dowloadToInfraredApi, params.name, params.id, true, '.pt')
+  } else if (params.type == AlgorithmType2['预测/推理']) {
+    await useDownload(dowloadToInfraredApi, params.name, params.id, true, '.zip')
+  }
+}
+
+const openStartDialog = async (row: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getToInfraredApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions2()
+  const params = {
+    title: '开始任务',
+    width: 580,
+    isEdit: true,
+    itemsOptions: itemsOptions,
+    model: res.data,
+    api: startToInfraredApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除可见光转红外信息
+const deleteToInfrared = async (params: any) => {
+  await useHandleData(delToInfraredApi, params.id, '删除【' + params.id + '】可见光转红外')
+  proTable.value?.getTableList()
+}
+
+// 批量删除可见光转红外信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delToInfraredApi, ids, '删除所选可见光转红外信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出可见光转红外列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出可见光转红外数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportToInfraredApi, '可见光转红外列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加可见光转红外
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '可见光转红外',
+    tempApi: importTemplateApi,
+    importApi: importToInfraredDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getToInfraredApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addToInfraredApi : updateToInfraredApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: '主键ID', width: 180 },
+  {
+    prop: 'name',
+    label: '任务名称',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
+  {
+    prop: 'status',
+    label: '任务状态',
+    search: {
+      el: 'select'
+    },
+    tag: true,
+    enum: statusEnums,
+    width: 150
+  },
+  {
+    prop: 'type',
+    label: '类型',
+    tag: true,
+    enum: enumsAlgorithmType,
+    width: 120
+  },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    width: 200
+  },
+  {
+    prop: 'algorithmName',
+    label: '算法名称',
+    width: 200
+  },
+  {
+    prop: 'modelName',
+    label: '模型名称',
+    width: 200
+  },
+  // {
+  //   prop: 'algorithmModelId',
+  //   label: '模型',
+  //   search: {
+  //     el: 'input'
+  //   },
+  //   width: 150
+  // },
+  {
+    prop: 'startTime',
+    label: '开始时间',
+    width: 180
+  },
+  {
+    prop: 'endTime',
+    label: '结束时间',
+    width: 180
+  },
+  {
+    prop: 'costSecond',
+    label: '耗时',
+    width: 120
+  },
+  {
+    prop: 'log',
+    label: '日志',
+    width: 120
+  },
+  {
+    prop: 'outputPath',
+    label: '输出路径',
+    width: 120
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传数据集',
+        enum: getImageDataList,
+        clearable: true
+      }
+    },
+    {
+      label: '上传数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集'
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModelId',
+      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: enumsAlgorithmModelTrack
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const getImageDataList = ref<any>([])
+onMounted(async () => {
+  const qyery = {
+    subsystem: SubSystem__['可见光转红外'],
+    pageNum: 1,
+    pageSize: 25
+  }
+  const result: any = await listDataSeqApi(qyery)
+  const data = result['data']['list']
+  for (const item of data) {
+    getImageDataList.value.push({
+      value: item['inputOssId'],
+      label: item['name']
+    })
+  }
+})
+
+const enumsAlgorithmModelTrack = ref<any>([])
+
+onMounted(async () => {
+  const result: any = await enumAlgorithmModelTrackApi()
+  // console.log(result.data);
+  enumsAlgorithmModelTrack.value = []
+  for (const item of result.data) {
+    if (SubSystem[item['subsystem']] === '可见光转红外') {
+      item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
+      enumsAlgorithmModelTrack.value.push(item)
+    }
+  }
+})
+
+const setItemsOptions2 = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModel',
+      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: enumsAlgorithmModelTrack
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const enumsAlgorithmConfigTrack = ref<any>([])
+onMounted(async () => {
+  const result = await enumAlgorithmConfigTrackApi()
+  enumsAlgorithmConfigTrack.value = result['data']
+  for (const item of enumsAlgorithmConfigTrack.value) {
+    item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
+  }
+  return result['data']
+})
+
+const setItemsOptionsModel = () => {
+  itemsOptions = [
+    {
+      label: '算法ID',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        placeholder: '请输入算法'
+      }
+    },
+    {
+      label: '算法类型',
+      prop: 'algorithmType',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请输入算法',
+        enum: enumsAlgorithmConfigTrack
+      }
+    },
+    {
+      label: '算法参数',
+      prop: 'parameterConfig',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型ID',
+      prop: 'id',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型名称',
+      prop: 'modelName',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型保存路径',
+      prop: 'modelAddress',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+</script>

+ 449 - 0
src/views/demo/trackSequence/index.vue

@@ -0,0 +1,449 @@
+<template>
+  <div class="table-box">
+    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listTrackSequenceApi">
+      <!-- 表格 header 按钮 -->
+      <template #tableHeader="scope">
+        <el-button type="primary" v-auth="['demo:trackSequence:add']" icon="CirclePlus" @click="openDialog(1, '注视轨迹序列新增')"> 新增 </el-button>
+        <!-- <el-button type="primary" v-auth="['demo:trackSequence:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button>
+        <el-button type="primary" v-auth="['demo:trackSequence:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button> -->
+        <el-button
+          type="danger"
+          v-auth="['demo:trackSequence:remove']"
+          icon="Delete"
+          plain
+          :disabled="!scope.isSelected"
+          @click="batchDelete(scope.selectedListIds)"
+        >
+          批量删除
+        </el-button>
+      </template>
+      <!-- 表格操作 -->
+      <template #operation="scope">
+        <el-button type="primary" link icon="View" v-if="scope.row.algorithmModelId != null" @click="openModelDialog(scope.row)">
+          <!--@click="openStartDialog(scope.row)"  -->
+          模型
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:trackSequence:start']"
+          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
+          @click="startTrackSequence(scope.row)"
+        >
+          开始
+        </el-button>
+        <el-popconfirm title="确定终止此任务吗?" @confirm="stopTrackSequence(scope.row)" v-if="scope.row.status == '1'">
+          <template #reference>
+            <el-button type="primary" link icon="Delete"> 终止</el-button>
+          </template>
+        </el-popconfirm>
+        <el-button
+          type="primary"
+          link
+          icon="View"
+          v-auth="['demo:trackSequence:download']"
+          v-if="scope.row.status == '2'"
+          @click="dowloadTrackSequence(scope.row)"
+        >
+          下载
+        </el-button>
+        <!-- <el-button type="primary" link icon="View" v-auth="['demo:toInfrared:query']" @click="openDialog(3, '查看', scope.row)"> 查看 </el-button> -->
+        <!-- <el-button type="primary" link icon="EditPen"v-auth="['demo:toInfrared:edit']" @click="openDialog(2, '编辑', scope.row)"> 编辑 </el-button> -->
+        <el-button
+          type="primary"
+          link
+          icon="Delete"
+          v-auth="['demo:toInfrared:remove']"
+          @click="deleteTrackSequence(scope.row)"
+          :disabled="scope.row.status == '1'"
+        >
+          删除
+        </el-button>
+      </template>
+    </ProTable>
+    <FormDialog ref="formDialogRef" />
+    <ImportExcel ref="dialogRef" />
+  </div>
+</template>
+
+<script setup lang="tsx" name="TrackSequence">
+import { ref, reactive, onMounted } from 'vue'
+import { useHandleData } from '@/hooks/useHandleData'
+import { useDownload } from '@/hooks/useDownload'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import ProTable from '@/components/ProTable/index.vue'
+import ImportExcel from '@/components/ImportExcel/index.vue'
+import FormDialog from '@/components/FormDialog/index.vue'
+import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
+import {
+  listTrackSequenceApi,
+  delTrackSequenceApi,
+  addTrackSequenceApi,
+  updateTrackSequenceApi,
+  importTemplateApi,
+  importTrackSequenceDataApi,
+  exportTrackSequenceApi,
+  getTrackSequenceApi,
+  startTrackSequenceApi,
+  stopTrackSequenceApi,
+  dowloadTrackSequenceApi
+} from '@/api/modules/demo/trackSequence'
+import { enumAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
+import { enumAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
+
+import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
+import statusEnums from '@/utils/status'
+import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
+
+const enumsAlgorithmConfigTrack = ref<any>([])
+onMounted(async () => {
+  const result = await enumAlgorithmConfigTrackApi()
+  // console.log(result)
+  // console.log(result['data'])
+  enumsAlgorithmConfigTrack.value = result['data']
+  return result['data']
+})
+
+const openModelDialog = async row => {
+  const algorithmModelId = row.algorithmModelId
+  const result: any = await getAlgorithmModelTrackApi(algorithmModelId)
+
+  // console.log(result.data)
+
+  setItemsOptionsModel()
+  const params = {
+    title: '模型',
+    width: 580,
+    isEdit: false,
+    itemsOptions: itemsOptions,
+    model: result.data,
+    api: updateTrackSequenceApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+const startTrackSequence = async (params: any) => {
+  const res: any = await startTrackSequenceApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('任务已开始,请等待完成!')
+  } else {
+    ElMessage.error('任务开始失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+
+const stopTrackSequence = async (params: any) => {
+  const res: any = await stopTrackSequenceApi(params.id)
+  if (res.code === 200) {
+    ElMessage.success('终止任务成功!')
+  } else {
+    ElMessage.error('终止任务失败,请检查!')
+  }
+  proTable.value?.getTableList()
+}
+
+const dowloadTrackSequence = async (params: any) => {
+  await useDownload(dowloadTrackSequenceApi, params.name, params.id, true, '.zip')
+}
+
+// ProTable 实例
+const proTable = ref<ProTableInstance>()
+
+// 删除注视轨迹序列信息
+const deleteTrackSequence = async (params: any) => {
+  await useHandleData(delTrackSequenceApi, params.id, '删除【' + params.id + '】注视轨迹序列')
+  proTable.value?.getTableList()
+}
+
+// 批量删除注视轨迹序列信息
+const batchDelete = async (ids: string[]) => {
+  await useHandleData(delTrackSequenceApi, ids, '删除所选注视轨迹序列信息')
+  proTable.value?.clearSelection()
+  proTable.value?.getTableList()
+}
+
+// 导出注视轨迹序列列表
+const downloadFile = async () => {
+  ElMessageBox.confirm('确认导出注视轨迹序列数据?', '温馨提示', { type: 'warning' }).then(() =>
+    useDownload(exportTrackSequenceApi, '注视轨迹序列列表', proTable.value?.searchParam)
+  )
+}
+
+// 批量添加注视轨迹序列
+const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
+const batchAdd = () => {
+  const params = {
+    title: '注视轨迹序列',
+    tempApi: importTemplateApi,
+    importApi: importTrackSequenceDataApi,
+    getTableList: proTable.value?.getTableList
+  }
+  dialogRef.value?.acceptParams(params)
+}
+
+const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
+// 打开弹框的功能
+const openDialog = async (type: number, title: string, row?: any) => {
+  let res = { data: {} }
+  if (row?.id) {
+    res = await getTrackSequenceApi(row?.id || null)
+  }
+  // 重置表单
+  setItemsOptions()
+  const params = {
+    title,
+    width: 580,
+    isEdit: type !== 3,
+    itemsOptions: itemsOptions,
+    model: type == 1 ? {} : res.data,
+    api: type == 1 ? addTrackSequenceApi : updateTrackSequenceApi,
+    getTableList: proTable.value?.getTableList
+  }
+  formDialogRef.value?.openDialog(params)
+}
+
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  { type: 'selection', fixed: 'left', width: 70 },
+  { prop: 'id', label: '主键ID', width: 180 },
+  {
+    prop: 'name',
+    label: '任务名称',
+    search: {
+      el: 'input'
+    },
+    width: 150
+  },
+  {
+    prop: 'status',
+    label: '任务状态',
+    search: {
+      el: 'select'
+    },
+    tag: true,
+    enum: statusEnums,
+    width: 150
+  },
+  {
+    prop: 'type',
+    label: '类型',
+    tag: true,
+    enum: enumsAlgorithmType,
+    width: 120
+  },
+  {
+    prop: 'subsystem',
+    label: '分系统',
+    tag: true,
+    enum: enumsSubSystem,
+    width: 200
+  },
+  {
+    prop: 'algorithmName',
+    label: '算法名称',
+    width: 200
+  },
+  {
+    prop: 'modelName',
+    label: '模型名称',
+    width: 200
+  },
+  // {
+  //   prop: 'algorithmModelId',
+  //   label: '模型',
+  //   search: {
+  //     el: 'input'
+  //   },
+  //   width: 150
+  // },
+  {
+    prop: 'startTime',
+    label: '开始时间',
+    width: 180
+  },
+  {
+    prop: 'endTime',
+    label: '结束时间',
+    width: 180
+  },
+  {
+    prop: 'costSecond',
+    label: '耗时',
+    width: 120
+  },
+  {
+    prop: 'log',
+    label: '日志',
+    width: 120
+  },
+  {
+    prop: 'outputPath',
+    label: '输出路径',
+    width: 120
+  },
+  {
+    prop: 'remarks',
+    label: '备注',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
+])
+
+// 表单配置项
+let itemsOptions: ProForm.ItemsOptions[] = []
+const setItemsOptions = () => {
+  itemsOptions = [
+    {
+      label: '任务名称',
+      prop: 'name',
+      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入任务名称'
+      }
+    },
+    {
+      label: '选择数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择或者上传数据集',
+        enum: getImageDataList,
+        clearable: true
+      }
+    },
+    {
+      label: '上传数据集',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传数据集'
+      }
+    },
+    {
+      label: '选择模型',
+      prop: 'algorithmModelId',
+      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'select',
+        placeholder: '请选择模型',
+        enum: enumsAlgorithmModelTrack
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const setItemsOptionsModel = () => {
+  itemsOptions = [
+    {
+      label: '算法ID',
+      prop: 'algorithmId',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        placeholder: '请输入算法'
+      }
+    },
+    {
+      label: '算法类型',
+      prop: 'algorithmType',
+      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
+      compOptions: {
+        disabled: true,
+        elTagName: 'select',
+        placeholder: '请输入算法',
+        enum: enumsAlgorithmConfigTrack
+      }
+    },
+    {
+      label: '算法参数',
+      prop: 'parameterConfig',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型ID',
+      prop: 'id',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型名称',
+      prop: 'modelName',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '模型保存路径',
+      prop: 'modelAddress',
+      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入模型名称'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
+    }
+  ]
+}
+
+const getImageDataList = ref<any>([])
+onMounted(async () => {
+  const qyery = {
+    subsystem: SubSystem__['注释轨迹序列'],
+    pageNum: 1,
+    pageSize: 25
+  }
+  const result: any = await listDataSeqApi(qyery)
+  const data = result['data']['list']
+  for (const item of data) {
+    getImageDataList.value.push({
+      value: item['inputOssId'],
+      label: item['name']
+    })
+  }
+})
+
+const enumsAlgorithmModelTrack = ref<any>([])
+
+onMounted(async () => {
+  const result: any = await enumAlgorithmModelTrackApi()
+  // console.log(result.data);
+  enumsAlgorithmModelTrack.value = []
+
+  for (const item of result.data) {
+    if (SubSystem[item['subsystem']] === '注释轨迹序列') {
+      item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
+      enumsAlgorithmModelTrack.value.push(item)
+    }
+  }
+})
+</script>

+ 78 - 0
src/views/demo/utils.ts

@@ -0,0 +1,78 @@
+/*
+ * @Datetime : 2024/9/28 15:51
+ * @Author   : WANGKANG
+ * @Email    : 1686617586@qq.com
+ * @Blog     :
+ * @File     : utils.vue
+ * @brief    : 组件工具包
+ * Copyright 2024 WANGKANG, All Rights Reserved.
+ */
+
+export const AlgorithmType = {
+  '0': '训练',
+  '1': '测试',
+  '2': '预测/推理'
+}
+
+export const SubSystem = {
+  '0': '可见光转红外',
+  '1': '目标检测',
+  '2': '注释轨迹序列'
+}
+
+export const SubSystem__ = {
+  可见光转红外: '0',
+  目标检测: '1',
+  注释轨迹序列: '2'
+}
+
+export const AlgorithmType2 = {
+  训练: '0',
+  测试: '1',
+  '预测/推理': '2'
+}
+
+export const enumsAlgorithmType = [
+  { label: '训练', value: '0' },
+  { label: '测试', value: '1' },
+  { label: '预测/推理', value: '2' }
+]
+
+export const enumsSubSystem = [
+  { label: '可见光转红外', value: '0' },
+  { label: '目标检测', value: '1' },
+  { label: '注释轨迹序列', value: '2' }
+]
+
+export const enumsModelStatus = [
+  {
+    label: '未训练',
+    value: '0',
+    disabled: false,
+    tagType: 'default'
+  },
+  {
+    label: '训练中',
+    value: '1',
+    disabled: false,
+    tagType: 'primary'
+  },
+  {
+    label: '完成',
+    value: '2',
+    disabled: false,
+    tagType: 'success'
+  },
+  {
+    label: '失败',
+    value: '3',
+    disabled: false,
+    tagType: 'danger'
+  },
+  {
+    label: '中断',
+    value: '4',
+    disabled: false,
+    tagType: 'default'
+  }
+]