This commit is contained in:
2025-09-27 14:05:45 +08:00
parent 89f600fa11
commit fe3e24b945
23 changed files with 474 additions and 261 deletions

View File

@@ -15,7 +15,6 @@ const genmaiLoading = ref(false) // Genmai Spirit加载状态
// 分页配置
const currentPage = ref(1)
const pageSize = ref(15)
const totalPages = computed(() => Math.max(1, Math.ceil((localProductData.value.length || 0) / pageSize.value)))
const amazonUpload = ref<HTMLInputElement | null>(null)
const dragActive = ref(false)
@@ -26,14 +25,6 @@ const paginatedData = computed(() => {
return localProductData.value.slice(start, end)
})
// 左侧步骤栏进度
const activeStep = computed(() => {
// 0 导入/输入 -> 1 采集 -> 2 查看校验 -> 3 导出
if (loading.value && progressPercentage.value < 100) return 1
if (!localProductData.value.length) return 0
if (localProductData.value.length && progressPercentage.value < 100) return 1
return 2
})
// 左侧:网站地区 & 待采集队列
const region = ref('JP')
@@ -53,8 +44,7 @@ function showMessage(message: string, type: 'success' | 'warning' | 'error' | 'i
async function processExcelFile(file: File) {
try {
loading.value = true
tableLoading.value = true
localProductData.value = []
// 不再立即清空表格数据,保留之前的数据
progressPercentage.value = 0
progressVisible.value = false
@@ -70,7 +60,6 @@ async function processExcelFile(file: File) {
showMessage(error.message || '处理文件失败', 'error')
} finally {
loading.value = false
tableLoading.value = false
}
}
@@ -99,7 +88,7 @@ async function batchGetProductInfo(asinList: string[]) {
try {
currentAsin.value = '正在处理...'
progressPercentage.value = 0
localProductData.value = []
localProductData.value = [] // 开始采集时才清空表格数据
const batchId = `BATCH_${Date.now()}`
const batchSize = 2 // 每批处理2个ASIN
@@ -147,12 +136,7 @@ async function batchGetProductInfo(asinList: string[]) {
progressPercentage.value = 100
currentAsin.value = '处理完成'
// 结果提示
if (failedCount > 0) {
showMessage(`采集完成!共 ${asinList.length} 个ASIN成功 ${asinList.length - failedCount} 个,失败 ${failedCount}`, 'warning')
} else {
showMessage(`采集完成!成功获取 ${asinList.length} 个产品信息`, 'success')
}
} catch (error: any) {
showMessage(error.message || '批量获取产品信息失败', 'error')
@@ -180,33 +164,53 @@ async function startQueuedFetch() {
}
// 导出Excel数据
const exportLoading = ref(false)
const exportProgress = ref(0)
const showExportProgress = ref(false)
async function exportToExcel() {
if (!localProductData.value.length) {
showMessage('没有数据可供导出', 'warning')
return
}
try {
loading.value = true
showMessage('正在生成Excel文件请稍候...', 'info')
exportLoading.value = true
showExportProgress.value = true
exportProgress.value = 0
// 数据格式化 - 只保留核心字段
const exportData = localProductData.value.map(product => ({
asin: product.asin || '',
seller_shipper: getSellerShipperText(product),
price: product.price || '无货'
}))
const progressInterval = setInterval(() => {
if (exportProgress.value < 90) exportProgress.value += Math.random() * 20
}, 100)
await amazonApi.exportToExcel(exportData, {
filename: `Amazon产品数据_${new Date().toISOString().slice(0, 10)}.xlsx`
})
// 生成Excel HTML格式
let html = `<table>
<tr><th>ASIN</th><th>卖家/配送方</th><th>当前售价</th></tr>`
showMessage('Excel文件导出成功', 'success')
} catch (error: any) {
showMessage(error.message || '导出Excel失败', 'error')
} finally {
loading.value = false
}
localProductData.value.forEach(product => {
html += `<tr>
<td>${product.asin || ''}</td>
<td>${getSellerShipperText(product)}</td>
<td>${product.price || '无货'}</td>
</tr>`
})
html += '</table>'
const blob = new Blob([html], { type: 'application/vnd.ms-excel' })
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `Amazon产品数据_${new Date().toISOString().slice(0, 10)}.xls`
link.click()
URL.revokeObjectURL(link.href)
clearInterval(progressInterval)
exportProgress.value = 100
showMessage('Excel文件导出成功', 'success')
setTimeout(() => {
showExportProgress.value = false
exportLoading.value = false
exportProgress.value = 0
}, 2000)
}
// 获取卖家/配送方信息 - 数据处理辅助函数
@@ -275,6 +279,7 @@ function downloadAmazonTemplate() {
document.body.removeChild(a)
URL.revokeObjectURL(url)
}
// 组件挂载时获取最新数据
onMounted(async () => {
try {
@@ -345,7 +350,14 @@ onMounted(async () => {
<div class="step-card">
<div class="step-header"><div class="title">导出数据</div></div>
<div class="action-buttons column">
<el-button size="small" class="w100 btn-blue" :disabled="!localProductData.length || loading" @click="exportToExcel">导出Excel</el-button>
<el-button size="small" class="w100 btn-blue" :disabled="!localProductData.length || loading || exportLoading" :loading="exportLoading" @click="exportToExcel">{{ exportLoading ? '导出中...' : '导出Excel' }}</el-button>
<!-- 导出进度条 -->
<div v-if="showExportProgress" class="export-progress">
<div class="export-progress-bar">
<div class="export-progress-fill" :style="{ width: exportProgress + '%' }"></div>
</div>
<div class="export-progress-text">{{ Math.round(exportProgress) }}%</div>
</div>
<el-button size="small" class="w100 btn-blue" :loading="genmaiLoading" @click="openGenmaiSpirit">{{ genmaiLoading ? '启动中...' : '跟卖精灵' }}</el-button>
</div>
</div>
@@ -498,6 +510,10 @@ onMounted(async () => {
.progress-fill { height: 100%; background: #1677FF; border-radius: 999px; transition: width 0.3s ease; }
.progress-text { font-size: 13px; color: #1677FF; font-weight: 500; min-width: 44px; text-align: right; }
.current-status { font-size: 12px; color: #606266; padding-left: 2px; }
.export-progress { display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 0 4px; }
.export-progress-bar { flex: 1; height: 4px; background: #e3eeff; border-radius: 2px; overflow: hidden; }
.export-progress-fill { height: 100%; background: #1677FF; border-radius: 2px; transition: width 0.3s ease; }
.export-progress-text { font-size: 11px; color: #1677FF; font-weight: 500; min-width: 32px; text-align: right; }
.table-container { display: flex; flex-direction: column; flex: 1; min-height: 400px; overflow: hidden; }
.table-section { flex: 1; overflow: hidden; position: relative; background: #fff; border: 1px solid #ebeef5; border-radius: 4px; display: flex; flex-direction: column; }
.table-wrapper { flex: 1; overflow: auto; }
@@ -528,6 +544,7 @@ onMounted(async () => {
.empty-icon { font-size: 48px; margin-bottom: 12px; opacity: 0.6; }
.empty-text { font-size: 14px; color: #909399; }
.empty-abs { position: absolute; left: 0; right: 0; top: 48px; bottom: 0; display: flex; align-items: center; justify-content: center; }
</style>
<script lang="ts">