This commit is contained in:
2026-09-07 11:02:36 +08:00
parent b8dd969cb1
commit f4fe079703
4 changed files with 82 additions and 42 deletions
+80 -40
View File
@@ -429,6 +429,26 @@ const anStatusOptions = [
const anTagType = { pending: 'info', submitted: 'warning', approved: 'success', rejected: 'danger' }
const anTagText = { pending: '领取中', submitted: '待审核', approved: '已通过', rejected: '已拒绝' }
// 任务图集(2026-09-07 图片粒度下发):任务 = 勾选的具体图片,选几张任务里就展示几张——
// 面板直接网格展示被占用(annotateTaskId>0)的图片,每张角标 = 任务 id + 当前状态;
// 不再以任务记录表呈现。停用释放的图(annotateTaskId 清 0)自动移出网格
const taskImages = computed(() => (detail.value?.images || []).filter((it) => meta(it).annotateTaskId > 0))
const taskChips = computed(() => {
const occupied = new Set(taskImages.value.map((it) => meta(it).annotateTaskId))
return anTasks.value.filter((t) => t.status === 'published' || occupied.has(t.id))
})
const taskImgTag = (it) => {
const rs = reviewStatusOf(it)
if (rs === 1) return { text: '待审核', type: 'warning' }
if (rs === 2) return { text: '已通过', type: 'success' }
return { text: '待标注', type: 'info' }
}
// 刷新 = 任务概要 + 图片占用一起刷新(停用释放/下发后网格即时更新)
async function refreshTasks() {
await Promise.all([loadAnnotateTasks(), loadAll()])
}
async function loadAnnotateTasks() {
anLoading.value = true
try {
@@ -444,17 +464,17 @@ async function loadAnnotateTasks() {
async function stopAnnotateTask(row) {
try {
await ElMessageBox.confirm(`停用任务「${row.name}」?停用后 App 端不可再领取。`, '停用任务', {
type: 'warning',
confirmButtonText: '停用',
cancelButtonText: '取消',
})
await ElMessageBox.confirm(
`停用任务「${row.name}」?停用后 App 端不可再领取,未被领取的图片释放回未标注。`,
'停用任务',
{ type: 'warning', confirmButtonText: '停用', cancelButtonText: '取消' },
)
} catch {
return
}
await request.post('/annotate-tasks/stop', { id: row.id })
ElMessage.success('已停用')
loadAnnotateTasks()
ElMessage.success('已停用,未被领取的图已释放回未标注')
await refreshTasks()
}
async function loadAnnotateRecords() {
@@ -1253,43 +1273,37 @@ onBeforeUnmount(() => {
</el-radio-group>
</div>
<!-- 标注任务面板仅本数据集进度/停用下发入口在未标注 tab 勾选图片顶栏 -->
<!-- 标注任务面板2026-09-07 图片粒度任务 = 勾选下发的具体图片集合
选几张任务里就展示几张网格直出任务图集角标 = 任务 id + 状态
头部仅任务概要条下发入口在未标注tab 勾选图片顶栏 -->
<div v-if="listTab === 'tasks'" v-loading="anLoading" class="rows-area">
<div class="panel-toolbar">
<span class="panel-tip">下发入口未标注tab 勾选图片后点顶栏下发标注任务</span>
<el-button @click="loadAnnotateTasks">刷新</el-button>
</div>
<el-table :data="anTasks" size="small">
<el-table-column prop="id" label="ID" width="60" />
<el-table-column prop="name" label="任务名" min-width="140" show-overflow-tooltip />
<el-table-column prop="poolRemain" label="池余量" width="80" />
<el-table-column prop="pending" label="领取中" width="80" />
<el-table-column prop="submitted" label="待审核" width="80" />
<el-table-column prop="approved" label="已通过" width="80" />
<el-table-column prop="rejected" label="已拒绝" width="80" />
<el-table-column label="状态" width="90">
<template #default="{ row }">
<el-tag :type="row.status === 'published' ? 'success' : 'info'" size="small">
{{ row.status === 'published' ? '进行中' : '已停用' }}
<template v-if="taskChips.length">
<div v-for="t in taskChips" :key="t.id" class="task-chip">
<span class="task-chip-name">#{{ t.id }} {{ t.name }}</span>
<el-tag :type="t.status === 'published' ? 'success' : 'info'" size="small">
{{ t.status === 'published' ? '进行中' : '已停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="下发时间" width="170" show-overflow-tooltip />
<el-table-column label="操作" width="80" fixed="right">
<template #default="{ row }">
<el-button v-if="row.status === 'published'" link type="danger" @click="stopAnnotateTask(row)">停用</el-button>
</template>
</el-table-column>
</el-table>
<div class="pager">
<el-pagination
:current-page="anTaskPage"
:page-size="20"
:total="anTasksTotal"
layout="total, prev, pager, next"
@current-change="(p) => { anTaskPage = p; loadAnnotateTasks() }"
/>
<span class="task-chip-stat">
待标注 {{ t.poolRemain }} · 领取中 {{ t.pending }} · 待审核 {{ t.submitted }} · 已通过 {{ t.approved }} · 已拒绝 {{ t.rejected }}
</span>
<el-button v-if="t.status === 'published'" link type="danger" @click="stopAnnotateTask(t)">停用</el-button>
</div>
</template>
<span v-else class="panel-tip">暂无任务下发入口未标注tab 勾选图片后点顶栏下发标注任务</span>
<el-button class="task-refresh" @click="refreshTasks">刷新</el-button>
</div>
<div v-if="taskImages.length" class="card-grid">
<div v-for="item in taskImages" :key="item.filename" class="img-card">
<div class="card-img">
<img :src="imgUrl(item.url)" :alt="item.filename" loading="lazy" />
<span class="badge">#{{ meta(item).annotateTaskId }}</span>
<el-tag class="card-status" :type="taskImgTag(item).type" size="small">{{ taskImgTag(item).text }}</el-tag>
</div>
<div class="card-name" :title="item.filename">{{ item.filename }}</div>
</div>
</div>
<el-empty v-else-if="!anLoading" description="暂无下发的图片。在「未标注」tab 勾选图片后点顶栏「下发标注任务」" />
</div>
<!-- 标注记录面板仅本数据集每用户每张图的处理明细 + 手动解冻 -->
@@ -1608,6 +1622,32 @@ onBeforeUnmount(() => {
font-size: 12px;
color: #909399;
}
.task-chip {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border: 1px solid #ebeef5;
border-radius: 6px;
font-size: 12px;
}
.task-chip-name {
font-weight: 600;
white-space: nowrap;
}
.task-chip-stat {
color: #909399;
white-space: nowrap;
}
.task-refresh {
margin-left: auto;
}
.card-status {
position: absolute;
left: 6px;
bottom: 6px;
z-index: 2;
}
.label-progress {
display: flex;
align-items: center;