1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- <template>
- <div class="table-box">
- <ProTable ref="proTable" :columns="columns" row-key="id" :data="bizProcessList">
- <!-- 表格 header 按钮 -->
- <template #tableHeader="scope">
- <!-- <el-button type="primary" v-auth="['identification:identificationSubtaskDetails:add']" icon="CirclePlus" @click="openDialog(1, '算法业务处理新增')"> 新增 </el-button>
- <el-button type="primary" v-auth="['identification:identificationSubtaskDetails:import']" icon="Upload" plain @click="batchAdd"> 导入 </el-button> -->
- <!-- <el-button type="primary" v-auth="['identification:identificationSubtaskDetails:export']" icon="Download" plain @click="downloadFile">-->
- <!-- 导出-->
- <!-- </el-button>-->
- <!-- <el-button-->
- <!-- type="danger"-->
- <!-- v-auth="['identification:identificationSubtaskDetails:remove']"-->
- <!-- icon="Delete"-->
- <!-- plain-->
- <!-- :disabled="!scope.isSelected"-->
- <!-- @click="batchDelete(scope.selectedListIds)"-->
- <!-- >-->
- <!-- 批量删除-->
- <!-- </el-button>-->
- <!-- v-if="!scope.row.name.includes('训练')"-->
- <el-button v-if="listData.length > 0 && !listData[0].name.includes('训练')" type="primary" icon="View" @click="showCompareResult()">
- 验证指标对比
- </el-button>
- <!-- <el-button type="primary" icon="View" @click="showValResult(true)"> 验证结果 </el-button>-->
- <el-button
- v-if="listData.length > 0 && !listData[0].name.includes('训练')"
- type="primary"
- icon="View"
- @click="showValResult(false && scope.row)"
- >
- 测试结果
- </el-button>
- <el-button v-if="listData.length > 0 && !listData[0].name.includes('训练')" type="primary" icon="View" @click="showValResult(true)">
- 验证结果
- </el-button>
- </template>
- <!-- 表格操作 -->
- <template #operation="scope">
- <!-- <el-button-->
- <!-- type="primary"-->
- <!-- link-->
- <!-- icon="View"-->
- <!-- v-auth="['identification:identificationSubtaskDetails:query']"-->
- <!-- @click="openDialog(3, '算法业务处理查看', scope.row)"-->
- <!-- >-->
- <!-- 查看详情-->
- <!-- </el-button>-->
- <el-button
- v-if="scope.row.name.indexOf('训练') === -1 && (scope.row.status === '0' || scope.row.status === '3')"
- type="primary"
- link
- icon="VideoPlay"
- @click="reRunTask(scope.row)"
- >
- 开始任务
- </el-button>
- <el-button
- v-if="scope.row.name.indexOf('训练') !== -1 && (scope.row.status === '0' || scope.row.status === '3')"
- type="primary"
- link
- icon="VideoPlay"
- @click="startTask(scope.row)"
- >
- 开始任务
- </el-button>
- <el-button v-if="scope.row.status === '0'" type="primary" link icon="Refresh" @click="taskExecute('continue', scope.row)">
- 继续任务
- </el-button>
- <el-button v-if="scope.row.status === '1'" type="primary" link icon="Refresh" @click="taskExecute('pause', scope.row)"> 暂停任务 </el-button>
- <el-button v-if="scope.row.status === '1'" type="primary" link icon="Refresh" @click="taskExecute('stop', scope.row)"> 停止任务 </el-button>
- <el-button v-if="!scope.row.name.includes('测试')" type="primary" link icon="finished" @click="showResult(scope.row)"> 结果图 </el-button>
- <el-button v-if="!scope.row.name.includes('训练')" type="primary" link icon="search" @click="showTimeResult(scope.row)"> 查看指标 </el-button>
- <el-button type="primary" link icon="document" v-auth="['identification:identificationSubtaskDetails:query']" @click="viewLog(scope.row)">
- 查看日志
- </el-button>
- <el-button type="primary" link icon="FolderOpened" @click="openDir(scope.row, true)"> 预处理文件夹 </el-button>
- <el-button type="primary" link icon="FolderOpened" @click="openDir(scope.row, false)"> 结果文件夹 </el-button>
- <el-button type="primary" link icon="SoldOut" @click="exportData(scope.row)"> 导出结果 </el-button>
- </template>
- </ProTable>
- <FormDialog ref="formDialogRef" />
- <ImportExcel ref="dialogRef" />
- <el-dialog v-model="dialogVisible" title="日志" width="70%">
- <div class="log" ref="logRef">
- <div class="p" v-for="(item, index) in logInfo" :key="index">{{ item }}</div>
- </div>
- </el-dialog>
- <el-dialog v-model="resultVisible" title="对比结果" width="70%">
- <div v-if="!resultsFlag" class="resultShow">
- <el-row class="headerRow">
- <el-col class="col" :span="spanNum" v-for="(agloName, index) in resultsData['agNameList']" :key="index">
- <span>{{ agloName }}</span>
- </el-col>
- </el-row>
- <el-row class="row">
- <el-col class="col" :span="spanNum" v-for="(RCurveUrl, index) in resultsData['rcureList']" :key="index">
- <div v-if="index === 0" :span="4" class="oneCol">{{ RCurveUrl }}</div>
- <ImagePreview
- class="img"
- v-else
- :width="100"
- :height="100"
- :src="'/api/profile' + RCurveUrl"
- :preview-src-list="['/api/profile' + RCurveUrl]"
- />
- </el-col>
- </el-row>
- <el-row class="row">
- <el-col class="col" :span="spanNum" v-for="(PCurveUrl, index) in resultsData['pcureList']" :key="index">
- <div v-if="index === 0" class="oneCol">{{ PCurveUrl }}</div>
- <ImagePreview
- class="img"
- v-else
- :width="100"
- :height="100"
- :src="'/api/profile' + PCurveUrl"
- :preview-src-list="['/api/profile' + PCurveUrl]"
- />
- </el-col>
- </el-row>
- <el-row class="row">
- <el-col class="col" :span="spanNum" v-for="(F1CurveUrl, index) in resultsData['f1cureList']" :key="index">
- <div v-if="index === 0" class="oneCol">{{ F1CurveUrl }}</div>
- <ImagePreview
- class="img"
- v-else
- :width="100"
- :height="100"
- :src="'/api/profile' + F1CurveUrl"
- :preview-src-list="['/api/profile' + F1CurveUrl]"
- />
- </el-col>
- </el-row>
- </div>
- <div v-if="resultsFlag" class="resultShow">
- <el-row class="headerRow">
- <el-col class="col" :span="spanNum" v-for="(agloName, index) in testResultsData['agNameList']" :key="index">
- <span>{{ agloName }}</span>
- </el-col>
- </el-row>
- <el-row class="row" v-for="(item, index) in testResultsData['resultList']" :key="index">
- <el-col class="col" :span="spanNum" v-for="(url, index1) in item" :key="index1">
- <!-- <span>{{ url }}</span> -->
- <ImagePreview class="img" :width="100" :height="100" :src="'/api/profile' + url" :preview-src-list="['/api/profile' + url]" />
- </el-col>
- </el-row>
- </div>
- </el-dialog>
- <el-dialog v-model="resultDialogVisible" title="执行结果">
- <!-- style="width: 70vw"-->
- <div v-if="refSelectData.name.includes('训练')">
- <div style="padding: 14px">
- <span>Results</span>
- </div>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/loss.png'"></el-image>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/AP50.png'"></el-image>
- </div>
- <div v-else>
- <el-card :body-style="{ padding: '0px' }">
- <div style="padding: 14px">
- <span>P_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/P_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>R_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/R_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>PR_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/PR_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>F1_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + refSelectData.resultPath + '/F1_curve.png'"></el-image>
- </el-card>
- </div>
- </el-dialog>
- <el-dialog v-model="compareDialogVisible" title="验证指标对比">
- <!-- style="width: 70vw"-->
- <el-container style="display: flex; flex-direction: row">
- <el-container v-for="(item, index) in valListData" :key="index" style="display: flex; flex-direction: column">
- <!-- <el-button @click="console.log(item)">test</el-button>-->
- <span style="font-size: 18px"> {{ item.name }} </span>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 3px">
- <div style="padding: 14px">
- <span>P_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + item.resultPath + '/P_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>R_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + item.resultPath + '/R_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>PR_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + item.resultPath + '/PR_curve.png'"></el-image>
- </el-card>
- <el-card :body-style="{ padding: '0px' }" style="margin-top: 10px">
- <div style="padding: 14px">
- <span>F1_curve</span>
- </div>
- <el-image :src="PATH_PREFIX + item.resultPath + '/F1_curve.png'"></el-image>
- </el-card>
- </el-container>
- </el-container>
- </el-dialog>
- <el-dialog v-model="valDialogVisible" :title="titleMsg" style="width: 85vw; height: 85vh; overflow-x: auto">
- <!-- style="width: 70vw"-->
- <el-container style="display: flex; flex-direction: row">
- <el-container v-for="(item, index) in imgDataList" :key="index" style="display: flex; flex-direction: column">
- <!-- <el-button @click="console.log(item)">test</el-button>-->
- <el-container v-for="(_item, _index) in item" :key="_index">
- <span
- v-if="_item.name"
- :style="{
- color: _item.color ? _item.color : '#ffffff',
- width: '80px',
- 'margin-right': '20px'
- }"
- >
- {{ _item.name }}
- </span>
- <el-image v-if="_item.srcUrl" :src="_item.srcUrl" style="width: 200px; height: 200px"></el-image>
- <span v-if="_item.imgUrl">标签</span>
- <ImgMaker
- :canvas-id="_item.name + '_' + _index"
- style="width: 200px; height: 200px"
- ref="imgMaker"
- v-if="_item.imgUrl"
- :is-pic-only="true"
- :src="_item.imgUrl"
- :width="200"
- :height="200"
- :c-width="200"
- :c-height="200"
- :class-def="typeDefs"
- :json-data="_item.jsonData"
- ></ImgMaker>
- <el-image v-if="_item.resUrl" :src="_item.resUrl" style="width: 200px; height: 200px"></el-image>
- </el-container>
- </el-container>
- </el-container>
- </el-dialog>
- <ResultDialog ref="ResultDialogRef" />
- </div>
- </template>
- <script setup lang="tsx" name="BizProcess">
- import { ref, reactive, onMounted, onUnmounted, watch, nextTick } from 'vue'
- import { useHandleData } from '@/hooks/useHandleData'
- import { useDownload } from '@/hooks/useDownload'
- import { ElMessageBox, ElMessage } 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 ImgMaker from '../../demo/components/img-maker'
- import {
- listBizProcessApi,
- delBizProcessApi,
- addBizProcessApi,
- updateBizProcessApi,
- exportBizProcessApi,
- getBizProcessApi,
- getTrainResultApi,
- getVerifyResultApi,
- getTestResultApi,
- getImgList
- } from '@/api/modules/task/bizProcessNew'
- // getTrainResultApi,getVerifyResultApi,getTestResultApi
- import { getSubtaskApi } from '@/api/modules/task/subtask'
- import { getDictsApi, listDataApi as listDictDataApi } from '@/api/modules/system/dictData'
- import { useRoute } from 'vue-router'
- import ImagePreview from '@/components/ImagePreview/index.vue'
- import http from '@/api'
- import ResultDialog from '@/components/ResultDialog/ResultDialog.vue'
- const ResultDialogRef = ref<InstanceType<typeof ResultDialog> | null>(null)
- const showTimeResult = async function (row) {
- let path = row.resultPath.split('ObjectDetection_Web')
- path = path[path.length - 1]
- let result = await http.get('/profile/task/' + path + '/result.json')
- ResultDialogRef.value.openDialog(result)
- }
- const route = useRoute()
- const PATH_PREFIX = 'api/profile/task'
- let resultDialogVisible = ref(false)
- let refSelectData = ref(reactive({}))
- const reRunTask = row => {
- http.post<any>('/identification/identificationSubtaskDetails/execute', { taskId: row.id }, { loading: true }).then(res => {
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- } else {
- ElMessage.success('启动成功')
- }
- })
- }
- const startTask = row => {
- http.post<any>('/identification/identificationSubtaskDetails/startTask', { taskId: row.id }, { loading: true }).then(res => {
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- } else {
- ElMessage.success('启动成功')
- }
- })
- }
- const taskExecute = (type, row) => {
- http
- .post<any>(
- '/identification/identificationSubtaskDetails/' + (type === 'continue' ? 'continueTask' : type === 'pause' ? 'pauseTask' : 'stopTask'),
- { bizId: row.id },
- { loading: true }
- )
- .then(res => {
- if (res.code !== 200) {
- ElMessage.error(res.msg)
- } else {
- ElMessage.success('操作成功')
- }
- })
- }
- const typeDefs = ref(reactive([]))
- const exportData = row => {
- http.get<any>('/identification/identificationSubtaskDetails/resultZip', { taskId: row.id }, { loading: true }).then(res => {
- console.log(res)
- if (res.code === 200) {
- window.open(res.msg, '_blank')
- // http.get<any>('/identification/identificationSubtaskDetails/openDir', { directory: row.resultPath + "/weights" }, { loading: true }).then(res => {
- // console.log(res)
- // })
- }
- })
- }
- const openDir = (row, isPre) => {
- console.log(row)
- http
- .get<any>(
- '/identification/identificationSubtaskDetails/openDir',
- { directory: isPre ? row.preprocessPath : row.resultPath, type: '2' },
- { loading: true }
- )
- .then(res => {
- console.log(res)
- })
- }
- let imgDataList = ref(reactive([]))
- let titleMsg = ref('')
- let valDialogVisible = ref(false)
- const showValResult = async isVal => {
- let hasInit = false
- titleMsg.value = isVal ? '验证结果对比' : '测试结果对比'
- imgDataList.value = reactive([])
- let _selectedData = ref(proTable.value.selectedList)
- if (_selectedData.value.filter(data => data.name.indexOf(isVal ? '验证' : '测试') !== -1).length === 0) {
- // ElMessage.error('请选择' + (isVal ? '验证' : '测试') + '任务')
- // return
- _selectedData.value = listData.value
- }
- for (let i = 0; i < _selectedData.value.length; i++) {
- if (_selectedData.value[i].name.indexOf(isVal ? '验证' : '测试') !== -1) {
- console.log(_selectedData.value[i])
- if (!hasInit) {
- hasInit = true
- let res = await getImgList({
- taskId: _selectedData.value[i].preprocessPath.substring(1).split('/')[0],
- subPath: 'images'
- })
- console.log('res data', res)
- imgDataList.value.push([])
- for (let j = 0; j < res.data.length; j++) {
- let jList = res.data[j].split('.')
- jList[jList.length - 1] = 'txt'
- let obj = {
- name: res.data[j],
- srcUrl: 'api/profile/task' + _selectedData.value[i].preprocessPath + (isVal ? '/images/' : '/') + res.data[j]
- // imgUrl: 'api/profile/task' + _selectedData.value[i].preprocessPath + '/images/' + res.data[j],
- // labelUrl: 'api/profile/task' + _selectedData.value[i].preprocessPath + '/labels/' + jList.join('.')
- }
- imgDataList.value[imgDataList.value.length - 1].push(obj)
- if (isVal) {
- obj.imgUrl = 'api/profile/task' + _selectedData.value[i].preprocessPath + '/images/' + res.data[j]
- obj.labelUrl = '/profile/task' + _selectedData.value[i].preprocessPath + '/labels/' + jList.join('.')
- console.log('url is', obj.labelUrl)
- setDetail(obj)
- }
- }
- }
- let res = await getImgList({
- taskId: _selectedData.value[i].preprocessPath.substring(1).split('/')[0],
- subPath: 'images'
- })
- console.log(res.data)
- if (isVal) {
- await loadVerifyResult(_selectedData.value[i].name, '/profile/task' + _selectedData.value[i].preprocessPath + '/result/verify_result.txt')
- }
- console.log('load result', verifyResult.value)
- imgDataList.value.push([])
- for (let j = 0; j < res.data.length; j++) {
- console.log('temp log', verifyResult.value)
- let jList = res.data[j].split('.')
- jList[jList - 1] = 'txt'
- imgDataList.value[imgDataList.value.length - 1].push({
- resUrl: 'api/profile/task' + _selectedData.value[i].resultPath + '/' + res.data[j],
- name: _selectedData.value[i].name,
- picName: res.data[j],
- color: verifyResult.value[res.data[j]] ? '#00ff00' : '#ff0000'
- })
- }
- }
- }
- console.log('datalist', imgDataList)
- valDialogVisible.value = true
- }
- const verifyResult = ref({})
- const loadVerifyResult = async (name, filepath) => {
- // console.log('filepath', filepath)
- try {
- verifyResult.value = {}
- let res = await http.get(filepath)
- console.log(res)
- // verifyResult.value[name] = {}
- let arr = res.replace('\r', '').split('\n')
- arr.forEach(str => {
- let vals = str.split(' ')
- verifyResult.value[vals[0]] = vals[1] === '1'
- })
- console.log('verifyResult', verifyResult.value)
- } catch (e) {
- verifyResult.value = {}
- }
- }
- import { xywh2fourNodes } from '../../demo/data/reformat'
- const setDetail = obj => {
- http.get<any>(obj.labelUrl).then(res => {
- obj.jsonData = []
- // console.log('result', res)
- res = xywh2fourNodes(res)
- let arr = res.replace('\r', '').split('\n')
- // console.log(arr)
- for (let i = 0; i < arr.length; i++) {
- let subArr = arr[i].split(' ')
- // console.log(subArr)
- let cssVal = '#000000'
- let label = '-1'
- for (let j = 0; j < typeDefs.value.length; j++) {
- if (typeDefs.value[j].label === subArr[0]) {
- cssVal = typeDefs.value[j].color
- label = typeDefs.value[j].label
- break
- }
- }
- const ww = 200
- const hh = 200
- obj.jsonData.push({
- subArr: subArr,
- pathString:
- 'M ' +
- subArr[1] * ww +
- ' ' +
- subArr[2] * hh +
- ' L ' +
- subArr[3] * ww +
- ' ' +
- subArr[4] * hh +
- ' L ' +
- subArr[5] * ww +
- ' ' +
- subArr[6] * hh +
- ' L ' +
- subArr[7] * ww +
- ' ' +
- subArr[8] * hh +
- ' z',
- // left: 0,
- // top: 0,
- fill: '',
- stroke: cssVal,
- strokeWidth: 5,
- label: label
- })
- }
- })
- }
- let compareDialogVisible = ref(false)
- const valListData = ref([])
- let listData = ref(reactive([]))
- const showCompareResult = () => {
- // console.log(listData.value)
- let _data = ref(proTable.value.selectedList)
- if (_data.value.filter(data => data.name.indexOf('验证') !== -1).length === 0) {
- _data.value = listData.value
- }
- valListData.value = _data.value.filter(item => {
- return item.name.includes('验证')
- })
- compareDialogVisible.value = true
- // console.log('vallist', valListData.value)
- }
- const showResult = row => {
- refSelectData.value = reactive(row)
- resultDialogVisible.value = true
- console.log(row)
- }
- const subTaskId = route.query.id as string
- // ProTable 实例
- const proTable = ref<ProTableInstance>()
- const dialogVisible = ref(false)
- const resultVisible = ref(false)
- let resultsData = ref({})
- let testResultsData = ref({})
- let resultsFlag = ref(false)
- let spanNum = ref<number>(4)
- // let logList = ref()
- const logRef = ref<HTMLElement | null>(null) // 显式声明 logRef 的类型;
- let logInfo = ref([] as any[])
- let taskType = ref()
- let taskStatus = ref()
- let bizProcessList = ref()
- // 每隔10秒请求一下列表
- const timer = ref() // 定时器
- const refreshList = () => {
- setTimeout(() => {
- listBizProcessApi({
- pageNum: 1,
- pageSize: 100,
- subtaskId: subTaskId
- }).then(res => {
- bizProcessList.value = res.data['list'].sort((a, b) => b.index - a.index)
- listData.value = reactive(res.data['list'].sort((a, b) => b.index - a.index))
- })
- }, 0)
- }
- onMounted(() => {
- listDictDataApi({
- pageNum: 1,
- pageSize: 10,
- dictType: 'class_definition'
- }).then(res => {
- // console.log(res)
- for (let i = 0; i < res.data.list.length; i++) {
- typeDefs.value.push({
- name: res.data.list[i].dictLabel,
- color: res.data.list[i].cssClass,
- label: res.data.list[i].dictValue
- })
- }
- })
- getSubtaskApi(subTaskId).then(res => {
- taskType.value = res.data.type
- taskStatus.value = res.data.status
- })
- refreshList()
- timer.value = setInterval(() => {
- refreshList()
- }, 10000)
- // 组件挂载后,logRef 将指向实际的 DOM 元素
- if (logRef.value) {
- // 操作 logRef 对应的 DOM 元素
- logRef.value.scrollTop = logRef.value.scrollHeight
- }
- })
- // 删除算法业务处理信息
- const deleteBizProcess = async (params: any) => {
- await useHandleData(delBizProcessApi, params.id, '删除【' + params.id + '】算法业务处理')
- proTable.value?.getTableList()
- }
- // 批量删除算法业务处理信息
- const batchDelete = async (ids: string[]) => {
- await useHandleData(delBizProcessApi, ids, '删除所选算法业务处理信息')
- proTable.value?.clearSelection()
- proTable.value?.getTableList()
- }
- // 导出算法业务处理列表
- const downloadFile = async () => {
- ElMessageBox.confirm('确认导出算法业务处理数据?', '温馨提示', { type: 'warning' }).then(() =>
- useDownload(exportBizProcessApi, '算法业务处理列表', proTable.value?.searchParam)
- )
- }
- // 批量添加算法业务处理
- const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
- // const batchAdd = () => {
- // const params = {
- // title: '算法业务处理',
- // tempApi: importTemplateApi,
- // importApi: importBizProcessDataApi,
- // getTableList: proTable.value?.getTableList
- // }
- // dialogRef.value?.acceptParams(params)
- // }
- // 对比结果
- const contrastResults = () => {
- const statusFlag = bizProcessList.value.every(item => {
- return item.status == '2'
- })
- if (statusFlag) {
- switch (taskType.value) {
- case '1':
- getTrainResultApi(subTaskId).then(res => {
- resultsFlag.value = false
- handleResultData(res.data)
- resultVisible.value = true
- })
- break
- case '2':
- getVerifyResultApi(subTaskId).then(res => {
- resultsFlag.value = false
- handleResultData(res.data)
- resultVisible.value = true
- })
- break
- case '3':
- getTestResultApi(subTaskId).then(res => {
- console.log('333', res)
- resultsFlag.value = true
- testResultsData.value = res.data as any
- const num = testResultsData.value['agNameList'].length
- spanNum.value = 24 / num <= 4 ? 4 : Math.floor(24 / num)
- resultVisible.value = true
- })
- break
- default:
- break
- }
- } else {
- ElMessage.warning(`所有算法状态为‘已完成’,才可以对比`)
- }
- }
- const handleResultData = data => {
- resultsData.value = data
- resultsData.value['agNameList'].unshift('')
- const num = resultsData.value['agNameList'].length + 1
- spanNum.value = 24 / num <= 4 ? 4 : Math.floor(24 / num)
- resultsData.value['rcureList'].unshift('R_curve')
- resultsData.value['pcureList'].unshift('P_curve')
- resultsData.value['f1cureList'].unshift('F1_curve')
- }
- // 查看日志
- let timer2 = ref()
- const viewLog = row => {
- // if (row.status === '0') {
- // ElMessage.warning('算法状态为待处理,暂无日志')
- // return
- // }
- const url = `/api/profile/task` + row.resultPath + '/log/log.log'
- logShow(url)
- dialogVisible.value = true
- timer2.value = setInterval(() => {
- if (dialogVisible.value) {
- logShow(url)
- }
- }, 5000)
- }
- // 日志读取
- const logShow = (url: any) => {
- fetchLogFile(url)
- .then(text => {
- logInfo.value = []
- logInfo.value = text.split('\n')
- nextTick(() => {
- const logContainer = logRef.value
- if (logContainer) {
- ;(logContainer as HTMLElement).scrollTop = (logContainer as HTMLElement).scrollHeight
- }
- })
- })
- .catch(error => {
- console.error('Failed to fetch the log file:', error)
- ElMessage.error('日志读取错误')
- })
- }
- const fetchLogFile = async url => {
- try {
- const response = await fetch(url, { method: 'GET' })
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`)
- }
- return await response.text()
- } catch (error) {
- throw error
- }
- }
- 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 getBizProcessApi(row?.id || null)
- }
- // 重置表单
- setItemsOptions()
- const params = {
- title,
- width: 580,
- isEdit: type !== 3,
- itemsOptions: itemsOptions,
- model: type == 1 ? {} : res.data,
- api: type == 1 ? addBizProcessApi : updateBizProcessApi,
- getTableList: proTable.value?.getTableList
- }
- formDialogRef.value?.openDialog(params)
- }
- onUnmounted(() => {
- clearInterval(timer.value)
- timer.value = null
- })
- watch(
- () => dialogVisible.value,
- val => {
- if (!val) {
- clearInterval(timer2.value)
- timer2.value = null
- }
- }
- )
- // 表格配置项
- const columns = reactive<ColumnProps<any>[]>([
- { type: 'selection', fixed: 'left', width: 70 },
- // { prop: 'id', label: '主键ID' },
- // {
- // prop: 'subTaskId',
- // label: '子任务id',
- // search: {
- // el: 'input'
- // },
- // width: 120
- // },
- {
- prop: 'name',
- label: '任务名称',
- search: {
- el: 'input'
- },
- width: 120
- },
- // {
- // prop: 'type',
- // label: '任务类型',
- // search: {
- // el: 'input'
- // },
- // width: 120
- // },
- {
- prop: 'status',
- label: '任务状态',
- tag: true,
- enum: () => getDictsApi('biz_task_status'),
- search: {
- el: 'tree-select'
- },
- width: 100,
- fieldNames: { label: 'dictLabel', value: 'dictValue' }
- },
- // {
- // prop: 'algorithmId',
- // label: '算法',
- // width: 120
- // },
- // {
- // prop: 'modelId',
- // label: '模型',
- // width: 120
- // },
- {
- prop: 'parameters',
- label: '调用算法时所用的参数'
- },
- {
- prop: 'absolutePreprocessPath',
- label: '预处理数据路径'
- },
- {
- prop: 'absoluteResultPath',
- label: '结果数据路径'
- },
- {
- prop: 'startTime',
- label: '开始时间'
- },
- {
- prop: 'endTime',
- label: '结束时间'
- },
- {
- prop: 'costSecond',
- label: '耗时'
- },
- {
- prop: 'remarks',
- label: '日志'
- },
- { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
- ])
- // 结果表格配置项
- // const resultColumns = reactive<ColumnProps<any>[]>([])
- // 表单配置项
- let itemsOptions: ProForm.ItemsOptions[] = []
- const setItemsOptions = () => {
- itemsOptions = [
- {
- label: '子任务id',
- prop: 'subTaskId',
- compOptions: {
- placeholder: '请输入子任务id'
- }
- },
- {
- label: '任务名称',
- prop: 'name',
- compOptions: {
- placeholder: '请输入任务名称'
- }
- },
- {
- label: '任务类型',
- prop: 'type',
- compOptions: {
- placeholder: '请输入任务类型'
- }
- },
- {
- label: '任务状态',
- prop: 'status',
- compOptions: {
- elTagName: 'select',
- labelKey: 'dictLabel',
- valueKey: 'dictValue',
- enum: () => getDictsApi('biz_task_status'),
- placeholder: '请选择任务状态'
- }
- },
- {
- label: '算法',
- prop: 'algorithmId',
- compOptions: {
- placeholder: '请输入算法'
- }
- },
- {
- label: '模型',
- prop: 'modelId',
- compOptions: {
- placeholder: '请输入模型'
- }
- },
- {
- label: '调用算法时所用的参数',
- prop: 'parameters',
- compOptions: {
- type: 'textarea',
- clearable: true,
- placeholder: '请输入内容'
- }
- },
- {
- label: '预处理数据路径',
- prop: 'preprocessPath',
- compOptions: {
- placeholder: '请输入预处理数据路径'
- }
- },
- {
- label: '结果数据路径',
- prop: 'resultPath',
- compOptions: {
- placeholder: '请输入结果数据路径'
- }
- },
- {
- label: '序号',
- prop: 'index',
- compOptions: {
- placeholder: '请输入序号'
- }
- },
- {
- label: '开始时间',
- prop: 'startTime',
- compOptions: {
- elTagName: 'date-picker',
- type: 'date',
- placeholder: '请选择开始时间'
- }
- },
- {
- label: '结束时间',
- prop: 'endTime',
- compOptions: {
- elTagName: 'date-picker',
- type: 'date',
- placeholder: '请选择结束时间'
- }
- },
- {
- label: '耗时',
- prop: 'costSecond',
- compOptions: {
- placeholder: '请输入耗时'
- }
- },
- {
- label: '日志',
- prop: 'log',
- compOptions: {
- type: 'textarea',
- clearable: true,
- placeholder: '请输入内容'
- }
- }
- ]
- }
- </script>
- <style scoped lang="scss">
- .log {
- width: 90%;
- height: 60vh;
- /* 根据需要调整 */
- padding: 10px;
- // padding-bottom: 80px;
- margin-left: 50px;
- overflow-y: auto;
- font-family: 'Courier New', monospace;
- color: #4aff84;
- background-color: #1e1e1e;
- }
- .p {
- padding-left: 10px;
- margin-bottom: 5px;
- border-left: 3px solid #4aff84;
- }
- .resultShow {
- width: 100%;
- height: 60vh;
- overflow: hidden;
- overflow: scroll scroll;
- .headerRow {
- height: 50px;
- font-size: 1.2rem;
- line-height: 50px;
- text-align: center;
- }
- .row {
- .col {
- text-align: center;
- .oneCol {
- margin-top: 45px;
- font-size: 1.2rem;
- }
- .img {
- margin: 10px 0;
- }
- }
- }
- }
- </style>
|