Эх сурвалжийг харах

Merge branch 'dev_wk' into develop

WANGKANG 9 сар өмнө
parent
commit
fe19736a2b

+ 6 - 3
src/api/modules/demo/videoStable.ts

@@ -1,5 +1,4 @@
 import http from '@/api'
-// @ts-expect-error
 import { VideoStableVO, VideoStableForm, VideoStableQuery } from '@/api/interface/demo/videoStable'
 
 /**
@@ -75,6 +74,10 @@ export const startVideoStableApi = (id: String | Number) => {
   return http.get('/demo/videoStable/start/' + id)
 }
 
-export const getCompareImageApi = (taskName: String, idx: String | Number) => {
-  return http.get('/demo/videoStable/compare/' + taskName + '/' + idx)
+export const getCompareImageApi = (taskId: String, idx: String | Number) => {
+  return http.get('/demo/videoStable/compare/' + taskId + '/' + idx)
+}
+
+export const getCompareImageCountApi = (taskId: String | Number) => {
+  return http.get('/demo/videoStable/compare/num/' + taskId)
 }

+ 2 - 12
src/components/FormDialog/index.vue

@@ -13,9 +13,6 @@
         <FileUpload :file-size="4096" :file-type="['pt']" />
       </template>
     </ProFrom>
-    <div class="upload-video-box" v-if="parameter.showVideoUpload">
-      <FileUpload ref="videoUploadRef" :limit="1" :file-size="4096" :file-type="['mp4', 'avi', 'rmvb', 'mov', 'wmv', 'flv']" />
-    </div>
     <template #footer>
       <span class="dialog-footer">
         <el-button type="primary" v-if="parameter.isEdit" :loading="butLoading" @click="handleSubmit">确认</el-button>
@@ -44,7 +41,6 @@ export interface FormParameterProps {
   itemsOptions: ProForm.ItemsOptions[] // 动态表单字段配置
   model?: Record<ProForm.FormItem['prop'], ProForm.FormItem['value']> // 表单数据对象
   getTableList?: () => void // 获取表格数据的Api
-  showVideoUpload: boolean // 是否显示视频上传
 }
 
 // dialog状态
@@ -57,8 +53,7 @@ const parameter = ref<FormParameterProps>({
   top: '10vh',
   itemsOptions: [],
   formOptions: {},
-  isEdit: true,
-  showVideoUpload: false
+  isEdit: true
 })
 const _options: ComputedRef<ProForm.FormOptions> = computed(() => {
   const form = {
@@ -74,16 +69,11 @@ const handleSubmit = () => {
   const formEl = proFormRef.value?.proFormRef
   const formModel = proFormRef.value?.formModel
 
-  let urlModel = {}
-  if (parameter.value.showVideoUpload) {
-    console.log(videoUploadRef.value.uploadFileListExport)
-    urlModel = { url: videoUploadRef.value?.uploadFileListExport[0].url }
-  }
   butLoading.value = true
   if (!formEl) return
   formEl.validate(valid => {
     if (valid) {
-      parameter.value.api!({ ...formModel, ...parameter.value.model, ...urlModel }).then(res => {
+      parameter.value.api!({ ...formModel, ...parameter.value.model }).then(res => {
         if (res.code == 200) {
           proFormRef.value?.resetForm(formEl)
           ElMessage.success('操作成功')

+ 7 - 2
src/components/ProForm/index.vue

@@ -25,11 +25,16 @@
               <SelectIcon v-model:icon-value="formModel[item.prop]" />
             </template>
             <template v-else-if="item.compOptions.elTagName === 'file-upload'">
-              <FileUpload v-model:model-value="formModel[item.prop]" v-bind="$attrs" />
+              <FileUpload
+                v-model:model-value="formModel[item.prop]"
+                :file-size="item.compOptions.fileSize"
+                :file-type="item.compOptions.fileType"
+                v-bind="$attrs"
+              />
             </template>
             <template v-else-if="item.compOptions.elTagName === 'img-upload'">
               <uploadImg v-model:image-url="formModel[item.prop]" />
-<!--              <el-button @click="() => {console.log(formModel[item.prop])}"/>-->
+              <!--              <el-button @click="() => {console.log(formModel[item.prop])}"/>-->
             </template>
 
             <template v-else-if="item.compOptions.elTagName === 'imgs-upload'">

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

@@ -65,7 +65,7 @@ interface UploadFileProps {
   text?: string // 按钮文字
   icon?: string
   fileType?: Array<string>
-  uploadApiPath: string // 上传文件服务器地址
+  uploadApiPath?: string // 上传文件服务器地址
 }
 
 // 默认值

+ 2 - 0
src/typings/ProForm.d.ts

@@ -101,6 +101,8 @@ declare namespace ProForm {
     multiple?: boolean
     disabled?: boolean
     elTagName?: ElTagName
+    fileSize?: number // 文件大小
+    fileType?: string[] // 文件类型
     type?: string
     rangeSeparator?: string // 时间范围分隔符
     startPlaceholder?: string // 开始时间Placeholder

+ 20 - 8
src/views/demo/video2image/index.vue

@@ -85,6 +85,7 @@ const startVideo2image = async (params: any) => {
   } else {
     ElMessage.error('开始视频转图片开始失败,请检查!')
   }
+  proTable.value?.getTableList()
 }
 
 const dowloadVideo2image = async (params: any) => {
@@ -277,14 +278,6 @@ const setItemsOptions = () => {
         placeholder: '请输入视频名称'
       }
     },
-    {
-      label: '备注',
-      prop: 'remarks',
-      rules: [{ required: true, message: '备注不能为空', trigger: 'blur' }],
-      compOptions: {
-        placeholder: '请输入备注'
-      }
-    },
     {
       label: '切割帧率',
       prop: 'fps',
@@ -302,6 +295,25 @@ const setItemsOptions = () => {
         type: 'number',
         placeholder: '请输入切割帧率,范围:1-60'
       }
+    },
+    {
+      label: '上传视频',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '视频不能为空', trigger: 'blur' }],
+      compOptions: {
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['mp4', 'avi', 'rmvb', 'mov', 'wmv', 'flv'],
+        placeholder: '请上传视频文件'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
+      compOptions: {
+        placeholder: '请输入备注'
+      }
     }
   ]
 }

+ 176 - 93
src/views/demo/videoStable/index.vue

@@ -4,8 +4,8 @@
       <!-- 表格 header 按钮 -->
       <template #tableHeader="scope">
         <el-button type="primary" v-auth="['demo:videoStable:add']" icon="CirclePlus" @click="openDialog(1, '视频去抖动新增')"> 新增 </el-button>
-        <el-button type="primary" v-auth="['demo:videoStable:import']" icon="Upload" plain @click="batchAdd"> 导入</el-button>
-        <el-button type="primary" v-auth="['demo:videoStable:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>
+        <!--        <el-button type="primary" v-auth="['demo:videoStable:import']" icon="Upload" plain @click="batchAdd"> 导入</el-button>-->
+        <!--        <el-button type="primary" v-auth="['demo:videoStable:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>-->
         <el-button
           type="danger"
           v-auth="['demo:videoStable:remove']"
@@ -32,14 +32,25 @@
     </ProTable>
     <FormDialog ref="formDialogRef" />
     <ImportExcel ref="dialogRef" />
-    <el-dialog v-model="dialogVisible" :title="'图片对比: ' + taskName + '第' + imageIdx + '张图片对比'" width="80%">
-      <div class="image-dialog">
-        <el-image :src="'data:image/png;base64,' + imageBase64List.origin" style="width: 45%"></el-image>
-        <el-image :src="'data:image/png;base64,' + imageBase64List.stable" style="width: 45%"></el-image>
+    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
+      <el-form>
+        <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-option label="60" value="60"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div class="image-dialog" v-if="imageIdx > 0">
+        <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].origin" style="width: 45%"></el-image>
+        <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].stable" style="width: 45%"></el-image>
       </div>
-      <div class="image-dialog-btn">
-        <el-button type="primary" @click="pre_picture" :disabled="imageIdx === 1">上一个</el-button>
-        <el-button type="primary" @click="next_picture">下一个</el-button>
+      <div class="image-dialog-btn" v-if="imageFps == 0">
+        <el-button type="primary" @click="pre_picture" :disabled="imageIdx <= 1">上一个</el-button>
+        <el-button type="primary" @click="next_picture" :disabled="imageIdx >= fileCount">下一个</el-button>
       </div>
     </el-dialog>
   </div>
@@ -64,16 +75,40 @@ import {
   exportVideoStableApi,
   getVideoStableApi,
   startVideoStableApi,
-  getCompareImageApi
+  getCompareImageApi,
+  getCompareImageCountApi
 } from '@/api/modules/demo/videoStable'
 
 const dialogVisible = ref(false)
-const taskName = ref('')
-const imageIdx = ref(1)
+const taskId = ref('')
+const imageIdx = ref(0)
 const imageBase64List = ref({
   origin: '',
   stable: ''
 })
+const inFileCount = ref(0)
+const outFileCount = ref(0)
+// 直接缓存所有图片
+const cacheImages = ref({ 0: { origin: '', stable: '' } })
+const dialogTitle = ref('')
+const fileCount = ref(0)
+const imageFps = ref(0)
+const intervalChangeFps: any = ref()
+
+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 startVideoStable = async (params: any) => {
   const res = await startVideoStableApi(params.id)
@@ -85,27 +120,57 @@ const startVideoStable = async (params: any) => {
   proTable.value?.getTableList()
 }
 
-const loadImageData = async (taskName: string, imageIdx: number) => {
-  const res: any = await getCompareImageApi(taskName, imageIdx)
+const loadImageData = async (taskId: string, imageIdx: number) => {
+  const res: any = await getCompareImageApi(taskId, imageIdx)
   imageBase64List.value.origin = res.origin
   imageBase64List.value.stable = res.stable
 }
 const compareVideoStable = async (params: any) => {
-  taskName.value = params.name
-  imageIdx.value = 1
-  await loadImageData(taskName.value, imageIdx.value)
+  taskId.value = params.id
+  imageIdx.value = 0
 
+  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)
+  for (let idx = 1; idx <= fileCount.value; idx++) {
+    dialogTitle.value = '缓存图片中: 第' + idx + '张图片 共' + fileCount.value + '张图片'
+    if (cacheImages.value[idx]) {
+      continue
+    }
+    const res: any = await getCompareImageApi(taskId.value, idx)
+    cacheImages.value[idx] = {
+      origin: res.origin,
+      stable: res.stable
+    }
+  }
+  next_picture()
 }
 const next_picture = async () => {
-  imageIdx.value = imageIdx.value + 1
-  await loadImageData(taskName.value, imageIdx.value)
+  if (imageIdx.value < fileCount.value) {
+    if (!cacheImages.value[imageIdx.value + 1]) {
+      await loadImageData(taskId.value, imageIdx.value + 1)
+    }
+    imageIdx.value = imageIdx.value + 1
+  }
+  dialogTitle.value = '图片对比: 第' + imageIdx.value + '张图片 共' + fileCount.value + '张图片'
 }
 const pre_picture = async () => {
   if (imageIdx.value > 1) {
+    if (!cacheImages.value[imageIdx.value - 1]) {
+      await loadImageData(taskId.value, imageIdx.value - 1)
+    }
     imageIdx.value = imageIdx.value - 1
-    await loadImageData(taskName.value, imageIdx.value)
   }
+  dialogTitle.value = '图片对比: 第' + imageIdx.value + '张图片 共' + fileCount.value + '张图片'
 }
 
 // ProTable 实例
@@ -212,22 +277,6 @@ const columns = reactive<ColumnProps<any>[]>([
     tag: true,
     enum: statusEnums
   },
-  {
-    prop: 'inPath',
-    label: '输入图片集路径',
-    search: {
-      el: 'input'
-    },
-    width: 120
-  },
-  {
-    prop: 'outPath',
-    label: '去抖动的图片集路径',
-    search: {
-      el: 'input'
-    },
-    width: 120
-  },
   {
     prop: 'startTime',
     label: '开始时间',
@@ -268,6 +317,56 @@ const columns = reactive<ColumnProps<any>[]>([
     },
     width: 120
   },
+
+  {
+    prop: 'block_size',
+    label: 'block_size',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'radius',
+    label: 'radius',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'cornerquality',
+    label: 'cornerquality',
+    search: {
+      el: 'input'
+    },
+    width: 130
+  },
+  {
+    prop: 'cornerminDistance',
+    label: 'cornerminDistance',
+    search: {
+      el: 'input'
+    },
+    width: 180
+  },
+  {
+    prop: 'lklevel',
+    label: 'lklevel',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+  {
+    prop: 'lkwinSiz',
+    label: 'lkwinSiz',
+    search: {
+      el: 'input'
+    },
+    width: 120
+  },
+
   {
     prop: 'remarks',
     label: '备注',
@@ -296,114 +395,98 @@ const setItemsOptions = () => {
       }
     },
     {
-      label: '输入路径',
-      prop: 'inPath',
-      rules: [{ required: true, message: '输入图片集路径不能为空', trigger: 'blur' }],
-      compOptions: {
-        type: 'block_size',
-        clearable: true,
-        placeholder: '请输入内容'
-      }
-    },
-    {
-      label: '输出路径',
-      prop: 'outPath',
-      rules: [{ required: true, message: '去抖动的图片集路径不能为空', trigger: 'blur' }],
-      compOptions: {
-        type: 'block_size',
-        clearable: true,
-        placeholder: '请输入内容'
-      }
-    },
-    {
-      label: '备注',
-      prop: 'remarks',
-      rules: [
-        {
-          required: false,
-          message: '备注不能为空',
-          trigger: 'blur'
-        }
-      ],
+      label: '图片集压缩包',
+      prop: 'inputOssId',
+      rules: [{ required: false, message: '图片集压缩包不能为空', trigger: 'blur' }],
       compOptions: {
-        placeholder: '请输入备注'
+        elTagName: 'file-upload',
+        fileSize: 4096,
+        fileType: ['zip'],
+        placeholder: '请上传图片集压缩包'
       }
     },
     {
       label: 'block_size',
       prop: 'block_size',
-      rules: [{ required: true, message: 'block_size不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'block_size不能为空', trigger: 'blur' }],
       compOptions: {
         type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 50
+        placeholder: '默认50'
       }
     },
     {
       label: 'radius',
       prop: 'radius',
-      rules: [{ required: true, message: 'radius不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'radius不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 500
+        placeholder: '默认500'
       }
     },
     {
       label: 'buffer_size',
       prop: 'buffer_size',
-      rules: [{ required: true, message: 'buffer_size不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'buffer_size不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 200
+        placeholder: '默认200'
       }
     },
     {
       label: 'cornerquality',
       prop: 'cornerquality',
-      rules: [{ required: true, message: 'cornerquality不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'cornerquality不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 0.2
+        placeholder: '默认0.2'
       }
     },
     {
       label: 'cornerminDistance',
       prop: 'cornerminDistance',
-      rules: [{ required: true, message: 'cornerminDistance不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'cornerminDistance不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 5
+        placeholder: '默认5'
       }
     },
     {
       label: 'lklevel',
       prop: 'lklevel',
-      rules: [{ required: true, message: 'lklevel不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'lklevel不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 3
+        placeholder: '默认3'
       }
     },
     {
       label: 'lkwinSiz',
       prop: 'lkwinSiz',
-      rules: [{ required: true, message: 'lkwinSiz不能为空', trigger: 'blur' }],
+      rules: [{ required: false, message: 'lkwinSiz不能为空', trigger: 'blur' }],
       compOptions: {
-        type: 'block_size',
+        type: 'input',
         clearable: true,
-        placeholder: '请输入内容',
-        value: 15
+        placeholder: '默认15'
+      }
+    },
+    {
+      label: '备注',
+      prop: 'remarks',
+      rules: [
+        {
+          required: false,
+          message: '备注不能为空',
+          trigger: 'blur'
+        }
+      ],
+      compOptions: {
+        placeholder: '请输入备注'
       }
     }
   ]