fix: polish order detail drawer track/fee UX and drawer flush layout
Remove redundant basic summary, fix empty a-alert content, refine track timeline with status and bilingual copy, and stretch drawers across scrollbar-gutter. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f71d2f1088
commit
f193929351
4
src/api/TrackOrder/typings.d.ts
vendored
4
src/api/TrackOrder/typings.d.ts
vendored
@ -21,6 +21,10 @@ declare namespace API {
|
|||||||
type GetDetailTimelineOutput = {
|
type GetDetailTimelineOutput = {
|
||||||
/** 轨迹编码 */
|
/** 轨迹编码 */
|
||||||
trackCode?: string;
|
trackCode?: string;
|
||||||
|
/** 轨迹状态 */
|
||||||
|
trackStatus?: string;
|
||||||
|
/** 轨迹状态 code */
|
||||||
|
trackStatusCode?: string;
|
||||||
/** 轨迹内容 */
|
/** 轨迹内容 */
|
||||||
content?: string;
|
content?: string;
|
||||||
/** 轨迹英文内容 */
|
/** 轨迹英文内容 */
|
||||||
|
|||||||
4
src/api/interface-trackOrder/typings.d.ts
vendored
4
src/api/interface-trackOrder/typings.d.ts
vendored
@ -20,6 +20,10 @@ declare namespace API {
|
|||||||
type GetDetailTimelineOutput = {
|
type GetDetailTimelineOutput = {
|
||||||
/** 轨迹编码 */
|
/** 轨迹编码 */
|
||||||
trackCode?: string;
|
trackCode?: string;
|
||||||
|
/** 轨迹状态 */
|
||||||
|
trackStatus?: string;
|
||||||
|
/** 轨迹状态 code */
|
||||||
|
trackStatusCode?: string;
|
||||||
/** 轨迹内容 */
|
/** 轨迹内容 */
|
||||||
content?: string;
|
content?: string;
|
||||||
/** 轨迹英文内容 */
|
/** 轨迹英文内容 */
|
||||||
|
|||||||
@ -159,6 +159,17 @@ body .arco-drawer {
|
|||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* index.html 为防 boot/居中抖动给 html 加了 scrollbar-gutter: stable,
|
||||||
|
* Chromium 下 fixed 容器会被收窄一截 gutter(约 15px),抽屉 right:0 仍贴容器右缘,
|
||||||
|
* 视觉上就在屏幕右边界留出缝。用 100vw 铺满视觉视口。
|
||||||
|
*/
|
||||||
|
body .arco-drawer-container {
|
||||||
|
width: 100vw;
|
||||||
|
left: 0;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/* vxe table wrapper */
|
/* vxe table wrapper */
|
||||||
body .vxe-table--border,
|
body .vxe-table--border,
|
||||||
body .vxe-grid {
|
body .vxe-grid {
|
||||||
|
|||||||
@ -1895,6 +1895,7 @@ export default {
|
|||||||
'order.myOrders.drawer.track.remark': 'Remark',
|
'order.myOrders.drawer.track.remark': 'Remark',
|
||||||
'order.myOrders.drawer.track.code': 'Track code',
|
'order.myOrders.drawer.track.code': 'Track code',
|
||||||
'order.myOrders.drawer.track.timezone': 'TZ {zone}',
|
'order.myOrders.drawer.track.timezone': 'TZ {zone}',
|
||||||
|
'order.myOrders.drawer.track.statusUnknown': 'Update',
|
||||||
'order.myOrders.drawer.weightLength': 'Length(cm)',
|
'order.myOrders.drawer.weightLength': 'Length(cm)',
|
||||||
'order.myOrders.drawer.weightWidth': 'Width(cm)',
|
'order.myOrders.drawer.weightWidth': 'Width(cm)',
|
||||||
'order.myOrders.drawer.weightHeight': 'Height(cm)',
|
'order.myOrders.drawer.weightHeight': 'Height(cm)',
|
||||||
@ -2192,7 +2193,7 @@ export default {
|
|||||||
'order.placeOrder.batch.stepTemplate': 'Select template',
|
'order.placeOrder.batch.stepTemplate': 'Select template',
|
||||||
'order.placeOrder.batch.stepUpload': 'Upload Excel',
|
'order.placeOrder.batch.stepUpload': 'Upload Excel',
|
||||||
'order.placeOrder.batch.stepSubmit': 'Submit',
|
'order.placeOrder.batch.stepSubmit': 'Submit',
|
||||||
'order.placeOrder.batch.guideHint': 'Click a step to jump · pick template on the right, then upload & submit',
|
'order.placeOrder.batch.guideHint': 'Click a step to jump · pick template & sender, then upload & submit',
|
||||||
'order.placeOrder.batch.pickTemplateHint': 'Select a template',
|
'order.placeOrder.batch.pickTemplateHint': 'Select a template',
|
||||||
'order.placeOrder.batch.block.noTemplate': 'Please select an order template on the right first',
|
'order.placeOrder.batch.block.noTemplate': 'Please select an order template on the right first',
|
||||||
'order.placeOrder.batch.block.templateDraft': 'Finish mapping this custom template before submitting',
|
'order.placeOrder.batch.block.templateDraft': 'Finish mapping this custom template before submitting',
|
||||||
@ -2257,6 +2258,11 @@ export default {
|
|||||||
'order.placeOrder.single.hideExtraCols': 'Less',
|
'order.placeOrder.single.hideExtraCols': 'Less',
|
||||||
'order.placeOrder.single.showRecipientOptional': 'More',
|
'order.placeOrder.single.showRecipientOptional': 'More',
|
||||||
'order.placeOrder.single.hideRecipientOptional': 'Less',
|
'order.placeOrder.single.hideRecipientOptional': 'Less',
|
||||||
|
'order.placeOrder.single.saveReceiver': 'Save',
|
||||||
|
'order.placeOrder.single.savingReceiver': 'Saving…',
|
||||||
|
'order.placeOrder.single.saveReceiverRequired': 'Enter recipient name and address line 1 first',
|
||||||
|
'order.placeOrder.single.saveReceiverSuccess': 'Recipient address saved',
|
||||||
|
'order.placeOrder.single.saveReceiverFailed': 'Failed to save recipient address',
|
||||||
'order.placeOrder.single.declarationResizeHint': 'Scroll sideways for more columns; drag bottom to resize height',
|
'order.placeOrder.single.declarationResizeHint': 'Scroll sideways for more columns; drag bottom to resize height',
|
||||||
'order.placeOrder.single.successTitle': 'Order created',
|
'order.placeOrder.single.successTitle': 'Order created',
|
||||||
'order.placeOrder.single.successContent': 'You can view details and status in My Orders.',
|
'order.placeOrder.single.successContent': 'You can view details and status in My Orders.',
|
||||||
|
|||||||
@ -1814,6 +1814,7 @@ export default {
|
|||||||
'order.myOrders.drawer.track.remark': '备注',
|
'order.myOrders.drawer.track.remark': '备注',
|
||||||
'order.myOrders.drawer.track.code': '轨迹代码',
|
'order.myOrders.drawer.track.code': '轨迹代码',
|
||||||
'order.myOrders.drawer.track.timezone': '时区 {zone}',
|
'order.myOrders.drawer.track.timezone': '时区 {zone}',
|
||||||
|
'order.myOrders.drawer.track.statusUnknown': '轨迹更新',
|
||||||
'order.myOrders.drawer.weightLength': '长(cm)',
|
'order.myOrders.drawer.weightLength': '长(cm)',
|
||||||
'order.myOrders.drawer.weightWidth': '宽(cm)',
|
'order.myOrders.drawer.weightWidth': '宽(cm)',
|
||||||
'order.myOrders.drawer.weightHeight': '高(cm)',
|
'order.myOrders.drawer.weightHeight': '高(cm)',
|
||||||
@ -2111,7 +2112,7 @@ export default {
|
|||||||
'order.placeOrder.batch.stepTemplate': '选择模板',
|
'order.placeOrder.batch.stepTemplate': '选择模板',
|
||||||
'order.placeOrder.batch.stepUpload': '上传 Excel',
|
'order.placeOrder.batch.stepUpload': '上传 Excel',
|
||||||
'order.placeOrder.batch.stepSubmit': '提交下单',
|
'order.placeOrder.batch.stepSubmit': '提交下单',
|
||||||
'order.placeOrder.batch.guideHint': '点步骤可定位 · 右侧选模板,左侧上传后提交',
|
'order.placeOrder.batch.guideHint': '点步骤可定位 · 先选模板与发件人,再上传提交',
|
||||||
'order.placeOrder.batch.pickTemplateHint': '请选择模板',
|
'order.placeOrder.batch.pickTemplateHint': '请选择模板',
|
||||||
'order.placeOrder.batch.block.noTemplate': '请先在右侧选择下单模板',
|
'order.placeOrder.batch.block.noTemplate': '请先在右侧选择下单模板',
|
||||||
'order.placeOrder.batch.block.templateDraft': '当前自定义模板待编辑完成映射后才能提交',
|
'order.placeOrder.batch.block.templateDraft': '当前自定义模板待编辑完成映射后才能提交',
|
||||||
@ -2182,6 +2183,11 @@ export default {
|
|||||||
'order.placeOrder.single.declarationSkuFilled': '已填入申报信息,请补充单价等必填项',
|
'order.placeOrder.single.declarationSkuFilled': '已填入申报信息,请补充单价等必填项',
|
||||||
'order.placeOrder.single.showRecipientOptional': '更多',
|
'order.placeOrder.single.showRecipientOptional': '更多',
|
||||||
'order.placeOrder.single.hideRecipientOptional': '收起',
|
'order.placeOrder.single.hideRecipientOptional': '收起',
|
||||||
|
'order.placeOrder.single.saveReceiver': '保存',
|
||||||
|
'order.placeOrder.single.savingReceiver': '保存中…',
|
||||||
|
'order.placeOrder.single.saveReceiverRequired': '请先填写收件人名称和地址1',
|
||||||
|
'order.placeOrder.single.saveReceiverSuccess': '收件地址已保存',
|
||||||
|
'order.placeOrder.single.saveReceiverFailed': '保存收件地址失败',
|
||||||
'order.placeOrder.single.declarationResizeHint': '左右滑动看更多列,底部拖拽调节高度',
|
'order.placeOrder.single.declarationResizeHint': '左右滑动看更多列,底部拖拽调节高度',
|
||||||
'order.placeOrder.single.successTitle': '单票下单成功',
|
'order.placeOrder.single.successTitle': '单票下单成功',
|
||||||
'order.placeOrder.single.successContent': '订单已创建,可前往「我的订单」查看详情与后续状态。',
|
'order.placeOrder.single.successContent': '订单已创建,可前往「我的订单」查看详情与后续状态。',
|
||||||
|
|||||||
@ -160,9 +160,10 @@
|
|||||||
v-for="(w, i) in warningList"
|
v-for="(w, i) in warningList"
|
||||||
:key="i"
|
:key="i"
|
||||||
type="warning"
|
type="warning"
|
||||||
:content="w"
|
|
||||||
class="warn-item"
|
class="warn-item"
|
||||||
/>
|
>
|
||||||
|
{{ w }}
|
||||||
|
</a-alert>
|
||||||
|
|
||||||
<div class="section-title">{{ t('channel.salesProducts.billingSimulate.receivable') }}</div>
|
<div class="section-title">{{ t('channel.salesProducts.billingSimulate.receivable') }}</div>
|
||||||
<a-table
|
<a-table
|
||||||
|
|||||||
@ -290,14 +290,16 @@ function handleCancel() {
|
|||||||
v-if="showInsuranceTip"
|
v-if="showInsuranceTip"
|
||||||
type="info"
|
type="info"
|
||||||
show-icon
|
show-icon
|
||||||
:content="t('order.myOrders.claimed.tipInsured', { amount: declaredSumText })"
|
>
|
||||||
/>
|
{{ t('order.myOrders.claimed.tipInsured', { amount: declaredSumText }) }}
|
||||||
|
</a-alert>
|
||||||
<a-alert
|
<a-alert
|
||||||
v-else-if="showUninsuredTip"
|
v-else-if="showUninsuredTip"
|
||||||
type="warning"
|
type="warning"
|
||||||
show-icon
|
show-icon
|
||||||
:content="t('order.myOrders.claimed.tipUninsured')"
|
>
|
||||||
/>
|
{{ t('order.myOrders.claimed.tipUninsured') }}
|
||||||
|
</a-alert>
|
||||||
<div v-if="declaredSumNumber != null" class="claim-max-hint">
|
<div v-if="declaredSumNumber != null" class="claim-max-hint">
|
||||||
{{ t('order.myOrders.claimed.maxHint', { amount: declaredSumText }) }}
|
{{ t('order.myOrders.claimed.maxHint', { amount: declaredSumText }) }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -36,12 +36,22 @@
|
|||||||
<a-button v-else class="app-btn-search" @click="startBasicEdit">
|
<a-button v-else class="app-btn-search" @click="startBasicEdit">
|
||||||
{{ $t('order.myOrders.drawer.actions.edit') }}
|
{{ $t('order.myOrders.drawer.actions.edit') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button class="app-btn-search" @click="handleAskAdvisor">
|
||||||
|
{{ $t('nanaAssistant.askAboutWaybill') }}
|
||||||
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="activeTab === 'track'">
|
<template v-else-if="activeTab === 'track'">
|
||||||
<span class="toolbar-meta">
|
<span class="toolbar-meta">
|
||||||
<span class="toolbar-meta-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
<span class="toolbar-meta-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
||||||
<span class="toolbar-meta-value">{{ trackOrderNumber || '--' }}</span>
|
<span class="toolbar-meta-value">{{ trackOrderNumber || '--' }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
<a-tag
|
||||||
|
v-if="currentOrderStatusMeta"
|
||||||
|
size="small"
|
||||||
|
:style="getOrderStatusTagStyle(currentOrderStatusMeta)"
|
||||||
|
>
|
||||||
|
{{ $t(currentOrderStatusMeta.labelKey) }}
|
||||||
|
</a-tag>
|
||||||
<a-tag v-if="trackTimeline.length" size="small" color="arcoblue">
|
<a-tag v-if="trackTimeline.length" size="small" color="arcoblue">
|
||||||
{{ $t('order.myOrders.drawer.track.count', { count: trackTimeline.length }) }}
|
{{ $t('order.myOrders.drawer.track.count', { count: trackTimeline.length }) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
@ -66,40 +76,6 @@
|
|||||||
<div class="drawer-tab-content">
|
<div class="drawer-tab-content">
|
||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<div v-if="activeTab === 'basic'" class="tab-panel basic-info">
|
<div v-if="activeTab === 'basic'" class="tab-panel basic-info">
|
||||||
<div class="basic-summary">
|
|
||||||
<div class="basic-summary-top">
|
|
||||||
<div class="basic-summary-main">
|
|
||||||
<span class="basic-summary-label">{{ $t('order.myOrders.drawer.serviceNo') }}</span>
|
|
||||||
<span class="basic-summary-no">{{ getOrderValue('serviceNo') }}</span>
|
|
||||||
</div>
|
|
||||||
<a-tag
|
|
||||||
v-if="currentOrderStatusMeta"
|
|
||||||
size="small"
|
|
||||||
:style="getOrderStatusTagStyle(currentOrderStatusMeta)"
|
|
||||||
>
|
|
||||||
{{ $t(currentOrderStatusMeta.labelKey) }}
|
|
||||||
</a-tag>
|
|
||||||
</div>
|
|
||||||
<div class="basic-summary-chips">
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.clientNo') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('clientNo') }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('trackNo') }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.consigneeCountryName') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('consigneeCountryName') }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="basic-summary-actions">
|
|
||||||
<a-button class="app-btn-search" @click="handleAskAdvisor">{{ $t('nanaAssistant.askAboutWaybill') }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="predeclareFailGuide" class="predeclare-fail-guide">
|
<div v-if="predeclareFailGuide" class="predeclare-fail-guide">
|
||||||
<p class="predeclare-fail-guide__reason">{{ predeclareFailGuide.reason }}</p>
|
<p class="predeclare-fail-guide__reason">{{ predeclareFailGuide.reason }}</p>
|
||||||
<p v-if="predeclareFailGuide.tips?.[0]" class="predeclare-fail-guide__tip">
|
<p v-if="predeclareFailGuide.tips?.[0]" class="predeclare-fail-guide__tip">
|
||||||
@ -116,9 +92,6 @@
|
|||||||
<p class="predeclare-fail-guide__raw">{{ predeclareFailGuide.rawReason }}</p>
|
<p class="predeclare-fail-guide__raw">{{ predeclareFailGuide.rawReason }}</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="predeclare-fail-guide__actions">
|
<div class="predeclare-fail-guide__actions">
|
||||||
<a-button class="app-btn-search" @click="handleAskAdvisor">
|
|
||||||
{{ $t('order.myOrders.drawer.failGuideAskSupport') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button class="app-btn-search" @click="startBasicEdit">
|
<a-button class="app-btn-search" @click="startBasicEdit">
|
||||||
{{ $t('order.myOrders.drawer.failGuideEdit') }}
|
{{ $t('order.myOrders.drawer.failGuideEdit') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -580,10 +553,7 @@
|
|||||||
:class="{ active: isTrackNodeActive(item, i) }"
|
:class="{ active: isTrackNodeActive(item, i) }"
|
||||||
>
|
>
|
||||||
<div class="track-left">
|
<div class="track-left">
|
||||||
<span v-if="isTrackNodeActive(item, i)" class="track-icon active">
|
<span class="track-dot" :class="{ active: isTrackNodeActive(item, i) }" />
|
||||||
<icon-check-circle-fill />
|
|
||||||
</span>
|
|
||||||
<span v-else class="track-icon">{{ displayTrackTimeline.length - i }}</span>
|
|
||||||
<span
|
<span
|
||||||
v-if="i < displayTrackTimeline.length - 1"
|
v-if="i < displayTrackTimeline.length - 1"
|
||||||
class="track-line"
|
class="track-line"
|
||||||
@ -591,29 +561,32 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="track-right">
|
<div class="track-right">
|
||||||
<div class="track-card">
|
<div class="track-row-head">
|
||||||
<div class="track-card-head">
|
<span class="track-status">{{ getTrackStatusLabel(item) }}</span>
|
||||||
<div class="track-title">{{ item.content || '--' }}</div>
|
<a-tag v-if="isTrackNodeActive(item, i)" size="small" color="green">
|
||||||
<a-tag v-if="isTrackNodeActive(item, i)" size="small" color="green">
|
{{ $t('order.myOrders.drawer.track.latest') }}
|
||||||
{{ $t('order.myOrders.drawer.track.latest') }}
|
</a-tag>
|
||||||
</a-tag>
|
</div>
|
||||||
</div>
|
<div v-if="getTrackZhDetail(item)" class="track-content track-content--zh">
|
||||||
<div v-if="formatTrackPlace(item)" class="track-meta track-place">
|
{{ getTrackZhDetail(item) }}
|
||||||
<icon-location class="track-meta-icon" />
|
</div>
|
||||||
<span>{{ formatTrackPlace(item) }}</span>
|
<div v-if="getTrackEnDetail(item)" class="track-content track-content--en">
|
||||||
</div>
|
{{ getTrackEnDetail(item) }}
|
||||||
<div v-if="formatTrackTimeDisplay(item)" class="track-meta track-time">
|
</div>
|
||||||
<span>{{ item.trackTimePrefix || '' }}{{ formatTrackTimeDisplay(item) }}</span>
|
<div class="track-meta-row">
|
||||||
<span v-if="item.trackTimeZone" class="track-timezone">
|
<span v-if="formatTrackTimeDisplay(item)" class="track-meta-time">
|
||||||
{{ $t('order.myOrders.drawer.track.timezone', { zone: item.trackTimeZone }) }}
|
{{ item.trackTimePrefix || '' }}{{ formatTrackTimeDisplay(item) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
<span v-if="formatTrackPlace(item)" class="track-meta-place">
|
||||||
<div v-if="item.remark" class="track-meta track-remark">
|
{{ formatTrackPlace(item) }}
|
||||||
{{ $t('order.myOrders.drawer.track.remark') }}:{{ item.remark }}
|
</span>
|
||||||
</div>
|
<span v-if="item.trackTimeZone" class="track-meta-zone">
|
||||||
<div v-if="item.trackCode" class="track-meta track-code">
|
{{ item.trackTimeZone }}
|
||||||
{{ $t('order.myOrders.drawer.track.code') }}:{{ item.trackCode }}
|
</span>
|
||||||
</div>
|
<span v-if="item.trackCode" class="track-meta-code">{{ item.trackCode }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.remark" class="track-remark">
|
||||||
|
{{ $t('order.myOrders.drawer.track.remark') }}:{{ item.remark }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -663,7 +636,7 @@ import { ref, computed, watch, reactive } from 'vue';
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { IconRefresh, IconCheckCircleFill, IconLocation, IconRobot, IconDown, IconUp } from '@arco-design/web-vue/es/icon';
|
import { IconRefresh, IconRobot, IconDown, IconUp } from '@arco-design/web-vue/es/icon';
|
||||||
import useDrawer from '@/components/DrawerPro/useDrawer';
|
import useDrawer from '@/components/DrawerPro/useDrawer';
|
||||||
import { postGetDetailTimeline } from '@/api/TrackOrder/trackOrder';
|
import { postGetDetailTimeline } from '@/api/TrackOrder/trackOrder';
|
||||||
import {
|
import {
|
||||||
@ -1444,15 +1417,50 @@ function formatTrackTimeDisplay(item: any) {
|
|||||||
return formatTrackTime(item?.trackTime);
|
return formatTrackTime(item?.trackTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeTrackText(value: unknown) {
|
||||||
|
const text = value == null ? '' : String(value).trim();
|
||||||
|
return !text || text === '--' ? '' : text;
|
||||||
|
}
|
||||||
|
|
||||||
function formatTrackPlace(item: any) {
|
function formatTrackPlace(item: any) {
|
||||||
return item?.trackPlace == null ? '' : String(item.trackPlace).trim();
|
const structured = [item?.trackPlaceNation, item?.trackPlaceProvince, item?.trackPlaceCity]
|
||||||
|
.map(normalizeTrackText)
|
||||||
|
.filter(Boolean);
|
||||||
|
if (structured.length) return structured.join(' · ');
|
||||||
|
return normalizeTrackText(item?.trackPlace);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrackStatusLabel(item: any) {
|
||||||
|
return (
|
||||||
|
normalizeTrackText(item?.trackStatus) ||
|
||||||
|
normalizeTrackText(item?.content) ||
|
||||||
|
t('order.myOrders.drawer.track.statusUnknown')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有独立状态时,中文内容作为详情;否则中文已作标题 */
|
||||||
|
function getTrackZhDetail(item: any) {
|
||||||
|
const status = normalizeTrackText(item?.trackStatus);
|
||||||
|
const zh = normalizeTrackText(item?.content);
|
||||||
|
if (!zh || !status || zh === status) return '';
|
||||||
|
return zh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 英文内容;与标题/中文相同则不重复展示 */
|
||||||
|
function getTrackEnDetail(item: any) {
|
||||||
|
const en = normalizeTrackText(item?.enContent);
|
||||||
|
if (!en) return '';
|
||||||
|
const zh = normalizeTrackText(item?.content);
|
||||||
|
const status = normalizeTrackText(item?.trackStatus);
|
||||||
|
if (en === zh || en === status) return '';
|
||||||
|
return en;
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayTrackTimeline = computed(() => {
|
const displayTrackTimeline = computed(() => {
|
||||||
const list = trackTimeline.value;
|
const list = [...trackTimeline.value];
|
||||||
if (!list.length) return [];
|
if (!list.length) return [];
|
||||||
if (list.some((item) => item?.isHighlight)) return [...list];
|
// 与顺丰/京东一致:最新在上
|
||||||
return [...list].reverse();
|
return list.sort((a, b) => Number(b?.trackTime || 0) - Number(a?.trackTime || 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
function isTrackNodeActive(item: any, index: number) {
|
function isTrackNodeActive(item: any, index: number) {
|
||||||
@ -2124,54 +2132,6 @@ defineExpose({
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basic-summary {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: 1px solid var(--color-border-2);
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--app-card-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-top {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-main {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-3);
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-no {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
line-height: 26px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-chips {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-actions {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.predeclare-fail-guide {
|
.predeclare-fail-guide {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
@ -2229,29 +2189,6 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.basic-chip {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
max-width: 100%;
|
|
||||||
padding: 4px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--color-fill-2);
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-chip-label {
|
|
||||||
color: var(--color-text-3);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-chip-value {
|
|
||||||
color: var(--color-text-1);
|
|
||||||
font-weight: 500;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-view-switch {
|
.basic-view-switch {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
@ -3018,19 +2955,18 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.track-timeline {
|
.track-timeline {
|
||||||
padding: 4px 0;
|
padding: 4px 0 8px;
|
||||||
|
|
||||||
.track-item {
|
.track-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
.track-card {
|
.track-status {
|
||||||
border-color: #b9f0c2;
|
color: var(--app-primary-color, #2d8c8c);
|
||||||
background: #f6ffed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-title {
|
.track-content {
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3039,41 +2975,38 @@ defineExpose({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 28px;
|
width: 16px;
|
||||||
margin-right: 12px;
|
margin-right: 14px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
.track-icon {
|
.track-dot {
|
||||||
width: 24px;
|
width: 10px;
|
||||||
height: 24px;
|
height: 10px;
|
||||||
line-height: 24px;
|
|
||||||
text-align: center;
|
|
||||||
background: var(--color-fill-2);
|
|
||||||
color: var(--color-text-2);
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-size: 12px;
|
background: var(--color-fill-3);
|
||||||
|
border: 2px solid var(--color-border-2);
|
||||||
|
box-sizing: border-box;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
display: flex;
|
width: 12px;
|
||||||
align-items: center;
|
height: 12px;
|
||||||
justify-content: center;
|
background: var(--app-primary-color, #2d8c8c);
|
||||||
background: transparent;
|
border-color: color-mix(in srgb, var(--app-primary-color, #2d8c8c) 35%, #fff);
|
||||||
color: var(--app-primary-color, #2d8c8c);
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--app-primary-color, #2d8c8c) 18%, transparent);
|
||||||
font-size: 22px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-line {
|
.track-line {
|
||||||
width: 2px;
|
width: 2px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 20px;
|
min-height: 18px;
|
||||||
background: var(--color-fill-3);
|
background: var(--color-fill-3);
|
||||||
margin: 4px 0;
|
margin: 4px 0 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: var(--app-primary-color, #2d8c8c);
|
background: color-mix(in srgb, var(--app-primary-color, #2d8c8c) 45%, var(--color-fill-3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3081,61 +3014,75 @@ defineExpose({
|
|||||||
.track-right {
|
.track-right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-card {
|
.track-row-head {
|
||||||
padding: 10px 12px;
|
|
||||||
border: 1px solid var(--color-border-2);
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--app-card-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-card-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
line-height: 22px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-meta {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 4px 8px;
|
gap: 8px;
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-3);
|
|
||||||
margin-top: 6px;
|
|
||||||
line-height: 20px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-place {
|
.track-status {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
line-height: 22px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-content {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
|
&--en {
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-meta-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px 10px;
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-meta-place {
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-meta-icon {
|
.track-meta-code {
|
||||||
font-size: 14px;
|
padding: 0 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: var(--color-fill-2);
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-3);
|
||||||
flex-shrink: 0;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-timezone {
|
.track-remark {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-3);
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.track-remark,
|
.track-item:last-child .track-right {
|
||||||
.track-code {
|
padding-bottom: 0;
|
||||||
color: var(--color-text-3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -261,10 +261,11 @@ watch(
|
|||||||
<a-alert
|
<a-alert
|
||||||
v-if="preview.error"
|
v-if="preview.error"
|
||||||
type="warning"
|
type="warning"
|
||||||
:content="preview.error"
|
|
||||||
show-icon
|
show-icon
|
||||||
class="pay-order-alert"
|
class="pay-order-alert"
|
||||||
/>
|
>
|
||||||
|
{{ preview.error }}
|
||||||
|
</a-alert>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
v-else
|
v-else
|
||||||
|
|||||||
@ -142,9 +142,10 @@ function toggleExpand(id: number) {
|
|||||||
<a-alert
|
<a-alert
|
||||||
v-if="trace.failReason"
|
v-if="trace.failReason"
|
||||||
type="warning"
|
type="warning"
|
||||||
:content="trace.failReason"
|
|
||||||
style="margin-bottom: 12px"
|
style="margin-bottom: 12px"
|
||||||
/>
|
>
|
||||||
|
{{ trace.failReason }}
|
||||||
|
</a-alert>
|
||||||
|
|
||||||
<div v-else class="alloc-trace__conclusion">
|
<div v-else class="alloc-trace__conclusion">
|
||||||
{{
|
{{
|
||||||
|
|||||||
@ -290,14 +290,16 @@ function handleCancel() {
|
|||||||
v-if="showInsuranceTip"
|
v-if="showInsuranceTip"
|
||||||
type="info"
|
type="info"
|
||||||
show-icon
|
show-icon
|
||||||
:content="t('order.myOrders.claimed.tipInsured', { amount: declaredSumText })"
|
>
|
||||||
/>
|
{{ t('order.myOrders.claimed.tipInsured', { amount: declaredSumText }) }}
|
||||||
|
</a-alert>
|
||||||
<a-alert
|
<a-alert
|
||||||
v-else-if="showUninsuredTip"
|
v-else-if="showUninsuredTip"
|
||||||
type="warning"
|
type="warning"
|
||||||
show-icon
|
show-icon
|
||||||
:content="t('order.myOrders.claimed.tipUninsured')"
|
>
|
||||||
/>
|
{{ t('order.myOrders.claimed.tipUninsured') }}
|
||||||
|
</a-alert>
|
||||||
<div v-if="declaredSumNumber != null" class="claim-max-hint">
|
<div v-if="declaredSumNumber != null" class="claim-max-hint">
|
||||||
{{ t('order.myOrders.claimed.maxHint', { amount: declaredSumText }) }}
|
{{ t('order.myOrders.claimed.maxHint', { amount: declaredSumText }) }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -36,6 +36,9 @@
|
|||||||
<a-button v-else class="app-btn-search" @click="startBasicEdit">
|
<a-button v-else class="app-btn-search" @click="startBasicEdit">
|
||||||
{{ $t('order.myOrders.drawer.actions.edit') }}
|
{{ $t('order.myOrders.drawer.actions.edit') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button class="app-btn-search" @click="handleAskAdvisor">
|
||||||
|
{{ $t('nanaAssistant.askAboutWaybill') }}
|
||||||
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="activeTab === 'weight'">
|
<template v-else-if="activeTab === 'weight'">
|
||||||
<template v-if="weightEditing">
|
<template v-if="weightEditing">
|
||||||
@ -80,6 +83,13 @@
|
|||||||
<span class="toolbar-meta-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
<span class="toolbar-meta-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
||||||
<span class="toolbar-meta-value">{{ trackOrderNumber || '--' }}</span>
|
<span class="toolbar-meta-value">{{ trackOrderNumber || '--' }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
<a-tag
|
||||||
|
v-if="currentOrderStatusMeta"
|
||||||
|
size="small"
|
||||||
|
:style="getOrderStatusTagStyle(currentOrderStatusMeta)"
|
||||||
|
>
|
||||||
|
{{ $t(currentOrderStatusMeta.labelKey) }}
|
||||||
|
</a-tag>
|
||||||
<a-tag v-if="trackTimeline.length" size="small" color="arcoblue">
|
<a-tag v-if="trackTimeline.length" size="small" color="arcoblue">
|
||||||
{{ $t('order.myOrders.drawer.track.count', { count: trackTimeline.length }) }}
|
{{ $t('order.myOrders.drawer.track.count', { count: trackTimeline.length }) }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
@ -104,60 +114,6 @@
|
|||||||
<div class="drawer-tab-content">
|
<div class="drawer-tab-content">
|
||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<div v-if="activeTab === 'basic'" class="tab-panel basic-info">
|
<div v-if="activeTab === 'basic'" class="tab-panel basic-info">
|
||||||
<div class="basic-summary">
|
|
||||||
<div class="basic-summary-top">
|
|
||||||
<div class="basic-summary-main">
|
|
||||||
<span class="basic-summary-label">{{ $t('order.myOrders.drawer.serviceNo') }}</span>
|
|
||||||
<span class="basic-summary-no">{{ getOrderValue('serviceNo') }}</span>
|
|
||||||
</div>
|
|
||||||
<a-tag
|
|
||||||
v-if="currentOrderStatusMeta"
|
|
||||||
size="small"
|
|
||||||
:style="getOrderStatusTagStyle(currentOrderStatusMeta)"
|
|
||||||
>
|
|
||||||
{{ $t(currentOrderStatusMeta.labelKey) }}
|
|
||||||
</a-tag>
|
|
||||||
</div>
|
|
||||||
<div class="basic-summary-chips">
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.clientNo') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('clientNo') }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.trackNo') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('trackNo') }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.downstreamServiceNo') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('downstreamServiceNo') }}</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.channelName') }}</span>
|
|
||||||
<span class="basic-chip-value basic-chip-value--with-action">
|
|
||||||
{{ getOrderValue('channelName') }}
|
|
||||||
<a-button
|
|
||||||
v-if="canViewAllocationTrace"
|
|
||||||
type="text"
|
|
||||||
size="mini"
|
|
||||||
class="alloc-eye-btn"
|
|
||||||
:title="$t('order.myOrders.allocationTrace.view')"
|
|
||||||
@click.stop="openAllocationTrace"
|
|
||||||
>
|
|
||||||
<template #icon><icon-eye /></template>
|
|
||||||
</a-button>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span class="basic-chip">
|
|
||||||
<span class="basic-chip-label">{{ $t('order.myOrders.drawer.consigneeCountryName') }}</span>
|
|
||||||
<span class="basic-chip-value">{{ getOrderValue('consigneeCountryName') }}</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="basic-summary-actions">
|
|
||||||
<a-button class="app-btn-search" @click="handleAskAdvisor">{{ $t('nanaAssistant.askAboutWaybill') }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="predeclareFailGuide" class="predeclare-fail-guide">
|
<div v-if="predeclareFailGuide" class="predeclare-fail-guide">
|
||||||
<p class="predeclare-fail-guide__reason">{{ predeclareFailGuide.reason }}</p>
|
<p class="predeclare-fail-guide__reason">{{ predeclareFailGuide.reason }}</p>
|
||||||
<p v-if="predeclareFailGuide.tips?.[0]" class="predeclare-fail-guide__tip">
|
<p v-if="predeclareFailGuide.tips?.[0]" class="predeclare-fail-guide__tip">
|
||||||
@ -174,9 +130,6 @@
|
|||||||
<p class="predeclare-fail-guide__raw">{{ predeclareFailGuide.rawReason }}</p>
|
<p class="predeclare-fail-guide__raw">{{ predeclareFailGuide.rawReason }}</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="predeclare-fail-guide__actions">
|
<div class="predeclare-fail-guide__actions">
|
||||||
<a-button class="app-btn-search" @click="handleAskAdvisor">
|
|
||||||
{{ $t('order.myOrders.drawer.failGuideAskSupport') }}
|
|
||||||
</a-button>
|
|
||||||
<a-button class="app-btn-search" @click="startBasicEdit">
|
<a-button class="app-btn-search" @click="startBasicEdit">
|
||||||
{{ $t('order.myOrders.drawer.failGuideEdit') }}
|
{{ $t('order.myOrders.drawer.failGuideEdit') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
@ -682,8 +635,9 @@
|
|||||||
v-if="hasNegativeGrossProfit"
|
v-if="hasNegativeGrossProfit"
|
||||||
type="warning"
|
type="warning"
|
||||||
show-icon
|
show-icon
|
||||||
:content="$t('order.myOrders.drawer.fee.negativeGrossProfitWarn')"
|
>
|
||||||
/>
|
{{ $t('order.myOrders.drawer.fee.negativeGrossProfitWarn') }}
|
||||||
|
</a-alert>
|
||||||
|
|
||||||
<div class="fee-view-switch">
|
<div class="fee-view-switch">
|
||||||
<a-radio-group
|
<a-radio-group
|
||||||
@ -773,10 +727,7 @@
|
|||||||
:class="{ active: isTrackNodeActive(item, i) }"
|
:class="{ active: isTrackNodeActive(item, i) }"
|
||||||
>
|
>
|
||||||
<div class="track-left">
|
<div class="track-left">
|
||||||
<span v-if="isTrackNodeActive(item, i)" class="track-icon active">
|
<span class="track-dot" :class="{ active: isTrackNodeActive(item, i) }" />
|
||||||
<icon-check-circle-fill />
|
|
||||||
</span>
|
|
||||||
<span v-else class="track-icon">{{ displayTrackTimeline.length - i }}</span>
|
|
||||||
<span
|
<span
|
||||||
v-if="i < displayTrackTimeline.length - 1"
|
v-if="i < displayTrackTimeline.length - 1"
|
||||||
class="track-line"
|
class="track-line"
|
||||||
@ -784,29 +735,32 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="track-right">
|
<div class="track-right">
|
||||||
<div class="track-card">
|
<div class="track-row-head">
|
||||||
<div class="track-card-head">
|
<span class="track-status">{{ getTrackStatusLabel(item) }}</span>
|
||||||
<div class="track-title">{{ item.content || '--' }}</div>
|
<a-tag v-if="isTrackNodeActive(item, i)" size="small" color="green">
|
||||||
<a-tag v-if="isTrackNodeActive(item, i)" size="small" color="green">
|
{{ $t('order.myOrders.drawer.track.latest') }}
|
||||||
{{ $t('order.myOrders.drawer.track.latest') }}
|
</a-tag>
|
||||||
</a-tag>
|
</div>
|
||||||
</div>
|
<div v-if="getTrackZhDetail(item)" class="track-content track-content--zh">
|
||||||
<div v-if="formatTrackPlace(item)" class="track-meta track-place">
|
{{ getTrackZhDetail(item) }}
|
||||||
<icon-location class="track-meta-icon" />
|
</div>
|
||||||
<span>{{ formatTrackPlace(item) }}</span>
|
<div v-if="getTrackEnDetail(item)" class="track-content track-content--en">
|
||||||
</div>
|
{{ getTrackEnDetail(item) }}
|
||||||
<div v-if="formatTrackTimeDisplay(item)" class="track-meta track-time">
|
</div>
|
||||||
<span>{{ item.trackTimePrefix || '' }}{{ formatTrackTimeDisplay(item) }}</span>
|
<div class="track-meta-row">
|
||||||
<span v-if="item.trackTimeZone" class="track-timezone">
|
<span v-if="formatTrackTimeDisplay(item)" class="track-meta-time">
|
||||||
{{ $t('order.myOrders.drawer.track.timezone', { zone: item.trackTimeZone }) }}
|
{{ item.trackTimePrefix || '' }}{{ formatTrackTimeDisplay(item) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
<span v-if="formatTrackPlace(item)" class="track-meta-place">
|
||||||
<div v-if="item.remark" class="track-meta track-remark">
|
{{ formatTrackPlace(item) }}
|
||||||
{{ $t('order.myOrders.drawer.track.remark') }}:{{ item.remark }}
|
</span>
|
||||||
</div>
|
<span v-if="item.trackTimeZone" class="track-meta-zone">
|
||||||
<div v-if="item.trackCode" class="track-meta track-code">
|
{{ item.trackTimeZone }}
|
||||||
{{ $t('order.myOrders.drawer.track.code') }}:{{ item.trackCode }}
|
</span>
|
||||||
</div>
|
<span v-if="item.trackCode" class="track-meta-code">{{ item.trackCode }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.remark" class="track-remark">
|
||||||
|
{{ $t('order.myOrders.drawer.track.remark') }}:{{ item.remark }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -895,7 +849,7 @@ import { ref, computed, watch, reactive } from 'vue';
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { IconRefresh, IconCheckCircleFill, IconLocation, IconRobot, IconEye } from '@arco-design/web-vue/es/icon';
|
import { IconRefresh, IconRobot, IconEye } from '@arco-design/web-vue/es/icon';
|
||||||
import useDrawer from '@/components/DrawerPro/useDrawer';
|
import useDrawer from '@/components/DrawerPro/useDrawer';
|
||||||
import { postGetDetailTimeline } from '@/api/TrackOrder/trackOrder';
|
import { postGetDetailTimeline } from '@/api/TrackOrder/trackOrder';
|
||||||
import {
|
import {
|
||||||
@ -1605,15 +1559,50 @@ function formatTrackTimeDisplay(item: any) {
|
|||||||
return formatTrackTime(item?.trackTime);
|
return formatTrackTime(item?.trackTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeTrackText(value: unknown) {
|
||||||
|
const text = value == null ? '' : String(value).trim();
|
||||||
|
return !text || text === '--' ? '' : text;
|
||||||
|
}
|
||||||
|
|
||||||
function formatTrackPlace(item: any) {
|
function formatTrackPlace(item: any) {
|
||||||
return item?.trackPlace == null ? '' : String(item.trackPlace).trim();
|
const structured = [item?.trackPlaceNation, item?.trackPlaceProvince, item?.trackPlaceCity]
|
||||||
|
.map(normalizeTrackText)
|
||||||
|
.filter(Boolean);
|
||||||
|
if (structured.length) return structured.join(' · ');
|
||||||
|
return normalizeTrackText(item?.trackPlace);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrackStatusLabel(item: any) {
|
||||||
|
return (
|
||||||
|
normalizeTrackText(item?.trackStatus) ||
|
||||||
|
normalizeTrackText(item?.content) ||
|
||||||
|
t('order.myOrders.drawer.track.statusUnknown')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 有独立状态时,中文内容作为详情;否则中文已作标题 */
|
||||||
|
function getTrackZhDetail(item: any) {
|
||||||
|
const status = normalizeTrackText(item?.trackStatus);
|
||||||
|
const zh = normalizeTrackText(item?.content);
|
||||||
|
if (!zh || !status || zh === status) return '';
|
||||||
|
return zh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 英文内容;与标题/中文相同则不重复展示 */
|
||||||
|
function getTrackEnDetail(item: any) {
|
||||||
|
const en = normalizeTrackText(item?.enContent);
|
||||||
|
if (!en) return '';
|
||||||
|
const zh = normalizeTrackText(item?.content);
|
||||||
|
const status = normalizeTrackText(item?.trackStatus);
|
||||||
|
if (en === zh || en === status) return '';
|
||||||
|
return en;
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayTrackTimeline = computed(() => {
|
const displayTrackTimeline = computed(() => {
|
||||||
const list = trackTimeline.value;
|
const list = [...trackTimeline.value];
|
||||||
if (!list.length) return [];
|
if (!list.length) return [];
|
||||||
if (list.some((item) => item?.isHighlight)) return [...list];
|
// 与顺丰/京东一致:最新在上
|
||||||
return [...list].reverse();
|
return list.sort((a, b) => Number(b?.trackTime || 0) - Number(a?.trackTime || 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
function isTrackNodeActive(item: any, index: number) {
|
function isTrackNodeActive(item: any, index: number) {
|
||||||
@ -2522,54 +2511,6 @@ defineExpose({
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basic-summary {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: 1px solid var(--color-border-2);
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--app-card-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-top {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-main {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-3);
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-no {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
line-height: 26px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-chips {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-summary-actions {
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.predeclare-fail-guide {
|
.predeclare-fail-guide {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
@ -2627,30 +2568,6 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.basic-chip {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
max-width: 100%;
|
|
||||||
padding: 4px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--color-fill-2);
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-chip-label {
|
|
||||||
color: var(--color-text-3);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-chip-value {
|
|
||||||
color: var(--color-text-1);
|
|
||||||
font-weight: 500;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-chip-value--with-action,
|
|
||||||
.detail-field-text--with-action {
|
.detail-field-text--with-action {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -3436,19 +3353,18 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.track-timeline {
|
.track-timeline {
|
||||||
padding: 4px 0;
|
padding: 4px 0 8px;
|
||||||
|
|
||||||
.track-item {
|
.track-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
.track-card {
|
.track-status {
|
||||||
border-color: #b9f0c2;
|
color: var(--app-primary-color, #2d8c8c);
|
||||||
background: #f6ffed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-title {
|
.track-content {
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3457,41 +3373,38 @@ defineExpose({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 28px;
|
width: 16px;
|
||||||
margin-right: 12px;
|
margin-right: 14px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
|
||||||
.track-icon {
|
.track-dot {
|
||||||
width: 24px;
|
width: 10px;
|
||||||
height: 24px;
|
height: 10px;
|
||||||
line-height: 24px;
|
|
||||||
text-align: center;
|
|
||||||
background: var(--color-fill-2);
|
|
||||||
color: var(--color-text-2);
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-size: 12px;
|
background: var(--color-fill-3);
|
||||||
|
border: 2px solid var(--color-border-2);
|
||||||
|
box-sizing: border-box;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
display: flex;
|
width: 12px;
|
||||||
align-items: center;
|
height: 12px;
|
||||||
justify-content: center;
|
background: var(--app-primary-color, #2d8c8c);
|
||||||
background: transparent;
|
border-color: color-mix(in srgb, var(--app-primary-color, #2d8c8c) 35%, #fff);
|
||||||
color: var(--app-primary-color, #2d8c8c);
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--app-primary-color, #2d8c8c) 18%, transparent);
|
||||||
font-size: 22px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-line {
|
.track-line {
|
||||||
width: 2px;
|
width: 2px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 20px;
|
min-height: 18px;
|
||||||
background: var(--color-fill-3);
|
background: var(--color-fill-3);
|
||||||
margin: 4px 0;
|
margin: 4px 0 0;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: var(--app-primary-color, #2d8c8c);
|
background: color-mix(in srgb, var(--app-primary-color, #2d8c8c) 45%, var(--color-fill-3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3499,61 +3412,75 @@ defineExpose({
|
|||||||
.track-right {
|
.track-right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-card {
|
.track-row-head {
|
||||||
padding: 10px 12px;
|
|
||||||
border: 1px solid var(--color-border-2);
|
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--app-card-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-card-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--color-text-1);
|
|
||||||
line-height: 22px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-meta {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 4px 8px;
|
gap: 8px;
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-3);
|
|
||||||
margin-top: 6px;
|
|
||||||
line-height: 20px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-place {
|
.track-status {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
line-height: 22px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-content {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
|
&--en {
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-meta-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px 10px;
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-meta-place {
|
||||||
color: var(--color-text-2);
|
color: var(--color-text-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-meta-icon {
|
.track-meta-code {
|
||||||
font-size: 14px;
|
padding: 0 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: var(--color-fill-2);
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-3);
|
||||||
flex-shrink: 0;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-timezone {
|
.track-remark {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
color: var(--color-text-3);
|
color: var(--color-text-3);
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.track-remark,
|
.track-item:last-child .track-right {
|
||||||
.track-code {
|
padding-bottom: 0;
|
||||||
color: var(--color-text-3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -259,10 +259,11 @@ watch(
|
|||||||
<a-alert
|
<a-alert
|
||||||
v-if="preview.error"
|
v-if="preview.error"
|
||||||
type="warning"
|
type="warning"
|
||||||
:content="preview.error"
|
|
||||||
show-icon
|
show-icon
|
||||||
class="pay-order-alert"
|
class="pay-order-alert"
|
||||||
/>
|
>
|
||||||
|
{{ preview.error }}
|
||||||
|
</a-alert>
|
||||||
|
|
||||||
<a-table
|
<a-table
|
||||||
v-else
|
v-else
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user