214 lines
5.7 KiB
Vue
214 lines
5.7 KiB
Vue
<script setup lang="ts">
|
||
import type { FormInstance, FormRules } from 'element-plus'
|
||
import { onMounted, reactive, ref } from 'vue'
|
||
|
||
import { useRouter } from 'vue-router'
|
||
import { runApi, runApiAudio } from '~/composables/api'
|
||
|
||
const router = useRouter()
|
||
|
||
const runCheckBtnRef = ref()
|
||
const isRunningCheck = ref(false)
|
||
const vidPaths = ref<string[]>([])
|
||
|
||
interface RuleForm {
|
||
vidPath: string
|
||
function: string[]
|
||
}
|
||
const ruleFormRef = ref<FormInstance>()
|
||
const ruleForm = reactive<RuleForm>({
|
||
vidPath: '',
|
||
function: [
|
||
// 'runSam3',
|
||
// 'runHazardCheck',
|
||
// 'runGenerateReport',
|
||
// 'runAudioRecognition',
|
||
],
|
||
})
|
||
|
||
const timerDisplay = ref('00:00:00')
|
||
let timerInterval: ReturnType<typeof setInterval> | null = null
|
||
let startTime: number = 0
|
||
|
||
function startTimer() {
|
||
startTime = Date.now()
|
||
timerInterval = setInterval(() => {
|
||
const elapsed = Date.now() - startTime
|
||
const hours = Math.floor(elapsed / 3600000)
|
||
const minutes = Math.floor((elapsed % 3600000) / 60000)
|
||
const seconds = Math.floor((elapsed % 60000) / 1000)
|
||
timerDisplay.value = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
|
||
}, 1000)
|
||
}
|
||
|
||
function stopTimer() {
|
||
if (timerInterval) {
|
||
clearInterval(timerInterval)
|
||
timerInterval = null
|
||
}
|
||
}
|
||
|
||
const rules = reactive<FormRules<RuleForm>>({
|
||
vidPath: [
|
||
{
|
||
type: 'string',
|
||
required: true,
|
||
message: '请选择视频',
|
||
trigger: 'change',
|
||
},
|
||
],
|
||
})
|
||
|
||
async function runCheck(formEl: FormInstance | undefined) {
|
||
if (!formEl)
|
||
return
|
||
const valid = await formEl.validate((valid, fields) => {
|
||
if (valid) {
|
||
// console.log('submit!', ruleForm)
|
||
}
|
||
else {
|
||
console.error('error submit!', fields)
|
||
}
|
||
})
|
||
if (valid) {
|
||
isRunningCheck.value = true
|
||
startTimer()
|
||
if (ruleForm.function.includes('runAudioRecognition')) {
|
||
await runApiAudio('recognize', 'POST', {
|
||
path: vidPaths.value[vidPaths.value.indexOf(ruleForm.vidPath)],
|
||
})
|
||
}
|
||
await runApi('/run', {
|
||
vid_file: vidPaths.value[vidPaths.value.indexOf(ruleForm.vidPath)],
|
||
run_sam3: ruleForm.function.includes('runSam3'),
|
||
run_inspection: ruleForm.function.includes('runHazardCheck'),
|
||
gen_report: ruleForm.function.includes('runGenerateReport'),
|
||
}).then((res) => {
|
||
isRunningCheck.value = false
|
||
stopTimer()
|
||
// 判定是否成功运行
|
||
if (res !== 'error') {
|
||
router.push({
|
||
path: '/nav/hazardCheckResult',
|
||
query: { vid_file: vidPaths.value[vidPaths.value.indexOf(ruleForm.vidPath)] },
|
||
})
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
async function reloadFiles() {
|
||
await runApi('/reload_files', {}).then((res) => {
|
||
for (const item of (res as any)[0].choices) {
|
||
vidPaths.value.push(item[0])
|
||
}
|
||
})
|
||
}
|
||
|
||
function resetForm(formEl: FormInstance | undefined) {
|
||
if (!formEl)
|
||
return
|
||
formEl.resetFields()
|
||
}
|
||
|
||
async function goToResult(formEl: FormInstance | undefined) {
|
||
if (!formEl)
|
||
return
|
||
await formEl.validate((valid, fields) => {
|
||
if (valid) {
|
||
// console.log('跳转结果页')
|
||
router.push({
|
||
path: '/nav/hazardCheckResult',
|
||
query: { vid_file: ruleForm.vidPath },
|
||
})
|
||
}
|
||
else {
|
||
console.error('error submit!', fields)
|
||
}
|
||
})
|
||
}
|
||
|
||
onMounted(() => {
|
||
reloadFiles()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<!-- 最外层容器:占满整个视口 -->
|
||
<el-container style="margin: 0; height: 100%; flex-direction: column;">
|
||
<!-- 内层容器:自动填充剩余高度 -->
|
||
<el-main class="main" style="flex: 1; min-height: 0;">
|
||
<div class="flex flex-col items-center justify-center pt-30">
|
||
<el-form
|
||
ref="ruleFormRef"
|
||
style="max-width: 600px"
|
||
:model="ruleForm"
|
||
:rules="rules"
|
||
label-width="auto"
|
||
>
|
||
<el-form-item label="视频" prop="vidPath">
|
||
<el-select v-model="ruleForm.vidPath" placeholder="视频">
|
||
<el-option v-for="item in vidPaths" :key="item" :label="item" :value="item" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="功能选择" prop="function">
|
||
<el-checkbox-group v-model="ruleForm.function" class="checkbox-group">
|
||
<el-checkbox value="runSam3" name="function">
|
||
物体识别
|
||
</el-checkbox>
|
||
<el-checkbox value="runHazardCheck" name="function">
|
||
隐患检查
|
||
</el-checkbox>
|
||
<el-checkbox value="runGenerateReport" name="function">
|
||
生成报告
|
||
</el-checkbox>
|
||
<el-checkbox value="runAudioRecognition" name="function">
|
||
音频识别
|
||
</el-checkbox>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
<el-form-item v-if="!isRunningCheck">
|
||
<el-button @click="resetForm(ruleFormRef)">
|
||
重置表单
|
||
</el-button>
|
||
<el-button @click="goToResult(ruleFormRef)">
|
||
查看结果
|
||
</el-button>
|
||
<el-button
|
||
ref="runCheckBtnRef"
|
||
type="primary"
|
||
:loading="isRunningCheck"
|
||
@click="runCheck(ruleFormRef)"
|
||
>
|
||
运行检查
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
<el-progress
|
||
v-if="isRunningCheck"
|
||
:percentage="50"
|
||
:indeterminate="true"
|
||
style="width: 100%;"
|
||
>
|
||
<el-text>{{ timerDisplay }}</el-text>
|
||
</el-progress>
|
||
</div>
|
||
</el-main>
|
||
</el-container>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.main {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: start;
|
||
}
|
||
|
||
.checkbox-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16px;
|
||
justify-content: flex-start;
|
||
}
|
||
</style>
|