增加订单号查询
This commit is contained in:
@@ -195,6 +195,7 @@ export function fetchAdminCloudtentaclesDeliveryRecords(payload: {
|
||||
size?: number
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
platformOrderId?: string
|
||||
}) {
|
||||
return apiPost<AdminCloudtentaclesDeliveryRecordListResult>(
|
||||
'/api/v1/admin/cloudtentacles-records',
|
||||
|
||||
@@ -137,6 +137,22 @@ export interface AdminCloudtentaclesDeliveryRecordItem {
|
||||
status: number
|
||||
fulfillUser: string
|
||||
operatorName: string
|
||||
platformOrderId: string
|
||||
taskId: number
|
||||
taskNo: string
|
||||
orderShopId: string
|
||||
orderShopName: string
|
||||
consumeShopId: string
|
||||
consumeShopName: string
|
||||
roleName: string
|
||||
roleId: string
|
||||
localTaskStatus: string
|
||||
localDeliveryStatus: string
|
||||
localDispatchStatus: string
|
||||
localDispatchAt: string
|
||||
localResultCode: string
|
||||
localResultMessage: string
|
||||
matchConfidence: string
|
||||
raw: Record<string, unknown>
|
||||
}
|
||||
|
||||
@@ -145,6 +161,10 @@ export interface AdminCloudtentaclesDeliveryRecordListResult {
|
||||
page: number
|
||||
size: number
|
||||
total: number
|
||||
sourceKey?: string
|
||||
queryStartDate?: string
|
||||
queryEndDate?: string
|
||||
localOrderMatched?: boolean
|
||||
items: AdminCloudtentaclesDeliveryRecordItem[]
|
||||
raw: Record<string, unknown>
|
||||
}
|
||||
|
||||
+100
-12
@@ -23,6 +23,7 @@ const loading = ref(false)
|
||||
const sourceLoading = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const sourceKey = ref('')
|
||||
const platformOrderId = ref('')
|
||||
const dateRange = ref<[string, string]>(createDefaultDateRange())
|
||||
const page = ref(1)
|
||||
const pageSize = ref(100)
|
||||
@@ -58,7 +59,8 @@ async function loadSources() {
|
||||
}
|
||||
|
||||
async function loadRecords(nextPage = page.value) {
|
||||
if (!sourceKey.value) {
|
||||
const orderKeyword = platformOrderId.value.trim()
|
||||
if (!sourceKey.value && !orderKeyword) {
|
||||
showError('请先选择 cloudtentacles 账号')
|
||||
return
|
||||
}
|
||||
@@ -74,12 +76,16 @@ async function loadRecords(nextPage = page.value) {
|
||||
|
||||
try {
|
||||
const response = await fetchAdminCloudtentaclesDeliveryRecords({
|
||||
sourceKey: sourceKey.value,
|
||||
sourceKey: sourceKey.value || undefined,
|
||||
page: nextPage,
|
||||
size: pageSize.value,
|
||||
startDate,
|
||||
endDate,
|
||||
platformOrderId: orderKeyword || undefined,
|
||||
})
|
||||
if (response.data.sourceKey && sourceKey.value !== response.data.sourceKey) {
|
||||
sourceKey.value = response.data.sourceKey
|
||||
}
|
||||
page.value = response.data.page
|
||||
pageSize.value = response.data.size
|
||||
total.value = response.data.total
|
||||
@@ -92,6 +98,7 @@ async function loadRecords(nextPage = page.value) {
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
platformOrderId.value = ''
|
||||
dateRange.value = createDefaultDateRange()
|
||||
page.value = 1
|
||||
pageSize.value = 100
|
||||
@@ -145,6 +152,22 @@ function getStatusType(status: number) {
|
||||
return 'info'
|
||||
}
|
||||
|
||||
function getLocalDispatchStatusLabel(status: string) {
|
||||
const normalized = String(status || '').trim()
|
||||
if (normalized === 'success') return '本地已发货'
|
||||
if (normalized === 'failed') return '本地发货失败'
|
||||
if (normalized === 'pending') return '本地待发货'
|
||||
return normalized || '-'
|
||||
}
|
||||
|
||||
function getMatchConfidenceLabel(value: string) {
|
||||
if (value === 'high') return '高'
|
||||
if (value === 'medium') return '中'
|
||||
if (value === 'low') return '低'
|
||||
if (value === 'local') return '本地'
|
||||
return ''
|
||||
}
|
||||
|
||||
function createDefaultDateRange(): [string, string] {
|
||||
const end = new Date()
|
||||
const start = new Date(end)
|
||||
@@ -165,7 +188,7 @@ async function drawRecordImage(record: AdminCloudtentaclesDeliveryRecordItem) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const scale = window.devicePixelRatio || 1
|
||||
const width = 720
|
||||
const height = 260
|
||||
const height = 330
|
||||
canvas.width = width * scale
|
||||
canvas.height = height * scale
|
||||
canvas.style.width = `${width}px`
|
||||
@@ -193,6 +216,7 @@ async function drawRecordImage(record: AdminCloudtentaclesDeliveryRecordItem) {
|
||||
ctx.textAlign = 'left'
|
||||
|
||||
drawTicketCard(ctx, record, productImage)
|
||||
drawRecordMeta(ctx, record)
|
||||
return canvas.toDataURL('image/png')
|
||||
}
|
||||
|
||||
@@ -246,7 +270,7 @@ function drawTicketCard(
|
||||
ctx.textAlign = 'left'
|
||||
|
||||
const contentX = x + imageWidth + 16
|
||||
const orderText = `订单号:${record.virtualNumberId || record.recordId.slice(-6) || '-'}`
|
||||
const orderText = `订单号:${record.platformOrderId || record.recordId.slice(-8) || '-'}`
|
||||
ctx.fillStyle = '#1d5ea8'
|
||||
ctx.font = '16px sans-serif'
|
||||
drawEllipsisText(ctx, record.name || '未命名商品', contentX, y + 31, 170)
|
||||
@@ -275,6 +299,23 @@ function drawTicketCard(
|
||||
drawEllipsisText(ctx, `账号:${record.fulfillUser || record.phone || '-'}`, contentX, y + 90, 250)
|
||||
}
|
||||
|
||||
function drawRecordMeta(ctx: CanvasRenderingContext2D, record: AdminCloudtentaclesDeliveryRecordItem) {
|
||||
const left = 80
|
||||
const top = 250
|
||||
const lineHeight = 22
|
||||
const values = [
|
||||
`订单店铺:${record.orderShopName || record.orderShopId || '-'}`,
|
||||
`核销店铺:${record.consumeShopName || record.consumeShopId || '-'}`,
|
||||
`绑定角色:${record.roleName || record.fulfillUser || '-'}${record.roleId ? `(${record.roleId})` : ''}`,
|
||||
]
|
||||
|
||||
ctx.fillStyle = '#374151'
|
||||
ctx.font = '13px sans-serif'
|
||||
values.forEach((value, index) => {
|
||||
drawEllipsisText(ctx, value, left, top + index * lineHeight, 560)
|
||||
})
|
||||
}
|
||||
|
||||
async function loadRecordProductImage(imageUrl: string) {
|
||||
const normalizedUrl = String(imageUrl || '').trim()
|
||||
if (!normalizedUrl) {
|
||||
@@ -352,7 +393,9 @@ function drawEllipsisText(
|
||||
|
||||
function buildRecordImageFileName(record: AdminCloudtentaclesDeliveryRecordItem) {
|
||||
const name = sanitizeFileName(record.name || '发货记录')
|
||||
const id = sanitizeFileName(record.recordId.slice(0, 8) || String(record.virtualNumberId || 'record'))
|
||||
const id = sanitizeFileName(
|
||||
record.platformOrderId || record.recordId.slice(0, 8) || String(record.virtualNumberId || 'record'),
|
||||
)
|
||||
return `${name}-${id}.png`
|
||||
}
|
||||
|
||||
@@ -370,7 +413,7 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<div class="cloud-records-page list-page">
|
||||
<AdminPageHeader title="查询发货记录" description="按 cloudtentacles 账号和时间范围查询平台发货记录。">
|
||||
<AdminPageHeader title="查询发货记录" description="按订单号、cloudtentacles 账号和时间范围查询平台发货记录。">
|
||||
<template #extra>
|
||||
<span class="total-badge">共 {{ total }} 条记录</span>
|
||||
</template>
|
||||
@@ -380,7 +423,7 @@ onMounted(async () => {
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">查询条件</span>
|
||||
<span class="card-desc">查询 cloudtentacles 的已发货记录,记录码默认使用平台发货记录。</span>
|
||||
<span class="card-desc">输入订单号时会先关联本地任务,再匹配 cloudtentacles 发货记录。</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -399,6 +442,13 @@ onMounted(async () => {
|
||||
:disabled="!source.enabled || !source.hasToken"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-model.trim="platformOrderId"
|
||||
class="filter-control"
|
||||
clearable
|
||||
placeholder="订单号"
|
||||
@keyup.enter="loadRecords(1)"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
class="filter-control cloud-records-date-range"
|
||||
@@ -450,6 +500,24 @@ onMounted(async () => {
|
||||
<span class="cell-subline" :title="row.fulfillUser">
|
||||
账号:{{ row.fulfillUser || '-' }}
|
||||
</span>
|
||||
<span v-if="row.roleName || row.roleId" class="cell-subline" :title="`${row.roleName} ${row.roleId}`">
|
||||
角色:{{ row.roleName || '-' }}{{ row.roleId ? `(${row.roleId})` : '' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单 / 店铺" min-width="260">
|
||||
<template #default="{ row }">
|
||||
<div class="cell-stack">
|
||||
<span class="cell-title" :title="row.platformOrderId">
|
||||
{{ row.platformOrderId || '-' }}
|
||||
</span>
|
||||
<span class="cell-subline" :title="row.orderShopName || row.orderShopId">
|
||||
订单店铺:{{ row.orderShopName || row.orderShopId || '-' }}
|
||||
</span>
|
||||
<span class="cell-subline" :title="row.consumeShopName || row.consumeShopId">
|
||||
核销店铺:{{ row.consumeShopName || row.consumeShopId || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -463,9 +531,14 @@ onMounted(async () => {
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" effect="plain">
|
||||
{{ getStatusLabel(row.status) }}
|
||||
</el-tag>
|
||||
<div class="status-stack">
|
||||
<el-tag :type="getStatusType(row.status)" effect="plain">
|
||||
{{ getStatusLabel(row.status) }}
|
||||
</el-tag>
|
||||
<span v-if="row.localDispatchStatus" class="cell-subline">
|
||||
{{ getLocalDispatchStatusLabel(row.localDispatchStatus) }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作人" min-width="120">
|
||||
@@ -476,7 +549,15 @@ onMounted(async () => {
|
||||
</el-table-column>
|
||||
<el-table-column label="记录 ID" min-width="210">
|
||||
<template #default="{ row }">
|
||||
<span class="cell-subline" :title="row.recordId">{{ row.recordId || '-' }}</span>
|
||||
<div class="cell-stack">
|
||||
<span class="cell-subline" :title="row.recordId">{{ row.recordId || '-' }}</span>
|
||||
<span v-if="row.taskNo" class="cell-subline" :title="row.taskNo">
|
||||
任务:{{ row.taskNo }}
|
||||
<template v-if="getMatchConfidenceLabel(row.matchConfidence)">
|
||||
· 匹配{{ getMatchConfidenceLabel(row.matchConfidence) }}
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="136" fixed="right">
|
||||
@@ -519,7 +600,7 @@ onMounted(async () => {
|
||||
@import '@/styles/admin-list-pages.css';
|
||||
|
||||
.cloud-records-filter {
|
||||
grid-template-columns: minmax(180px, 0.34fr) minmax(360px, 1fr) auto;
|
||||
grid-template-columns: minmax(180px, 0.28fr) minmax(220px, 0.36fr) minmax(360px, 1fr) auto;
|
||||
}
|
||||
|
||||
.cloud-records-date-range {
|
||||
@@ -549,6 +630,13 @@ onMounted(async () => {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.status-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.cloud-records-filter {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
Reference in New Issue
Block a user