Quellcode durchsuchen

Merge branch 'tl-develop' into develop

allen vor 7 Monaten
Ursprung
Commit
b4c1c52809

+ 1 - 0
package.json

@@ -61,6 +61,7 @@
     "vue-konva": "^3.0.2",
     "vue-router": "^4.2.5",
     "vue-types": "^5.1.1",
+    "vue-video-player": "^6.0.0",
     "vuedraggable": "^4.1.0"
   },
   "devDependencies": {

+ 3 - 3
src/api/modules/demo/dataAugmentation.ts

@@ -109,8 +109,8 @@ export const stopDataAugmentationApi = (id: String | Number) => {
   return http.get('/demo/dataAugmentation/stop/' + id)
 }
 
-export const getCompareImageApi = (taskId: String, idx: String | Number) => {
-  return http.get('/demo/dataAugmentation/compare/' + taskId + '/' + idx)
+export const getCompareImageApi = (taskId: String) => {
+  return http.get('/demo/dataAugmentation/compare/' + taskId)
 }
 
 export const getCompareImageCountApi = (taskId: String | Number) => {
@@ -118,7 +118,7 @@ export const getCompareImageCountApi = (taskId: String | Number) => {
 }
 
 export const getDialogApi = (id: String | Number) => {
-  return http.get('/demo/dataAugmentation/log/' + id)
+  return http.get<any>('/demo/dataAugmentation/log/' + id, { loading: false })
 }
 
 export const getMetricApi = (id: String | Number) => {

+ 151 - 21
src/views/demo/dataAugmentation/index.vue

@@ -44,8 +44,8 @@
           link
           icon="View"
           v-auth="['demo:DataAugmentation:query']"
-          @click="openLogDialog(scope.row.id)"
-          v-if="scope.row.status != '0'"
+          @click="viewLogRef.handleOpen(scope.row.id)"
+          v-if="scope.row.status != '0' && scope.row.status != '1'"
         >
           日志
         </el-button>
@@ -59,20 +59,20 @@
     <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
       <div class="image-dialog" v-if="imageIdx >= 0 && cacheImages[imageIdx]">
         <div style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="image"></el-image>
           <!-- <el-tag>结果:</el-tag> -->
         </div>
         <div v-if="task_type_view == '目标毁伤评估'" style="width: 50%">
           <ul v-infinite-scroll="load" class="list" :infinite-scroll-disabled="disabled">
             <li v-for="i in count" :key="i" style="list-style-type: none">
-              <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].stable[i - 1]"></el-image>
+              <el-image :src="cacheImages[imageIdx].stable[i - 1]"></el-image>
             </li>
           </ul>
           <p v-if="loading">Loading...</p>
           <p v-if="noMore">No more</p>
         </div>
         <div v-else style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="image"></el-image>
         </div>
       </div>
       <div class="image-dialog-btn" v-if="imageFps == 0">
@@ -80,9 +80,10 @@
         <el-button type="primary" @click="next_picture" :disabled="imageIdx >= fileCount - 1">下一个</el-button>
       </div>
     </el-dialog>
-    <el-dialog v-model="logDialogVisible" title="日志" width="80%">
+    <!-- <el-dialog v-model="logDialogVisible" title="日志" width="80%">
       <el-text class="mx-1">{{ logDialog }}</el-text>
-    </el-dialog>
+    </el-dialog> -->
+    <ViewLog ref="viewLogRef" :get-log-api="getDialogApi" />
     <el-dialog v-model="metricDialogVisible" title="算法结果指标" width="500px" style="text-align: center">
       <el-table :data="metricList" style="width: 100%; margin-left: 10%; text-align: left">
         <el-table-column prop="name" label="name" width="200px" />
@@ -101,6 +102,7 @@ import ProTable from '@/components/ProTable/index.vue'
 import ImportExcel from '@/components/ImportExcel/index.vue'
 import DataAugmentationFormDialog from '@/components/DataAugmentationFormDialog/index.vue'
 import { ProTableInstance, ColumnProps, EnumProps } from '@/components/ProTable/interface'
+import ViewLog from '@/views/demo/components/ViewLog.vue'
 import {
   listDataAugmentationApi,
   delDataAugmentationApi,
@@ -121,7 +123,7 @@ import {
 // import {  } from '@/api/modules/system/dictData'
 import { S } from 'vite/dist/node/types.d-aGj9QkWt'
 import { servicesVersion } from 'typescript'
-
+const viewLogRef = ref()
 //打开指标窗口查看算法指标信息
 const metricDialogVisible = ref(false)
 const metricList = reactive([])
@@ -266,17 +268,18 @@ const compareDataAugmentation = async (params: any) => {
 
   dialogTitle.value = '缓存图片中'
   fileCount.value = Math.min(inFileCount.value, outFileCount.value)
+  const res: any = await getCompareImageApi(taskId.value)
   for (let idx = 1; idx <= fileCount.value; idx++) {
     dialogTitle.value = '缓存图片中: 第' + idx + '个样本 共' + fileCount.value + '个样本'
     if (cacheImages.value[idx - 1]) {
       continue
     }
-    const res: any = await getCompareImageApi(taskId.value, idx - 1)
+
     // console.log(res)
 
     cacheImages.value[idx - 1] = {
-      origin: res.origin,
-      stable: res.stable
+      origin: res.origin[idx - 1],
+      stable: res.stable[idx - 1]
     }
   }
   // console.log(cacheImages.value[0])
@@ -543,17 +546,144 @@ const addParams = params => {
     const obj: { [key: string]: number } = JSON.parse(validJsonString)
     Object.keys(obj).forEach(key => {
       model.value[key] = obj[key]
+      if (key === 'ratio_mix' || key === 'alpha') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                if (!value) {
+                  return callback(new Error('请输入一个0到1之间的浮点数'))
+                }
+                const regex = /^(0(\.\d+)?|1(\.0+)?)$/
+                if (!regex.test(value)) {
+                  return callback(new Error('请输入一个0到1之间的浮点数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      } else if (key === 'light') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                const minValue = 40
+                const maxValue = 60
 
-      itemsOptions.push({
-        label: key,
-        prop: key,
-        rules: [{ trigger: 'blur' }],
-        compOptions: {
-          type: 'input',
-          clearable: true,
-          placeholder: '默认值为' + obj[key]
-        }
-      })
+                const intValue = parseInt(value, 10)
+                if (isNaN(intValue) || intValue < minValue || intValue > maxValue) {
+                  return callback(new Error('请输入一个40到60之间的整数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      } else if (key === 'beta') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                const minValue = -30
+                const maxValue = -10
+
+                const intValue = parseInt(value, 10)
+                if (isNaN(intValue) || intValue < minValue || intValue > maxValue) {
+                  return callback(new Error('请输入一个-30到-10之间的负整数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      } else if (key === 'beta') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                const minValue = -30
+                const maxValue = -10
+
+                const intValue = parseInt(value, 10)
+                if (isNaN(intValue) || intValue < minValue || intValue > maxValue) {
+                  return callback(new Error('请输入一个-30到-10之间的负整数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      } else if (key === 's_v') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                const intValue = parseInt(value, 10)
+                if (isNaN(intValue) || intValue <= 0 || intValue % 2 === 0) {
+                  return callback(new Error('请输入一个大于0的奇整数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      }
     })
   } catch (error) {
     console.error('解析 JSON 字符串时出错:', error)

+ 15 - 12
src/views/demo/imageMosaic/index.vue

@@ -44,8 +44,8 @@
           link
           icon="View"
           v-auth="['demo:DataAugmentation:query']"
-          @click="openLogDialog(scope.row.id)"
-          v-if="scope.row.status != '0'"
+          @click="viewLogRef.handleOpen(scope.row.id)"
+          v-if="scope.row.status != '0' && scope.row.status != '1'"
         >
           日志
         </el-button>
@@ -59,20 +59,20 @@
     <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
       <div class="image-dialog" v-if="imageIdx >= 0 && cacheImages[imageIdx]">
         <div style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="image"></el-image>
           <!-- <el-tag>结果:</el-tag> -->
         </div>
         <div v-if="task_type_view == '目标毁伤评估'" style="width: 50%">
           <ul v-infinite-scroll="load" class="list" :infinite-scroll-disabled="disabled">
             <li v-for="i in count" :key="i" style="list-style-type: none">
-              <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].stable[i - 1]"></el-image>
+              <el-image :src="cacheImages[imageIdx].stable[i - 1]"></el-image>
             </li>
           </ul>
           <p v-if="loading">Loading...</p>
           <p v-if="noMore">No more</p>
         </div>
         <div v-else style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="image"></el-image>
         </div>
       </div>
       <div class="image-dialog-btn" v-if="imageFps == 0">
@@ -80,9 +80,10 @@
         <el-button type="primary" @click="next_picture" :disabled="imageIdx >= fileCount - 1">下一个</el-button>
       </div>
     </el-dialog>
-    <el-dialog v-model="logDialogVisible" title="日志" width="80%">
+    <!-- <el-dialog v-model="logDialogVisible" title="日志" width="80%">
       <el-text class="mx-1">{{ logDialog }}</el-text>
-    </el-dialog>
+    </el-dialog> -->
+    <ViewLog ref="viewLogRef" :get-log-api="getDialogApi" />
     <el-dialog v-model="metricDialogVisible" title="算法结果指标" width="40%;" style="text-align: center">
       <el-table :data="metricList" style="width: 100%; margin-left: 10%; text-align: left">
         <el-table-column prop="name" label="name" width="200px" />
@@ -101,6 +102,7 @@ import ProTable from '@/components/ProTable/index.vue'
 import ImportExcel from '@/components/ImportExcel/index.vue'
 import DataAugmentationFormDialog from '@/components/DataAugmentationFormDialog/index.vue'
 import { ProTableInstance, ColumnProps, EnumProps } from '@/components/ProTable/interface'
+import ViewLog from '@/views/demo/components/ViewLog.vue'
 import {
   listDataAugmentationApi1,
   delDataAugmentationApi,
@@ -119,9 +121,8 @@ import {
   getMetricApi
 } from '@/api/modules/demo/dataAugmentation'
 // import {  } from '@/api/modules/system/dictData'
-import { S } from 'vite/dist/node/types.d-aGj9QkWt'
-import { servicesVersion } from 'typescript'
 
+const viewLogRef = ref()
 //打开指标窗口查看算法指标信息
 const metricDialogVisible = ref(false)
 const metricList = reactive([])
@@ -266,17 +267,19 @@ const compareDataAugmentation = async (params: any) => {
 
   dialogTitle.value = '缓存图片中'
   fileCount.value = Math.min(inFileCount.value, outFileCount.value)
+  const res: any = await getCompareImageApi(taskId.value)
+  console.log(res)
   for (let idx = 1; idx <= fileCount.value; idx++) {
     dialogTitle.value = '缓存图片中: 第' + idx + '个样本 共' + fileCount.value + '个样本'
     if (cacheImages.value[idx - 1]) {
       continue
     }
-    const res: any = await getCompareImageApi(taskId.value, idx - 1)
+
     // console.log(res)
 
     cacheImages.value[idx - 1] = {
-      origin: res.origin,
-      stable: res.stable
+      origin: res.origin[idx - 1],
+      stable: res.stable[idx - 1]
     }
   }
   // console.log(cacheImages.value[0])

+ 14 - 12
src/views/demo/targetDamageAcess/index.vue

@@ -44,8 +44,8 @@
           link
           icon="View"
           v-auth="['demo:DataAugmentation:query']"
-          @click="openLogDialog(scope.row.id)"
-          v-if="scope.row.status != '0'"
+          @click="viewLogRef.handleOpen(scope.row.id)"
+          v-if="scope.row.status != '0' && scope.row.status != '1'"
         >
           日志
         </el-button>
@@ -59,20 +59,20 @@
     <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
       <div class="image-dialog" v-if="imageIdx >= 0 && cacheImages[imageIdx]">
         <div style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].origin" :key="index" :src="image"></el-image>
           <!-- <el-tag>结果:</el-tag> -->
         </div>
         <div v-if="task_type_view == '目标毁伤评估'" style="width: 50%">
           <ul v-infinite-scroll="load" class="list" :infinite-scroll-disabled="disabled">
             <li v-for="i in count" :key="i" style="list-style-type: none">
-              <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].stable[i - 1]"></el-image>
+              <el-image :src="cacheImages[imageIdx].stable[i - 1]"></el-image>
             </li>
           </ul>
           <p v-if="loading">Loading...</p>
           <p v-if="noMore">No more</p>
         </div>
         <div v-else style="width: 50%">
-          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="'data:image/png;base64,' + image"></el-image>
+          <el-image v-for="(image, index) in cacheImages[imageIdx].stable" :key="index" :src="image"></el-image>
         </div>
       </div>
       <div class="image-dialog-btn" v-if="imageFps == 0">
@@ -80,9 +80,10 @@
         <el-button type="primary" @click="next_picture" :disabled="imageIdx >= fileCount - 1">下一个</el-button>
       </div>
     </el-dialog>
-    <el-dialog v-model="logDialogVisible" title="日志" width="80%">
+    <!-- <el-dialog v-model="logDialogVisible" title="日志" width="80%">
       <el-text class="mx-1">{{ logDialog }}</el-text>
-    </el-dialog>
+    </el-dialog> -->
+    <ViewLog ref="viewLogRef" :get-log-api="getDialogApi" />
     <el-dialog v-model="metricDialogVisible" title="算法结果指标" width="40%;" style="text-align: center">
       <el-table :data="metricList" style="width: 100%; margin-left: 10%; text-align: left">
         <el-table-column prop="name" label="name" width="200px" />
@@ -101,6 +102,7 @@ import ProTable from '@/components/ProTable/index.vue'
 import ImportExcel from '@/components/ImportExcel/index.vue'
 import DataAugmentationFormDialog from '@/components/DataAugmentationFormDialog/index.vue'
 import { ProTableInstance, ColumnProps, EnumProps } from '@/components/ProTable/interface'
+import ViewLog from '@/views/demo/components/ViewLog.vue'
 import {
   listDataAugmentationApi2,
   delDataAugmentationApi,
@@ -119,9 +121,8 @@ import {
   getMetricApi
 } from '@/api/modules/demo/dataAugmentation'
 // import {  } from '@/api/modules/system/dictData'
-import { S } from 'vite/dist/node/types.d-aGj9QkWt'
-import { servicesVersion } from 'typescript'
 
+const viewLogRef = ref()
 //打开指标窗口查看算法指标信息
 const metricDialogVisible = ref(false)
 const metricList = reactive([])
@@ -266,17 +267,18 @@ const compareDataAugmentation = async (params: any) => {
 
   dialogTitle.value = '缓存图片中'
   fileCount.value = Math.min(inFileCount.value, outFileCount.value)
+  const res: any = await getCompareImageApi(taskId.value)
   for (let idx = 1; idx <= fileCount.value; idx++) {
     dialogTitle.value = '缓存图片中: 第' + idx + '个样本 共' + fileCount.value + '个样本'
     if (cacheImages.value[idx - 1]) {
       continue
     }
-    const res: any = await getCompareImageApi(taskId.value, idx - 1)
+
     // console.log(res)
 
     cacheImages.value[idx - 1] = {
-      origin: res.origin,
-      stable: res.stable
+      origin: res.origin[idx - 1],
+      stable: res.stable[idx - 1]
     }
   }
   // console.log(cacheImages.value[0])

+ 244 - 51
src/views/demo/targetTrack/index.vue

@@ -25,17 +25,9 @@
             <el-button type="primary" link icon="View"> 终止 </el-button>
           </template>
         </el-popconfirm>
-        <el-button type="primary" link icon="View" @click="openResultDialog(scope.row.id)" v-if="scope.row.status == '2'"> 预览 </el-button>
+        <el-button type="primary" link icon="View" @click="compareDataAugmentation(scope.row)" v-if="scope.row.status == '2'"> 预览 </el-button>
         <el-button type="primary" link icon="View" @click="downloadFile(scope.row)" v-if="scope.row.status == '2'"> 导出 </el-button>
-        <el-button
-          type="primary"
-          link
-          icon="View"
-          @click="openMetricDialog(scope.row.id)"
-          v-if="(scope.row.taskType == '图像增强' || scope.row.taskType == '图像逆光') && scope.row.status == '2'"
-        >
-          指标
-        </el-button>
+        <el-button type="primary" link icon="View" @click="openMetricDialog(scope.row.id)" v-if="scope.row.status == '2'"> 指标 </el-button>
         <el-button type="primary" link icon="View" v-auth="['demo:DataAugmentation:query']" @click="openDialog(3, '任务查看', scope.row)">
           查看
         </el-button>
@@ -56,7 +48,7 @@
     </ProTable>
     <DataAugmentationFormDialog ref="formDialogRef" />
     <ImportExcel ref="dialogRef" />
-    <el-dialog v-model="dialogVisible" title="结果预览" width="80%">
+    <!-- <el-dialog v-model="dialogVisible" title="结果预览" width="80%">
       <div style="display: flex; text-align: center">
         <div style="width: 50%" v-if="inputVideoUrl">
           <video controls width="90%">
@@ -71,12 +63,28 @@
           </video>
         </div>
       </div>
-    </el-dialog>
-
-    <!-- <VideoWindow ref="videoWindowRef" :video-url="url"></VideoWindow> -->
-    <!-- <el-dialog v-model="logDialogVisible" title="日志" width="80%">
-      <el-text class="mx-1">{{ logDialog }}</el-text>
     </el-dialog> -->
+
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%" @close="handleClose">
+      <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>
+      <div class="image-dialog" v-if="imageIdx >= 0 && cacheImages[imageIdx]">
+        <div style="width: 50%">
+          <el-image :src="cacheImages[imageIdx].origin[0]"></el-image>
+        </div>
+        <div style="width: 50%">
+          <el-image :src="cacheImages[imageIdx].stable[0]"></el-image>
+        </div>
+      </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 >= fileCount - 1">下一个</el-button>
+      </div>
+    </el-dialog>
     <ViewLog ref="viewLogRef" :get-log-api="getDialogApi" />
     <el-dialog v-model="metricDialogVisible" title="算法结果指标" width="500px" style="text-align: center">
       <el-table :data="metricList" style="width: 100%; margin-left: 10%; text-align: left">
@@ -88,7 +96,7 @@
 </template>
 
 <script setup lang="tsx" name="DataAugmentation">
-import { ref, reactive, onMounted, computed, onUnmounted, onBeforeMount } from 'vue'
+import { ref, reactive, onMounted, computed, onUnmounted, onBeforeMount, watch, nextTick } from 'vue'
 import { useHandleData } from '@/hooks/useHandleData'
 import { useDownload } from '@/hooks/useDownload'
 import { ElMessageBox, ElMessage } from 'element-plus'
@@ -96,7 +104,6 @@ import ProTable from '@/components/ProTable/index.vue'
 import ImportExcel from '@/components/ImportExcel/index.vue'
 import ViewLog from '@/views/demo/components/ViewLog.vue'
 
-import VideoWindow from '@/views/demo/components/VideoWindow.vue'
 import DataAugmentationFormDialog from '@/components/DataAugmentationFormDialog/index.vue'
 import { ProTableInstance, ColumnProps, EnumProps } from '@/components/ProTable/interface'
 import {
@@ -117,13 +124,150 @@ import {
   getMetricApi,
   getVideoUrl
 } from '@/api/modules/demo/dataAugmentation'
-// import {  } from '@/api/modules/system/dictData'
+// import { VideoPlayer } from 'vue-video-player'
+// import 'vue-video-player/dist/simple.css'
+
+// const playerOptions = ref({})
+// const videoPlayer = ref<InstanceType<typeof VideoPlayer> | null>(null);
+
+// const playVideo = () => {
+//   if (videoPlayer.value) {
+//     videoPlayer.value.player.play();
+//   }
+// };
+
+// const pauseVideo = () => {
+//   if (videoPlayer.value) {
+//     videoPlayer.value.player.pause();
+//   }
+// };
 
-const videoWindowRef = ref()
-const playerOptions = ref({})
+// const onPlay = () => {
+//   console.log('视频开始播放');
+// };
+
+// const onPause = () => {
+//   console.log('视频暂停播放');
+// };
+// const setPlayerOptions = (url) => {
+
+//   playerOptions.value = {
+//     sources: [{
+//       type: "video/mp4",
+//       src: url
+//     }],
+//     poster: "", // 视频封面图
+//     autoplay: false,
+//     controls: true,
+//     fluid: true // 响应式布局
+//   }
+// }
+
+const handleClose = () => {
+  if (intervalChangeFps.value) {
+    clearInterval(intervalChangeFps.value)
+  }
+}
+
+const changeFps = () => {
+  console.log('changeFps')
+  if (intervalChangeFps.value) {
+    clearInterval(intervalChangeFps.value)
+  }
+
+  if (imageFps.value == 0) {
+    return
+  }
+  imageIdx.value = 1
+  intervalChangeFps.value = setInterval(() => {
+    next_picture()
+  }, 1000 / imageFps.value)
+}
+const dialogVisible = ref(false)
+const taskId = ref('')
+const imageIdx = ref(0)
+const imageBase64List = ref({
+  origin: '',
+  stable: ''
+})
+const inFileCount = ref(0)
+const outFileCount = ref(0)
+const cacheImages = ref({})
+const dialogTitle = ref('')
+const fileCount = ref(0)
+const imageFps = ref(0)
+const intervalChangeFps: any = ref()
+const loadImageData = async (taskId: string, imageIdx: number) => {
+  const res: any = await getCompareImageApi(taskId, imageIdx)
+  // imageBase64List.value.origin = res.origin
+  // imageBase64List.value.stable = res.stable
+  cacheImages.value[imageIdx].origin = res.origin
+  cacheImages.value[imageIdx].stable = res.stable
+}
+const task_type_view = ref('')
+const compareDataAugmentation = async (params: any) => {
+  if (taskId.value !== '' && taskId.value !== null && taskId.value !== undefined && taskId.value == params.id) {
+    dialogVisible.value = true
+    return
+  }
+  task_type_view.value = params.taskType
+  taskId.value = params.id
+  imageIdx.value = 0
+  cacheImages.value = {}
+  const resCount: any = await getCompareImageCountApi(params.id)
+  if (resCount.code === 200) {
+    inFileCount.value = resCount.data.inFileCount
+    outFileCount.value = resCount.data.outFileCount
+  } else {
+    ElMessage.error('获取图片对比数量失败')
+    return
+  }
+  dialogVisible.value = true
+
+  dialogTitle.value = '缓存图片中'
+  fileCount.value = Math.min(inFileCount.value, outFileCount.value)
+  const res: any = await getCompareImageApi(taskId.value)
+  for (let idx = 1; idx <= fileCount.value; idx++) {
+    dialogTitle.value = '缓存图片中: 第' + idx + '个样本 共' + fileCount.value + '个样本'
+    if (cacheImages.value[idx - 1]) {
+      continue
+    }
+    //const res: any = await getCompareImageApi(taskId.value, idx - 1)
+    // console.log(res)
+
+    cacheImages.value[idx - 1] = {
+      origin: res.origin[idx - 1],
+      stable: res.stable[idx - 1]
+    }
+  }
+  // console.log(cacheImages.value[0])
+  if (fileCount.value > 0) {
+    dialogTitle.value = '预览: 第1个样本 共' + fileCount.value + '个样本'
+  } else {
+    dialogTitle.value = '无结果预览'
+  }
+
+  // next_picture()
+}
+const next_picture = async () => {
+  if (imageIdx.value < fileCount.value - 1) {
+    if (!cacheImages.value[imageIdx.value + 1]) {
+      await loadImageData(taskId.value, imageIdx.value + 1)
+    }
+    imageIdx.value = imageIdx.value + 1
+  }
+  dialogTitle.value = '预览: 第' + (imageIdx.value + 1) + '个样本 共' + fileCount.value + '个样本'
+}
+const pre_picture = async () => {
+  if (imageIdx.value > 0) {
+    if (!cacheImages.value[imageIdx.value - 1]) {
+      await loadImageData(taskId.value, imageIdx.value - 1)
+    }
+    imageIdx.value = imageIdx.value - 1
+  }
+  dialogTitle.value = '预览: 第' + (imageIdx.value + 1) + '个样本 共' + fileCount.value + '个样本'
+}
 
-const url = 'https://cdn.theguardian.tv/webM/2015/07/20/150716YesMen_synd_768k_vp8.webm'
-//const url = "https://v17.dogevideo.com/vcloud/17/v/20190424/1556036075_818c4125ec9c8cbc7a7a8a7cc1601512/1037/7d515b22c4958598c0fbd1e6290a5ca5.mp4?vkey=B561D3&tkey=17316085819fec852b94&auth_key=1731622981-omcPUa7d7Zy7svg9-1035588803-64c7aed2dc55c2766fcbb126aec1452a"
 //打开指标窗口查看算法指标信息
 const metricDialogVisible = ref(false)
 const metricList = reactive([])
@@ -134,35 +278,37 @@ const openMetricDialog = async (id: string | number) => {
   metricDialogVisible.value = true
 }
 
-const dialogVisible = ref(false)
+// const dialogVisible = ref(false)
 const inputVideoUrl = ref()
 const outputVideoUrl = ref()
-const openResultDialog = async (id: string | number) => {
-  const res: any = await getVideoUrl(id)
-  inputVideoUrl.value = res.data.input
-  outputVideoUrl.value = res.data.output
-  console.log(inputVideoUrl)
-  dialogVisible.value = true
-}
-const imageIdx = ref(0)
+// const openResultDialog = async (id: string | number) => {
+//   const res: any = await getVideoUrl(id)
+//   inputVideoUrl.value = res.data.input
+//   outputVideoUrl.value = res.data.output
+//   //setPlayerOptions(inputVideoUrl.value)
+//   // inputVideoUrl.value = '/api/public/video/input/' + id
+//   // outputVideoUrl.value = '/api/public/video/output/' + id
+//   console.log(inputVideoUrl)
+//   dialogVisible.value = true
+// }
 
 const taskType = ref([])
 const modelType = ref([
   {
-    label: 'yolov8_best',
-    value: 'yolov8_best'
+    label: 'yolov8_best.pt',
+    value: 'yolov8_best.pt'
   },
   {
-    label: 'yolov8_best_new',
-    value: 'yolov8_best_new'
+    label: 'yolov8_best_new.pt',
+    value: 'yolov8_best_new.pt'
   },
   {
-    label: 'yolov8__best',
-    value: 'yolov8__best'
+    label: 'yolov8__best.pt',
+    value: 'yolov8__best.pt'
   },
   {
-    label: 'yolov8__best_new',
-    value: 'yolov8__best_new'
+    label: 'yolov8__best_new.pt',
+    value: 'yolov8__best_new.pt'
   }
 ])
 const trackingMethod = ref([
@@ -524,17 +670,64 @@ const addParams = (params, task_Type) => {
     const obj: { [key: string]: number } = JSON.parse(validJsonString)
     Object.keys(obj).forEach(key => {
       model.value[key] = obj[key]
-
-      itemsOptions.push({
-        label: key,
-        prop: key,
-        rules: [{ trigger: 'blur' }],
-        compOptions: {
-          type: 'input',
-          clearable: true,
-          placeholder: '默认值为' + obj[key]
-        }
-      })
+      if (key === 'conf' || key === 'iou') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                if (!value) {
+                  return callback(new Error('请输入一个0到1之间的浮点数'))
+                }
+                const regex = /^(0(\.\d+)?|1(\.0+)?)$/
+                if (!regex.test(value)) {
+                  return callback(new Error('请输入一个0到1之间的浮点数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      } else if (key === 'imgsz') {
+        itemsOptions.push({
+          label: key,
+          prop: key,
+          rules: [
+            {
+              trigger: 'change',
+              validator: (rule, value, callback) => {
+                //console.log(value)
+                if (value === '' || value === undefined) {
+                  return callback()
+                }
+                if (!value) {
+                  return callback(new Error('请输入一个大于0的整数'))
+                }
+                const regex = /^[1-9]\d*$/
+                if (!regex.test(value)) {
+                  return callback(new Error('请输入一个大于0的整数'))
+                }
+                callback()
+              }
+            }
+          ],
+          compOptions: {
+            type: 'input',
+            clearable: true,
+            placeholder: '默认值为' + obj[key]
+          }
+        })
+      }
     })
   } catch (error) {
     console.error('解析 JSON 字符串时出错:', error)

+ 12 - 0
yarn.lock

@@ -1967,6 +1967,11 @@
     "@uppy/utils" "^4.1.2"
     nanoid "^3.1.25"
 
+"@videojs-player/vue@1.x":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@videojs-player/vue/-/vue-1.0.0.tgz#df7db677b43b2d9b6872e71cd0eb2238cc19a8fd"
+  integrity sha512-WonTezRfKu3fYdQLt/ta+nuKH6gMZUv8l40Jke/j4Lae7IqeO/+lLAmBnh3ni88bwR+vkFXIlZ2Ci7VKInIYJg==
+
 "@vitejs/plugin-vue-jsx@^3.1.0":
   version "3.1.0"
   resolved "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-3.1.0.tgz#9953fd9456539e1f0f253bf0fcd1289e66c67cd1"
@@ -8352,6 +8357,13 @@ vue-types@^5.1.1:
   dependencies:
     is-plain-object "5.0.0"
 
+vue-video-player@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/vue-video-player/-/vue-video-player-6.0.0.tgz#fc51581b4b0437e5efd7e30388f18d900e27573d"
+  integrity sha512-WP47OtefsjMEReRCIKIL3tRRgH/PyNm8ELjsbYgr/WWrYAj5Ih9Adzkzp+ylYOI/v57jJ4O7O4XkbXBCmsTqNw==
+  dependencies:
+    "@videojs-player/vue" "1.x"
+
 vue@3.3.13:
   version "3.3.13"
   resolved "https://registry.npmmirror.com/vue/-/vue-3.3.13.tgz#f03098fa1b4e7cc88c133bef92260b55e3767002"