2026-07-13 11:04:08 +08:00
|
|
|
<script setup lang="ts">
|
2026-08-05 16:23:00 +08:00
|
|
|
import { onMounted, ref } from 'vue'
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
import { Plus, Delete, Refresh } from '@element-plus/icons-vue'
|
|
|
|
|
import type { UploadRequestOptions } from 'element-plus'
|
2026-07-13 11:04:08 +08:00
|
|
|
import PageCard from '@/components/PageCard.vue'
|
2026-08-05 16:23:00 +08:00
|
|
|
import {
|
|
|
|
|
getDataConvertTasks,
|
|
|
|
|
createDataConvertTask,
|
|
|
|
|
uploadSourceFiles,
|
|
|
|
|
deleteDataConvertTask,
|
|
|
|
|
type DataConvertTask,
|
|
|
|
|
} from '@/api/modules/data-convert'
|
|
|
|
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
const tasks = ref<DataConvertTask[]>([])
|
|
|
|
|
const showCreate = ref(false)
|
|
|
|
|
const form = ref({ name: '', outputName: 'converted-data' })
|
|
|
|
|
|
|
|
|
|
async function load() {
|
|
|
|
|
loading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const res = await getDataConvertTasks()
|
|
|
|
|
tasks.value = res.items || []
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function submitCreate() {
|
|
|
|
|
if (!form.value.name) {
|
|
|
|
|
ElMessage.warning('请填写任务名称')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
await createDataConvertTask({
|
|
|
|
|
name: form.value.name,
|
|
|
|
|
output_filename: form.value.outputName + '.jsonl',
|
|
|
|
|
})
|
|
|
|
|
ElMessage.success('任务创建成功')
|
|
|
|
|
showCreate.value = false
|
|
|
|
|
form.value = { name: '', outputName: 'converted-data' }
|
|
|
|
|
load()
|
|
|
|
|
}
|
2026-07-13 11:04:08 +08:00
|
|
|
|
2026-08-05 16:23:00 +08:00
|
|
|
async function customUpload(options: UploadRequestOptions) {
|
|
|
|
|
const taskId = options.data?.taskId as string
|
|
|
|
|
if (!taskId) {
|
|
|
|
|
ElMessage.error('任务 ID 缺失')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const res = await uploadSourceFiles(taskId, [options.file])
|
|
|
|
|
const data = (res as any)?.data || res
|
|
|
|
|
if (data?.auto_converted) {
|
|
|
|
|
ElMessage.success(
|
|
|
|
|
`上传并自动转换完成,输入 ${data.input_count} / 输出 ${data.output_count},已自动导入数据集`,
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.warning('上传完成,但转换失败:' + (data?.error || '未知错误'))
|
|
|
|
|
}
|
|
|
|
|
load()
|
|
|
|
|
} catch {
|
|
|
|
|
ElMessage.error('上传失败')
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-07-13 11:04:08 +08:00
|
|
|
|
2026-08-05 16:23:00 +08:00
|
|
|
async function handleDelete(task: DataConvertTask) {
|
|
|
|
|
try {
|
|
|
|
|
await ElMessageBox.confirm(
|
|
|
|
|
`确定要删除任务「${task.name}」吗?`,
|
|
|
|
|
'删除确认',
|
|
|
|
|
{ confirmButtonText: '确定删除', cancelButtonText: '取消', type: 'warning' },
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
await deleteDataConvertTask(task.id)
|
|
|
|
|
ElMessage.success('任务已删除')
|
|
|
|
|
load()
|
2026-07-13 11:04:08 +08:00
|
|
|
}
|
|
|
|
|
|
2026-08-05 16:23:00 +08:00
|
|
|
function statusTag(status: string) {
|
|
|
|
|
const map: Record<string, { type: string; label: string }> = {
|
|
|
|
|
pending: { type: 'info', label: '待上传' },
|
|
|
|
|
uploaded: { type: 'warning', label: '已上传' },
|
|
|
|
|
running: { type: 'warning', label: '转换中' },
|
|
|
|
|
completed: { type: 'success', label: '已完成' },
|
|
|
|
|
failed: { type: 'danger', label: '失败' },
|
|
|
|
|
}
|
|
|
|
|
return map[status] || { type: 'info', label: status }
|
2026-07-13 11:04:08 +08:00
|
|
|
}
|
2026-08-05 16:23:00 +08:00
|
|
|
|
|
|
|
|
onMounted(load)
|
2026-07-13 11:04:08 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<PageCard
|
|
|
|
|
class="data-convert-page"
|
|
|
|
|
title="数据类型转换"
|
2026-08-05 16:23:00 +08:00
|
|
|
subtitle="将 JSON 文件转换为 JSONL 格式,转换结果自动导入到数据集管理"
|
2026-07-13 11:04:08 +08:00
|
|
|
>
|
2026-08-05 16:23:00 +08:00
|
|
|
<div class="toolbar">
|
|
|
|
|
<el-button type="primary" :icon="Plus" @click="showCreate = true">新建转换任务</el-button>
|
|
|
|
|
<el-button :icon="Refresh" @click="load">刷新</el-button>
|
|
|
|
|
</div>
|
2026-07-13 11:04:08 +08:00
|
|
|
|
2026-08-05 16:23:00 +08:00
|
|
|
<el-table :data="tasks" v-loading="loading" border stripe>
|
|
|
|
|
<el-table-column prop="name" label="任务名称" min-width="140" />
|
|
|
|
|
<el-table-column label="状态" min-width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-tag :type="statusTag(row.status).type">{{ statusTag(row.status).label }}</el-tag>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="数据量" min-width="120">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
{{ row.output_count }} 条
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column prop="output_filename" label="输出文件名" min-width="160" />
|
|
|
|
|
<el-table-column prop="create_time" label="创建时间" min-width="180" />
|
|
|
|
|
<el-table-column label="操作" width="240" fixed="right">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<el-upload
|
|
|
|
|
v-if="row.status === 'pending'"
|
|
|
|
|
:auto-upload="true"
|
|
|
|
|
:show-file-list="false"
|
|
|
|
|
accept=".json"
|
|
|
|
|
:http-request="customUpload"
|
|
|
|
|
:data="{ taskId: row.id }"
|
|
|
|
|
style="display: inline-block; margin-right: 8px"
|
|
|
|
|
>
|
|
|
|
|
<el-button link type="primary">上传文件</el-button>
|
|
|
|
|
</el-upload>
|
|
|
|
|
<el-button link type="danger" :icon="Delete" @click="handleDelete(row)">删除</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
<!-- 新建任务弹窗 -->
|
|
|
|
|
<el-dialog v-model="showCreate" title="新建转换任务" width="480px">
|
|
|
|
|
<el-form label-width="100px">
|
|
|
|
|
<el-form-item label="任务名称" required>
|
|
|
|
|
<el-input v-model="form.name" placeholder="请输入任务名称" />
|
2026-07-13 11:04:08 +08:00
|
|
|
</el-form-item>
|
2026-08-05 16:23:00 +08:00
|
|
|
<el-form-item label="输出文件名">
|
|
|
|
|
<el-input v-model="form.outputName" placeholder="converted-data">
|
|
|
|
|
<template #append>.jsonl</template>
|
|
|
|
|
</el-input>
|
2026-07-13 11:04:08 +08:00
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
2026-08-05 16:23:00 +08:00
|
|
|
<template #footer>
|
|
|
|
|
<el-button @click="showCreate = false">取消</el-button>
|
|
|
|
|
<el-button type="primary" @click="submitCreate">创建</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-dialog>
|
2026-07-13 11:04:08 +08:00
|
|
|
</PageCard>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2026-08-05 16:23:00 +08:00
|
|
|
.toolbar {
|
2026-07-13 11:04:08 +08:00
|
|
|
display: flex;
|
2026-08-05 16:23:00 +08:00
|
|
|
gap: 10px;
|
|
|
|
|
margin-bottom: 16px;
|
2026-07-13 11:04:08 +08:00
|
|
|
}
|
|
|
|
|
</style>
|