Files
orc-order-v2/web/frontend/src/views/files/Images.vue
T

250 lines
7.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="file-page animate-in">
<div class="page-header">
<div class="header-left">
<h3>图片处理</h3>
<el-tag type="info" size="small"> {{ total }} </el-tag>
</div>
<div class="header-actions">
<el-button type="primary" :disabled="!selected.length" @click="batchPipeline">
批量生成采购单 ({{ selected.length }})
</el-button>
<el-button :disabled="!selected.length" @click="batchOcr">
批量OCR
</el-button>
<el-button :disabled="!selected.length" @click="batchDownload">
批量下载
</el-button>
<el-button type="danger" :disabled="!selected.length" @click="batchDelete">
批量删除
</el-button>
</div>
</div>
<el-table
:data="items"
v-loading="loading"
@selection-change="onSelect"
stripe
style="width: 100%"
>
<el-table-column type="selection" width="45" />
<el-table-column label="图片文件名" min-width="200">
<template #default="{ row }">
<span class="file-name primary">{{ row.input_image || '--' }}</span>
</template>
</el-table-column>
<el-table-column label="" width="40" align="center">
<template #default="{ row }">
<el-icon :color="row.output_exists ? '#52C41A' : '#d1d5db'" :size="16">
<Right />
</el-icon>
</template>
</el-table-column>
<el-table-column label="Excel文件" min-width="180">
<template #default="{ row }">
<span class="file-name secondary">{{ row.output_excel || '--' }}</span>
</template>
</el-table-column>
<el-table-column label="" width="40" align="center">
<template #default="{ row }">
<el-icon :color="row.result_exists ? '#52C41A' : '#d1d5db'" :size="16">
<Right />
</el-icon>
</template>
</el-table-column>
<el-table-column label="采购单" min-width="180">
<template #default="{ row }">
<span class="file-name secondary">{{ row.result_purchase || '--' }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="statusType(row.status)" size="small">{{ statusText(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="pipelineFile(row)">
生成采购单
</el-button>
<el-button link type="primary" size="small" @click="ocrFile(row)">
仅OCR
</el-button>
<el-button link type="danger" size="small" @click="deleteFile(row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-wrap">
<el-pagination
v-model:current-page="page"
:page-size="pageSize"
:total="total"
layout="total, prev, pager, next"
@current-change="loadData"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Right } from '@element-plus/icons-vue'
import api from '../../api'
const items = ref<any[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = 50
const loading = ref(false)
const selected = ref<any[]>([])
function statusType(s: string) {
const m: Record<string, string> = { done: 'success', merged: 'success', excel_done: 'warning', ocr_done: 'info', pending: 'info' }
return m[s] || 'info'
}
function statusText(s: string) {
const m: Record<string, string> = { done: '已完成', merged: '已合并', excel_done: '已处理', ocr_done: '已OCR', pending: '待处理' }
return m[s] || s
}
async function loadData() {
loading.value = true
try {
const res = await api.get('/files/relations', { params: { view: 'images', page: page.value, page_size: pageSize } })
items.value = res.data.items
total.value = res.data.total
} catch {}
loading.value = false
}
function onSelect(rows: any[]) { selected.value = rows }
async function pipelineFile(row: any) {
try {
const res = await api.post('/processing/pipeline-single', { filename: row.input_image })
ElMessage.success(`处理任务已创建: ${res.data.task_id}`)
} catch (err: any) {
ElMessage.error(err.response?.data?.detail || '处理失败')
}
}
async function ocrFile(row: any) {
try {
const res = await api.post('/processing/ocr-single', { filename: row.input_image })
ElMessage.success(`OCR任务已创建: ${res.data.task_id}`)
} catch (err: any) {
ElMessage.error(err.response?.data?.detail || 'OCR失败')
}
}
async function downloadFile(row: any) {
const token = localStorage.getItem('token')
if (row.result_purchase) {
window.open(`/api/files/download/result/${encodeURIComponent(row.result_purchase)}?token=${token}`, '_blank')
} else if (row.output_excel) {
window.open(`/api/files/download/output/${encodeURIComponent(row.output_excel)}?token=${token}`, '_blank')
}
}
async function deleteFile(row: any) {
try {
await ElMessageBox.confirm(`确定删除 ${row.input_image}`, '确认')
await api.delete(`/files/input/${encodeURIComponent(row.input_image)}`)
if (row.id) await api.delete('/files/relations', { data: { ids: [row.id] } })
ElMessage.success('已删除')
loadData()
} catch {}
}
async function batchPipeline() {
try {
const filenames = selected.value.map(r => r.input_image).filter(Boolean)
const res = await api.post('/processing/pipeline', { files: filenames })
ElMessage.success(`批量处理任务已创建: ${res.data.task_id}`)
} catch (err: any) {
ElMessage.error(err.response?.data?.detail || '处理失败')
}
}
async function batchOcr() {
try {
const filenames = selected.value.map(r => r.input_image).filter(Boolean)
const res = await api.post('/processing/ocr-batch', { files: filenames })
ElMessage.success(`批量OCR任务已创建: ${res.data.task_id}`)
} catch (err: any) {
ElMessage.error(err.response?.data?.detail || 'OCR失败')
}
}
async function batchDownload() {
const token = localStorage.getItem('token')
for (const row of selected.value) {
if (row.result_purchase) {
window.open(`/api/files/download/result/${encodeURIComponent(row.result_purchase)}?token=${token}`, '_blank')
}
}
}
async function batchDelete() {
try {
await ElMessageBox.confirm(`确定删除选中的 ${selected.value.length} 个文件?`, '确认')
for (const row of selected.value) {
if (row.input_image) {
await api.delete(`/files/input/${encodeURIComponent(row.input_image)}`)
}
if (row.id) {
await api.delete('/files/relations', { data: { ids: [row.id] } })
}
}
ElMessage.success('批量删除完成')
loadData()
} catch {}
}
onMounted(loadData)
</script>
<style scoped>
.file-page {
width: 100%;
}
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
}
.header-left {
display: flex;
align-items: center;
gap: 12px;
}
.header-left h3 {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
}
.header-actions {
display: flex;
gap: 8px;
}
.file-name.primary {
font-weight: 600;
color: var(--text-primary);
}
.file-name.secondary {
color: var(--text-muted);
font-size: 13px;
}
.pagination-wrap {
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
</style>