feat: 运单管理支持获取下游文件
All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m39s
All checks were successful
Build and Deploy Front / deploy (push) Successful in 5m39s
工具栏增加获取下游面单/末端面单/POD,并修复语言包热更新后按钮显示 key。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b9702cd0bc
commit
631d113eea
@ -369,6 +369,55 @@ export async function postOrderDownstreamForwardCreateOne(
|
||||
}
|
||||
}
|
||||
|
||||
/** getFile type:下游面单 / 末端面单 / POD */
|
||||
export const DOWNSTREAM_GET_FILE_TYPES = [
|
||||
{ value: 21, labelKey: 'order.myOrders.actions.getDownstreamFileType.downstreamLabel' },
|
||||
{ value: 31, labelKey: 'order.myOrders.actions.getDownstreamFileType.lastMileLabel' },
|
||||
{ value: 180, labelKey: 'order.myOrders.actions.getDownstreamFileType.pod' },
|
||||
] as const
|
||||
|
||||
export type DownstreamGetFileType = (typeof DOWNSTREAM_GET_FILE_TYPES)[number]['value']
|
||||
|
||||
export interface OrderDownstreamGetFileResult {
|
||||
success?: boolean
|
||||
supplierCode?: string
|
||||
type?: number
|
||||
fileType?: string
|
||||
url?: string
|
||||
requestJson?: string
|
||||
statusCode?: number
|
||||
responseBody?: string
|
||||
storedFileUrl?: string
|
||||
downstreamServiceNo?: string
|
||||
trackNo?: string
|
||||
}
|
||||
|
||||
/** POST /order/downstream-forward-get-file → standardCode=getFile,转存 COS 并回写单号 */
|
||||
export async function postOrderDownstreamGetFile(body: {
|
||||
id: number | string
|
||||
type: DownstreamGetFileType
|
||||
}): Promise<OrderDownstreamGetFileResult> {
|
||||
const res = await axiosInstance.post(orderUrl('/order/downstream-forward-get-file'), {
|
||||
id: body.id,
|
||||
type: body.type,
|
||||
})
|
||||
assertBusinessOk(res.data)
|
||||
const d = res.data?.data ?? res.data?.Data ?? res.data ?? {}
|
||||
return {
|
||||
success: d.success ?? d.Success,
|
||||
supplierCode: d.supplierCode ?? d.SupplierCode,
|
||||
type: d.type ?? d.Type,
|
||||
fileType: d.fileType ?? d.FileType,
|
||||
url: d.url ?? d.Url,
|
||||
requestJson: d.requestJson ?? d.RequestJson,
|
||||
statusCode: d.statusCode ?? d.StatusCode,
|
||||
responseBody: d.responseBody ?? d.ResponseBody,
|
||||
storedFileUrl: d.storedFileUrl ?? d.StoredFileUrl,
|
||||
downstreamServiceNo: d.downstreamServiceNo ?? d.DownstreamServiceNo,
|
||||
trackNo: d.trackNo ?? d.TrackNo,
|
||||
}
|
||||
}
|
||||
|
||||
export interface OrderBatchActionFailure {
|
||||
orderId?: number
|
||||
OrderId?: number
|
||||
|
||||
@ -82,6 +82,7 @@ export const PERMISSION_ACTION_LABELS: Record<string, string> = {
|
||||
ChainPull: '串联拉取',
|
||||
CreateTrack: '创建轨迹',
|
||||
ForwardDownstream: '预报下游',
|
||||
GetDownstreamFile: '获取下游文件',
|
||||
MarkProblematic: '创建问题件',
|
||||
MarkClaimed: '创建理赔件',
|
||||
MarkProcessed: '标记已处理',
|
||||
@ -555,6 +556,7 @@ const CORE_GROUPS: PageButtonGroup[] = [
|
||||
{ code: 'PreDeclare', name: '预报' },
|
||||
{ code: 'CreateTrack', name: '创建轨迹订单' },
|
||||
{ code: 'ForwardDownstream', name: '预报下游订单' },
|
||||
{ code: 'GetDownstreamFile', name: '获取下游文件' },
|
||||
{ code: 'Print', name: '单个打印' },
|
||||
{ code: 'BatchPrint', name: '批量打印' },
|
||||
{ code: 'Intercept', name: '拦截' },
|
||||
|
||||
@ -1743,7 +1743,14 @@ export default {
|
||||
'order.myOrders.actions.predeclare': 'Re-predeclare',
|
||||
'order.myOrders.actions.createTrackOrder': 'Create track order',
|
||||
'order.myOrders.actions.forwardDownstreamCreate': 'Forward Downstream',
|
||||
'order.myOrders.actions.getDownstreamFile': 'Get Downstream File',
|
||||
'order.myOrders.actions.getDownstreamFileType.downstreamLabel': 'Get Downstream Label',
|
||||
'order.myOrders.actions.getDownstreamFileType.lastMileLabel': 'Get Last-mile Label',
|
||||
'order.myOrders.actions.getDownstreamFileType.pod': 'Get POD',
|
||||
'order.myOrders.modal.downstreamForwardTitle': 'Downstream forward result',
|
||||
'order.myOrders.modal.getDownstreamFileTitle': 'Get Downstream File Result',
|
||||
'order.myOrders.message.getDownstreamFileNeedSelect': 'Please select orders first',
|
||||
|
||||
'order.myOrders.modal.payTitle': 'Payment confirmation',
|
||||
'order.myOrders.modal.payOrderTotal': 'Amount due',
|
||||
'order.myOrders.modal.payGrandTotal': 'Total due',
|
||||
|
||||
@ -73,4 +73,18 @@ export async function initPreferredLocale(): Promise<void> {
|
||||
i18n.global.locale.value = 'en-US';
|
||||
}
|
||||
|
||||
/** 开发态:语言包热更新后立即灌入 i18n,避免按钮显示 key */
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept('./zh-CN', (mod) => {
|
||||
if (!mod?.default) return;
|
||||
i18n.global.setLocaleMessage('zh-CN', mod.default);
|
||||
fullLocaleLoaded.add('zh-CN-full');
|
||||
});
|
||||
import.meta.hot.accept('./en-US', (mod) => {
|
||||
if (!mod?.default) return;
|
||||
i18n.global.setLocaleMessage('en-US', mod.default);
|
||||
fullLocaleLoaded.add('en-US-full');
|
||||
});
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
|
||||
@ -1571,7 +1571,14 @@ export default {
|
||||
'order.myOrders.actions.predeclare': '重新预报',
|
||||
'order.myOrders.actions.createTrackOrder': '创建轨迹订单',
|
||||
'order.myOrders.actions.forwardDownstreamCreate': '预报下游',
|
||||
'order.myOrders.actions.getDownstreamFile': '获取下游文件',
|
||||
'order.myOrders.actions.getDownstreamFileType.downstreamLabel': '获取下游面单',
|
||||
'order.myOrders.actions.getDownstreamFileType.lastMileLabel': '获取末端面单',
|
||||
'order.myOrders.actions.getDownstreamFileType.pod': '获取POD',
|
||||
'order.myOrders.modal.downstreamForwardTitle': '下游预报结果',
|
||||
'order.myOrders.modal.getDownstreamFileTitle': '获取下游文件结果',
|
||||
'order.myOrders.message.getDownstreamFileNeedSelect': '请先选择订单',
|
||||
|
||||
'order.myOrders.modal.payTitle': '支付确认',
|
||||
'order.myOrders.modal.payOrderTotal': '应付合计',
|
||||
'order.myOrders.modal.payGrandTotal': '合计应付',
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
postOrderExport,
|
||||
postOrderTrackUpsertSmallBag,
|
||||
postOrderDownstreamForwardCreateOne,
|
||||
postOrderDownstreamGetFile,
|
||||
DOWNSTREAM_GET_FILE_TYPES,
|
||||
postOrderBatchJob,
|
||||
waitOrderBatchJob,
|
||||
formatBatchJobTrackUpsertResultText,
|
||||
@ -53,6 +55,8 @@
|
||||
postOrderHandleStatusUpdate,
|
||||
type OrderTrackUpsertResult,
|
||||
type OrderDownstreamForwardResult,
|
||||
type OrderDownstreamGetFileResult,
|
||||
type DownstreamGetFileType,
|
||||
} from '@/api/order';
|
||||
import { notifyCustomerBalanceChanged } from '@/api/customer/accountFlow';
|
||||
import { buildFailGuideFromReason } from '@/utils/parcelCreateFailGuide';
|
||||
@ -937,6 +941,87 @@
|
||||
}).catch(() => undefined);
|
||||
};
|
||||
|
||||
const getDownstreamFileType = ref<DownstreamGetFileType>(21);
|
||||
const getDownstreamFileModalVisible = ref(false);
|
||||
const getDownstreamFileResultText = ref('');
|
||||
|
||||
function tx(key: string, fallback: string) {
|
||||
return te(key) ? t(key) : fallback;
|
||||
}
|
||||
|
||||
function getDownstreamFileTypeFallback(type: DownstreamGetFileType) {
|
||||
if (type === 31) return '获取末端面单';
|
||||
if (type === 180) return '获取POD';
|
||||
return '获取下游面单';
|
||||
}
|
||||
|
||||
const getDownstreamFileTypeLabel = computed(() => {
|
||||
const hit = DOWNSTREAM_GET_FILE_TYPES.find((x) => x.value === getDownstreamFileType.value);
|
||||
if (!hit) {
|
||||
return tx(
|
||||
'order.myOrders.actions.getDownstreamFileType.downstreamLabel',
|
||||
'获取下游面单',
|
||||
);
|
||||
}
|
||||
return tx(hit.labelKey, getDownstreamFileTypeFallback(hit.value));
|
||||
});
|
||||
|
||||
function formatGetDownstreamFileResult(
|
||||
waybillNo: string,
|
||||
result: OrderDownstreamGetFileResult,
|
||||
type: DownstreamGetFileType,
|
||||
): string {
|
||||
const lines = [
|
||||
`【${waybillNo || '-'}】`,
|
||||
result.success ? '成功' : '失败',
|
||||
`standardCode:getFile`,
|
||||
`type:${result.type ?? type}`,
|
||||
];
|
||||
if (result.supplierCode) {
|
||||
lines.push(`supplierCode:${result.supplierCode}`);
|
||||
}
|
||||
if (result.downstreamServiceNo) {
|
||||
lines.push(`服务商单号:${result.downstreamServiceNo}`);
|
||||
}
|
||||
if (result.trackNo) {
|
||||
lines.push(`跟踪号:${result.trackNo}`);
|
||||
}
|
||||
if (result.storedFileUrl) {
|
||||
lines.push(`已存文件:${result.storedFileUrl}`);
|
||||
}
|
||||
lines.push(`请求:${result.url || '-'}`);
|
||||
if (result.requestJson) {
|
||||
lines.push(`请求体:\n${result.requestJson}`);
|
||||
}
|
||||
lines.push(`HTTP:${result.statusCode ?? '-'}`);
|
||||
if (result.responseBody) {
|
||||
lines.push(`响应:\n${result.responseBody}`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
const handleGetDownstreamFile = async (type: DownstreamGetFileType) => {
|
||||
const rows = requireSelectedRows();
|
||||
if (!rows.length) return;
|
||||
getDownstreamFileType.value = type;
|
||||
await withOrderActionLoading('getDownstreamFile', async () => {
|
||||
const resultBlocks: string[] = [];
|
||||
for (const row of rows) {
|
||||
const id = getOrderRowId(row)!;
|
||||
const waybillNo = row.waybillNo || row.serviceNo || String(id);
|
||||
try {
|
||||
const result = await postOrderDownstreamGetFile({ id, type });
|
||||
resultBlocks.push(formatGetDownstreamFileResult(waybillNo, result, type));
|
||||
} catch (err: any) {
|
||||
resultBlocks.push(`【${waybillNo}】失败:${err?.message || '请求异常'}`);
|
||||
}
|
||||
}
|
||||
getDownstreamFileResultText.value = resultBlocks.join('\n\n');
|
||||
getDownstreamFileModalVisible.value = true;
|
||||
await refreshListAndTabCounts();
|
||||
}).catch(() => undefined);
|
||||
};
|
||||
|
||||
function getOrderRowId(row: any): number | string | undefined {
|
||||
if (row == null) return undefined;
|
||||
const id = row.id ?? row.Id;
|
||||
@ -1986,6 +2071,28 @@
|
||||
:disabled="selectedRowCount === 0 || isActionBusy('batchPrint')"
|
||||
@click="handleBatchPrint"
|
||||
>{{ t('order.myOrders.actions.batchPrint') }}</a-button>
|
||||
<a-dropdown
|
||||
trigger="click"
|
||||
position="bl"
|
||||
:disabled="selectedRowCount === 0 || !!actionLoadingKey"
|
||||
>
|
||||
<a-button
|
||||
class="app-btn-toolbar btn-more"
|
||||
:loading="isActionLoading('getDownstreamFile')"
|
||||
:disabled="selectedRowCount === 0 || isActionBusy('getDownstreamFile')"
|
||||
>
|
||||
{{ getDownstreamFileTypeLabel }}
|
||||
<icon-down class="btn-more-arrow" />
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption
|
||||
v-for="opt in DOWNSTREAM_GET_FILE_TYPES"
|
||||
:key="opt.value"
|
||||
:disabled="selectedRowCount === 0 || isActionBusy('getDownstreamFile')"
|
||||
@click="handleGetDownstreamFile(opt.value)"
|
||||
>{{ tx(opt.labelKey, getDownstreamFileTypeFallback(opt.value)) }}</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<a-dropdown trigger="click" position="bl" :disabled="!!actionLoadingKey">
|
||||
<a-button
|
||||
class="app-btn-toolbar btn-more"
|
||||
@ -2186,6 +2293,15 @@
|
||||
<pre class="track-upsert-result">{{ downstreamForwardResultText }}</pre>
|
||||
</a-modal>
|
||||
|
||||
<a-modal
|
||||
v-model:visible="getDownstreamFileModalVisible"
|
||||
:title="tx('order.myOrders.modal.getDownstreamFileTitle', '获取下游文件结果')"
|
||||
:width="800"
|
||||
:footer="false"
|
||||
>
|
||||
<pre class="track-upsert-result">{{ getDownstreamFileResultText }}</pre>
|
||||
</a-modal>
|
||||
|
||||
<MarkProblematicModal
|
||||
v-if="problematicModalVisible"
|
||||
v-model:visible="problematicModalVisible"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user