|
|
|
@ -3,7 +3,9 @@
|
|
|
|
<div class="header">
|
|
|
|
<div class="header">
|
|
|
|
<div class="header-left">
|
|
|
|
<div class="header-left">
|
|
|
|
<div class="back-title" @click="goBack">
|
|
|
|
<div class="back-title" @click="goBack">
|
|
|
|
<el-icon style="margin-right: 6px" size="18"><ArrowLeft /></el-icon>
|
|
|
|
<el-icon style="margin-right: 6px" size="18">
|
|
|
|
|
|
|
|
<ArrowLeft/>
|
|
|
|
|
|
|
|
</el-icon>
|
|
|
|
<span>{{ task.name }}</span>
|
|
|
|
<span>{{ task.name }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="filter-buttons">
|
|
|
|
<div class="filter-buttons">
|
|
|
|
@ -22,8 +24,10 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="action-buttons">
|
|
|
|
<div class="action-buttons">
|
|
|
|
<el-button v-if="task.media_type !== 'qa'" link @click="openTagConfig" :icon="Setting" style="margin-right: 10px"
|
|
|
|
<el-button v-if="task.media_type !== 'qa'" link @click="openTagConfig" :icon="Setting"
|
|
|
|
>标签配置</el-button
|
|
|
|
style="margin-right: 10px"
|
|
|
|
|
|
|
|
>标签配置
|
|
|
|
|
|
|
|
</el-button
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-button link @click="openExportDialog" :icon="Printer" style="margin-right: 10px">数据导出</el-button>
|
|
|
|
<el-button link @click="openExportDialog" :icon="Printer" style="margin-right: 10px">数据导出</el-button>
|
|
|
|
<el-button type="primary" @click="startMarking">开始标注</el-button>
|
|
|
|
<el-button type="primary" @click="startMarking">开始标注</el-button>
|
|
|
|
@ -33,30 +37,30 @@
|
|
|
|
<div class="table-container">
|
|
|
|
<div class="table-container">
|
|
|
|
<div class="table-content">
|
|
|
|
<div class="table-content">
|
|
|
|
<el-table
|
|
|
|
<el-table
|
|
|
|
:data="sampleList"
|
|
|
|
:data="sampleList"
|
|
|
|
style="width: 100%"
|
|
|
|
style="width: 100%"
|
|
|
|
height="100%"
|
|
|
|
height="100%"
|
|
|
|
:stripe="false"
|
|
|
|
:stripe="false"
|
|
|
|
v-loading="sampleListLoading"
|
|
|
|
v-loading="sampleListLoading"
|
|
|
|
@row-click="handleRowClick"
|
|
|
|
@row-click="handleRowClick"
|
|
|
|
:row-style="{ cursor: 'pointer' }"
|
|
|
|
:row-style="{ cursor: 'pointer' }"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-table-column align="center" prop="index" label="序号" width="80" fixed />
|
|
|
|
<el-table-column align="center" prop="index" label="序号" width="80" fixed/>
|
|
|
|
<el-table-column
|
|
|
|
<el-table-column
|
|
|
|
prop="name"
|
|
|
|
prop="name"
|
|
|
|
label="名称"
|
|
|
|
label="名称"
|
|
|
|
:width="task.media_type !== 'timeseries' && task.media_type !== 'plaintext' ? '150' : ''"
|
|
|
|
:width="task.media_type !== 'timeseries' && task.media_type !== 'plaintext' ? '150' : ''"
|
|
|
|
fixed
|
|
|
|
fixed
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<template v-if="task.media_type === 'qa'">
|
|
|
|
<template v-if="task.media_type === 'qa'">
|
|
|
|
<el-table-column
|
|
|
|
<el-table-column
|
|
|
|
v-for="key in qaTableColumn"
|
|
|
|
v-for="key in qaTableColumn"
|
|
|
|
:key="key"
|
|
|
|
:key="key"
|
|
|
|
:prop="key"
|
|
|
|
:prop="key"
|
|
|
|
:label="key"
|
|
|
|
:label="key"
|
|
|
|
show-overflow-tooltip
|
|
|
|
show-overflow-tooltip
|
|
|
|
min-width="250px"
|
|
|
|
min-width="250px"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
@ -64,8 +68,9 @@
|
|
|
|
<el-table-column label="数据预览">
|
|
|
|
<el-table-column label="数据预览">
|
|
|
|
<template #default="scope">
|
|
|
|
<template #default="scope">
|
|
|
|
<audio v-if="task.media_type === 'audio'" :src="scope.row.previewUrl" controls></audio>
|
|
|
|
<audio v-if="task.media_type === 'audio'" :src="scope.row.previewUrl" controls></audio>
|
|
|
|
<video v-else-if="task.media_type === 'video'" :src="scope.row.previewUrl" controls style="height: 80px"></video>
|
|
|
|
<video v-else-if="task.media_type === 'video'" :src="scope.row.previewUrl" controls
|
|
|
|
<img v-else-if="task.media_type == 'image'" :src="scope.row.previewUrl" style="height: 80px" />
|
|
|
|
style="height: 80px"></video>
|
|
|
|
|
|
|
|
<img v-else-if="task.media_type == 'image'" :src="scope.row.previewUrl" style="height: 80px"/>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
@ -77,20 +82,21 @@
|
|
|
|
</el-tag>
|
|
|
|
</el-tag>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column v-if="task.media_type !== 'qa'" align="center" prop="annotated_count" label="标注数量" width="120" />
|
|
|
|
<el-table-column v-if="task.media_type !== 'qa'" align="center" prop="annotated_count" label="标注数量"
|
|
|
|
|
|
|
|
width="120"/>
|
|
|
|
</el-table>
|
|
|
|
</el-table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="pagination-box">
|
|
|
|
<div class="pagination-box">
|
|
|
|
<el-pagination
|
|
|
|
<el-pagination
|
|
|
|
background
|
|
|
|
background
|
|
|
|
:current-page="currentPage"
|
|
|
|
:current-page="currentPage"
|
|
|
|
:page-size="pageSize"
|
|
|
|
:page-size="pageSize"
|
|
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
|
|
layout="total, sizes, prev, pager, next"
|
|
|
|
layout="total, sizes, prev, pager, next"
|
|
|
|
:total="total"
|
|
|
|
:total="total"
|
|
|
|
@current-change="handleCurrentChange"
|
|
|
|
@current-change="handleCurrentChange"
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
@size-change="handleSizeChange"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@ -99,7 +105,7 @@
|
|
|
|
<el-form :model="exportForm" :rules="exportRules" ref="exportFormRef" label-width="100px">
|
|
|
|
<el-form :model="exportForm" :rules="exportRules" ref="exportFormRef" label-width="100px">
|
|
|
|
<el-form-item label="导出格式" prop="export_type">
|
|
|
|
<el-form-item label="导出格式" prop="export_type">
|
|
|
|
<el-select v-model="exportForm.export_type" placeholder="请选择导出格式" style="width: 130px">
|
|
|
|
<el-select v-model="exportForm.export_type" placeholder="请选择导出格式" style="width: 130px">
|
|
|
|
<el-option v-for="item in exportTypes" :key="item" :label="item" :value="item" />
|
|
|
|
<el-option v-for="item in exportTypes" :key="item" :label="item" :value="item"/>
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
@ -112,27 +118,27 @@
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { ArrowLeft, Setting, Printer } from '@element-plus/icons-vue';
|
|
|
|
import {ArrowLeft, Setting, Printer} from '@element-plus/icons-vue';
|
|
|
|
import { useGet, usePost } from '../../request';
|
|
|
|
import {useGet, usePost} from '../../request';
|
|
|
|
import { markingApi, baseApi } from '../../request/api/requestApi';
|
|
|
|
import {markingApi, baseApi} from '../../request/api/requestApi';
|
|
|
|
import { parseContent } from '../../utils/parse-first-level';
|
|
|
|
import {parseContent} from '../../utils/parse-first-level';
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
import {ElMessage} from 'element-plus';
|
|
|
|
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const router = useRouter();
|
|
|
|
const route = useRoute();
|
|
|
|
const route = useRoute();
|
|
|
|
const id = route.params.id as string;
|
|
|
|
const id = route.params.id as string;
|
|
|
|
const media_type = route.params.media_type as string;
|
|
|
|
const media_type = route.params.media_type as string;
|
|
|
|
|
|
|
|
|
|
|
|
const { doGet: taskGet } = useGet({
|
|
|
|
const {doGet: taskGet} = useGet({
|
|
|
|
url: markingApi.taskApi.get
|
|
|
|
url: markingApi.taskApi.get
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const { doGet: sampleListGet, loading: sampleListLoading } = useGet({
|
|
|
|
const {doGet: sampleListGet, loading: sampleListLoading} = useGet({
|
|
|
|
url: markingApi.sample.page(id)
|
|
|
|
url: markingApi.sample.page(id)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const { doGet: baseConfigGet } = useGet({
|
|
|
|
const {doGet: baseConfigGet} = useGet({
|
|
|
|
url: baseApi.config
|
|
|
|
url: baseApi.config
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const { doPost: exportPost, loading: exportPostLoading } = usePost({
|
|
|
|
const {doPost: exportPost, loading: exportPostLoading} = usePost({
|
|
|
|
url: markingApi.sample.export
|
|
|
|
url: markingApi.sample.export
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
@ -179,7 +185,7 @@ const exportForm = ref({
|
|
|
|
export_type: 'JSON'
|
|
|
|
export_type: 'JSON'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const exportRules = ref({
|
|
|
|
const exportRules = ref({
|
|
|
|
export_type: [{ required: true, message: '请选择导出类型', trigger: 'blur' }]
|
|
|
|
export_type: [{required: true, message: '请选择导出类型', trigger: 'blur'}]
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const exportFormRef = ref<any>();
|
|
|
|
const exportFormRef = ref<any>();
|
|
|
|
|
|
|
|
|
|
|
|
@ -202,9 +208,9 @@ const handleExportSubmit = async () => {
|
|
|
|
|
|
|
|
|
|
|
|
const openTagConfig = () => {
|
|
|
|
const openTagConfig = () => {
|
|
|
|
if (task.value.media_type !== 'plaintext' && task.value.media_type !== 'timeseries') {
|
|
|
|
if (task.value.media_type !== 'plaintext' && task.value.media_type !== 'timeseries') {
|
|
|
|
router.push({ path: `/data-factory/marking/canvas/${id}`, hash: '#config' });
|
|
|
|
router.push({path: `/data-factory/marking/canvas/${id}`, hash: '#config'});
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
router.push({ path: `/data-factory/marking/plaintextConfiguration/${id}` });
|
|
|
|
router.push({path: `/data-factory/marking/plaintextConfiguration/${id}`});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
@ -280,11 +286,11 @@ const getSampleList = async (pageNumber: number = 1, pageSize: number = 10, stat
|
|
|
|
if (res.data.code === 0) {
|
|
|
|
if (res.data.code === 0) {
|
|
|
|
sampleList.value = res.data.data.data.map((item: any, index: number) => {
|
|
|
|
sampleList.value = res.data.data.data.map((item: any, index: number) => {
|
|
|
|
const parsedData =
|
|
|
|
const parsedData =
|
|
|
|
task.value.media_type !== 'timeseries'
|
|
|
|
task.value.media_type !== 'timeseries'
|
|
|
|
? task.value.media_type === 'qa'
|
|
|
|
? task.value.media_type === 'qa'
|
|
|
|
? parseContent(eval(`(${item.data})`).content)
|
|
|
|
? parseContent(eval(`(${item.data})`).content)
|
|
|
|
: eval(`(${item.data})`)
|
|
|
|
: eval(`(${item.data})`)
|
|
|
|
: {};
|
|
|
|
: {};
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
index: index + 1,
|
|
|
|
index: index + 1,
|
|
|
|
...item,
|
|
|
|
...item,
|
|
|
|
@ -292,9 +298,9 @@ const getSampleList = async (pageNumber: number = 1, pageSize: number = 10, stat
|
|
|
|
created_time: new Date(item.created_time).toLocaleString(),
|
|
|
|
created_time: new Date(item.created_time).toLocaleString(),
|
|
|
|
updated_time: new Date(item.updated_time).toLocaleString(),
|
|
|
|
updated_time: new Date(item.updated_time).toLocaleString(),
|
|
|
|
previewUrl:
|
|
|
|
previewUrl:
|
|
|
|
task.value.media_type === 'timeseries' || task.value.media_type === 'qa'
|
|
|
|
task.value.media_type === 'timeseries' || task.value.media_type === 'qa'
|
|
|
|
? ''
|
|
|
|
? ''
|
|
|
|
: config.value?.storage_dataset_base_url + parsedData.sample_file_path
|
|
|
|
: config.value?.storage_dataset_base_url + parsedData.sample_file_path
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (task.value.media_type === 'qa') {
|
|
|
|
if (task.value.media_type === 'qa') {
|
|
|
|
@ -374,30 +380,36 @@ const outputSample = async (activeTxt: string) => {
|
|
|
|
padding: 20px;
|
|
|
|
padding: 20px;
|
|
|
|
background-color: #ffffff;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 4px;
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
|
|
.header {
|
|
|
|
.header {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
.header-left {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
gap: 60px;
|
|
|
|
gap: 60px;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
|
|
.back-title {
|
|
|
|
.back-title {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
align-items: center;
|
|
|
|
font-size: 18px;
|
|
|
|
font-size: 18px;
|
|
|
|
cursor: pointer;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.filter-buttons {
|
|
|
|
.filter-buttons {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
gap: 15px;
|
|
|
|
gap: 15px;
|
|
|
|
|
|
|
|
|
|
|
|
.btn-item {
|
|
|
|
.btn-item {
|
|
|
|
padding: 5px 15px;
|
|
|
|
padding: 5px 15px;
|
|
|
|
color: rgb(78 89 105 / 100%);
|
|
|
|
color: rgb(78 89 105 / 100%);
|
|
|
|
cursor: pointer;
|
|
|
|
cursor: pointer;
|
|
|
|
border-radius: 20px;
|
|
|
|
border-radius: 20px;
|
|
|
|
transition: background-color 0.4s;
|
|
|
|
transition: background-color 0.4s;
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
&.active {
|
|
|
|
color: rgb(22 93 255 / 100%);
|
|
|
|
color: rgb(22 93 255 / 100%);
|
|
|
|
background: rgb(237 237 237 / 100%);
|
|
|
|
background: rgb(237 237 237 / 100%);
|
|
|
|
@ -405,20 +417,24 @@ const outputSample = async (activeTxt: string) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
.action-buttons {
|
|
|
|
el-button {
|
|
|
|
el-button {
|
|
|
|
margin-left: 10px;
|
|
|
|
margin-left: 10px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.table-container {
|
|
|
|
.table-container {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
flex-direction: column;
|
|
|
|
justify-content: space-between;
|
|
|
|
justify-content: space-between;
|
|
|
|
height: calc(100% - 40px);
|
|
|
|
height: calc(100% - 40px);
|
|
|
|
|
|
|
|
|
|
|
|
.table-content {
|
|
|
|
.table-content {
|
|
|
|
flex: 1;
|
|
|
|
flex: 1;
|
|
|
|
overflow: auto;
|
|
|
|
overflow: auto;
|
|
|
|
|
|
|
|
|
|
|
|
.text-ellipsis {
|
|
|
|
.text-ellipsis {
|
|
|
|
display: inline-block;
|
|
|
|
display: inline-block;
|
|
|
|
width: 100%;
|
|
|
|
width: 100%;
|
|
|
|
@ -428,12 +444,14 @@ const outputSample = async (activeTxt: string) => {
|
|
|
|
vertical-align: middle;
|
|
|
|
vertical-align: middle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.pagination-box {
|
|
|
|
.pagination-box {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
justify-content: flex-end;
|
|
|
|
padding: 10px 0;
|
|
|
|
padding: 10px 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dialog-footer {
|
|
|
|
.dialog-footer {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
justify-content: flex-end;
|
|
|
|
|