1
This commit is contained in:
@@ -3,6 +3,7 @@ import { ref, computed, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { zebraApi, type ZebraOrder, type BanmaAccount } from '../../api/zebra'
|
||||
import AccountManager from '../common/AccountManager.vue'
|
||||
import { batchConvertImages } from '../../utils/imageProxy'
|
||||
|
||||
type Shop = { id: string; shopName: string }
|
||||
|
||||
@@ -21,6 +22,7 @@ const showProgress = ref(false)
|
||||
const allOrderData = ref<ZebraOrder[]>([])
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(15)
|
||||
const currentBatchId = ref('')
|
||||
|
||||
// 批量获取状态
|
||||
const fetchCurrentPage = ref(1)
|
||||
@@ -90,6 +92,7 @@ async function fetchData() {
|
||||
allOrderData.value = []
|
||||
fetchCurrentPage.value = 1
|
||||
fetchTotalItems.value = 0
|
||||
currentBatchId.value = `ZEBRA_${Date.now()}`
|
||||
|
||||
const [startDate = '', endDate = ''] = dateRange.value || []
|
||||
await fetchPageData(startDate, endDate)
|
||||
@@ -105,7 +108,8 @@ async function fetchPageData(startDate: string, endDate: string) {
|
||||
endDate,
|
||||
page: fetchCurrentPage.value,
|
||||
pageSize: 50,
|
||||
shopIds: selectedShops.value.join(',')
|
||||
shopIds: selectedShops.value.join(','),
|
||||
batchId: currentBatchId.value
|
||||
})
|
||||
|
||||
const orders = data.orders || []
|
||||
@@ -143,14 +147,103 @@ function stopFetch() {
|
||||
// 进度条保留显示,不自动隐藏
|
||||
}
|
||||
|
||||
|
||||
function showMessage(message: string, type: 'info' | 'success' | 'warning' | 'error' = 'info') {
|
||||
ElMessage({ message, type })
|
||||
}
|
||||
|
||||
async function exportToExcel() {
|
||||
if (!allOrderData.value.length) return
|
||||
if (!allOrderData.value.length) {
|
||||
showMessage('没有数据可供导出', 'warning')
|
||||
return
|
||||
}
|
||||
|
||||
exportLoading.value = true
|
||||
|
||||
try {
|
||||
const result = await zebraApi.exportAndSaveOrders({ orders: allOrderData.value })
|
||||
ElMessage({ message: `Excel文件已保存到: ${result.filePath}` as any, type: 'success' })
|
||||
} catch (e: any) {
|
||||
ElMessage({ message: e?.message || '导出Excel失败', type: 'error' })
|
||||
const ExcelJS = (await import('exceljs')).default
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const worksheet = workbook.addWorksheet('斑马订单数据')
|
||||
|
||||
worksheet.columns = [
|
||||
{ header: '下单时间', key: 'orderedAt', width: 15 },
|
||||
{ header: '商品图片', key: 'image', width: 15 },
|
||||
{ header: '商品名称', key: 'productTitle', width: 25 },
|
||||
{ header: '乐天订单号', key: 'shopOrderNumber', width: 20 },
|
||||
{ header: '下单距今', key: 'timeSinceOrder', width: 12 },
|
||||
{ header: '订单金额/日元', key: 'priceJpy', width: 15 },
|
||||
{ header: '数量', key: 'productQuantity', width: 8 },
|
||||
{ header: '税费/日元', key: 'shippingFeeJpy', width: 12 },
|
||||
{ header: '回款抽点rmb', key: 'serviceFee', width: 15 },
|
||||
{ header: '商品番号', key: 'productNumber', width: 15 },
|
||||
{ header: '1688订单号', key: 'poNumber', width: 15 },
|
||||
{ header: '采购金额/rmb', key: 'shippingFeeCny', width: 15 },
|
||||
{ header: '国际运费/rmb', key: 'internationalShippingFee', width: 15 },
|
||||
{ header: '国内物流', key: 'poLogisticsCompany', width: 12 },
|
||||
{ header: '国内单号', key: 'poTrackingNumber', width: 15 },
|
||||
{ header: '日本单号', key: 'internationalTrackingNumber', width: 15 },
|
||||
{ header: '地址状态', key: 'trackInfo', width: 12 }
|
||||
]
|
||||
|
||||
const imageUrls = allOrderData.value.map(order => order.productImage || '')
|
||||
const imageBase64s = await batchConvertImages(imageUrls, 80)
|
||||
|
||||
for (let i = 0; i < allOrderData.value.length; i++) {
|
||||
const order = allOrderData.value[i]
|
||||
const base64Image = imageBase64s[i]
|
||||
|
||||
const row = worksheet.addRow({
|
||||
orderedAt: order.orderedAt || '',
|
||||
image: base64Image ? '图片' : '无图片',
|
||||
productTitle: order.productTitle || '',
|
||||
shopOrderNumber: order.shopOrderNumber || '',
|
||||
timeSinceOrder: order.timeSinceOrder || '',
|
||||
priceJpy: formatJpy(order.priceJpy),
|
||||
productQuantity: order.productQuantity || 0,
|
||||
shippingFeeJpy: formatJpy(order.shippingFeeJpy),
|
||||
serviceFee: order.serviceFee || '',
|
||||
productNumber: order.productNumber || '',
|
||||
poNumber: order.poNumber || '',
|
||||
shippingFeeCny: formatCny(order.shippingFeeCny),
|
||||
internationalShippingFee: order.internationalShippingFee || '',
|
||||
poLogisticsCompany: order.poLogisticsCompany || '',
|
||||
poTrackingNumber: order.poTrackingNumber || '',
|
||||
internationalTrackingNumber: order.internationalTrackingNumber || '',
|
||||
trackInfo: order.trackInfo || ''
|
||||
})
|
||||
|
||||
if (base64Image) {
|
||||
const base64Data = base64Image.split(',')[1]
|
||||
if (base64Data) {
|
||||
const imageId = workbook.addImage({
|
||||
base64: base64Data,
|
||||
extension: 'jpeg',
|
||||
})
|
||||
|
||||
worksheet.addImage(imageId, {
|
||||
tl: { col: 1, row: row.number - 1 },
|
||||
ext: { width: 60, height: 60 }
|
||||
})
|
||||
|
||||
row.height = 50
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const blob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = `斑马订单数据_${new Date().toISOString().slice(0, 10)}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(link.href)
|
||||
|
||||
showMessage('Excel文件导出成功!', 'success')
|
||||
} catch (error) {
|
||||
showMessage('导出失败', 'error')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
@@ -160,7 +253,8 @@ onMounted(async () => {
|
||||
await loadAccounts()
|
||||
try {
|
||||
const latest = await zebraApi.getLatestOrders()
|
||||
allOrderData.value = latest?.orders || []
|
||||
const data = (latest as any)?.data || latest
|
||||
allOrderData.value = data?.orders || []
|
||||
} catch {}
|
||||
})
|
||||
|
||||
@@ -298,9 +392,10 @@ async function removeCurrentAccount() {
|
||||
<div class="step-index">4</div>
|
||||
<div class="step-body">
|
||||
<div class="step-title">导出数据</div>
|
||||
<div class="tip">点击下方按钮,可导出数据为 Excel。</div>
|
||||
<div class="tip">点击下方按钮导出所有订单数据到 Excel 文件</div>
|
||||
<div class="btn-col">
|
||||
<el-button size="small" type="success" :disabled="exportLoading || !allOrderData.length" @click="exportToExcel" class="w100">导出数据</el-button>
|
||||
<el-button size="small" type="success" :disabled="exportLoading || !allOrderData.length" :loading="exportLoading" @click="exportToExcel" class="w100">{{ exportLoading ? '导出中...' : '导出数据' }}</el-button>
|
||||
<!-- 导出进度条 -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -518,6 +613,10 @@ export default {
|
||||
.progress-bar { flex: 1; height: 6px; background: #e3eeff; border-radius: 999px; overflow: hidden; }
|
||||
.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; }
|
||||
.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: #67c23a; border-radius: 2px; transition: width 0.3s ease; }
|
||||
.export-progress-text { font-size: 11px; color: #67c23a; font-weight: 500; min-width: 32px; text-align: right; }
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user