1
This commit is contained in:
@@ -39,6 +39,11 @@ export function getGoofishOrder(id) {
|
|||||||
return request({ url: '/jarvis/erpGoofishOrder/' + id, method: 'get' })
|
return request({ url: '/jarvis/erpGoofishOrder/' + id, method: 'get' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 订单状态 / 物流 / 发货 变更日志 */
|
||||||
|
export function listGoofishOrderEventLogs(orderId) {
|
||||||
|
return request({ url: '/jarvis/erpGoofishOrder/' + orderId + '/eventLogs', method: 'get' })
|
||||||
|
}
|
||||||
|
|
||||||
export function pullGoofishOrders(appKey, hours) {
|
export function pullGoofishOrders(appKey, hours) {
|
||||||
return request({
|
return request({
|
||||||
url: '/jarvis/erpGoofishOrder/pull/' + encodeURIComponent(appKey),
|
url: '/jarvis/erpGoofishOrder/pull/' + encodeURIComponent(appKey),
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-alert type="info" :closable="false" show-icon class="mb8">
|
|
||||||
<template slot="title">
|
|
||||||
<div style="line-height:1.6">
|
|
||||||
① 第三方单号:本地京东单「第三方单号」= 闲鱼 order_no,用于关联与写入收件地址(jd_order.address)、物流 Redis 运单。<br>
|
|
||||||
② 闲管家订单详情<strong>往往不落明文收货地址</strong>;列表中的地址优先来自详情字段,否则来自关联的京东「地址」。<br>
|
|
||||||
③ 自动发货前请在「应用配置」填写 express_code(日日顺一般为 rrs)。<br>
|
|
||||||
④ <strong>增量拉单</strong>:按「pull-lookback-hours」回溯;<strong>历史全量</strong>:按「pull-full-history-days」起点 + 「pull-time-chunk-seconds」对 update_time 分段;单次请求的 update_time 跨度不得超过「pull-max-update-time-range-seconds」(默认约 180 天,避免平台「仅 6 个月内」报错),过长区间会自动再拆段。
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-alert>
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="96px">
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="96px">
|
||||||
<el-form-item label="AppKey" prop="appKey">
|
<el-form-item label="AppKey" prop="appKey">
|
||||||
<el-input v-model="queryParams.appKey" placeholder="可选" clearable @keyup.enter.native="handleQuery" />
|
<el-input v-model="queryParams.appKey" placeholder="可选" clearable @keyup.enter.native="handleQuery" />
|
||||||
@@ -77,27 +67,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="买家 buyer_nick" prop="buyerNick" width="120" show-overflow-tooltip />
|
<el-table-column label="买家" min-width="120" show-overflow-tooltip>
|
||||||
<el-table-column label="会员名" prop="userName" width="110" show-overflow-tooltip />
|
|
||||||
<el-table-column label="订单状态" prop="orderStatus" width="92">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ orderStatusLabel(scope.row.orderStatus) }}
|
{{ displayBuyerNick(scope.row) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实付 pay_amount" prop="payAmount" width="118" align="right">
|
<el-table-column label="订单状态" prop="orderStatus" width="118" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="orderStatusTagType(scope.row.orderStatus)"
|
||||||
|
:effect="orderStatusTagEffect(scope.row.orderStatus)"
|
||||||
|
size="small"
|
||||||
|
disable-transitions
|
||||||
|
>
|
||||||
|
{{ orderStatusLabel(scope.row.orderStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="实付" prop="payAmount" width="118" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ formatPayDisplay(scope.row) }}
|
{{ formatPayDisplay(scope.row) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="退款" prop="refundStatus" width="64" />
|
|
||||||
<el-table-column label="第三方单号(本地)" prop="jdThirdPartyOrderNo" min-width="130" show-overflow-tooltip />
|
|
||||||
<el-table-column label="内部单" prop="jdRemark" width="100" show-overflow-tooltip />
|
<el-table-column label="内部单" prop="jdRemark" width="100" show-overflow-tooltip />
|
||||||
<el-table-column label="运单号 waybill_no" prop="detailWaybillNo" min-width="128" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope">
|
<el-table-column label="快递" min-width="130" show-overflow-tooltip>
|
||||||
{{ displayWaybillNo(scope.row) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="快递 express_name" min-width="130" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="displayExpressName(scope.row) !== '—'">
|
<span v-if="displayExpressName(scope.row) !== '—'">
|
||||||
{{ displayExpressName(scope.row) }}
|
{{ displayExpressName(scope.row) }}
|
||||||
@@ -108,7 +102,22 @@
|
|||||||
<span v-else>—</span>
|
<span v-else>—</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="运单(本地扫描)" prop="localWaybillNo" min-width="120" show-overflow-tooltip />
|
<el-table-column label="运单号" min-width="188" align="left">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-for="w in [waybillDisplay(scope.row)]" :key="'wb-' + scope.row.id" class="waybill-cell">
|
||||||
|
<span v-if="w.kind === 'empty'">—</span>
|
||||||
|
<span v-else-if="w.kind === 'match'" class="waybill-cell--match" :title="w.text">{{ w.text }}</span>
|
||||||
|
<span v-else-if="w.kind === 'single'" class="waybill-cell--single" :title="w.text">
|
||||||
|
{{ w.text }}<span v-if="w.source === 'local'" class="waybill-cell--hint">(仅本地)</span>
|
||||||
|
</span>
|
||||||
|
<div v-else class="waybill-cell--warn">
|
||||||
|
<div class="waybill-cell--warn-title"><i class="el-icon-warning-outline" /> 平台与本地不一致</div>
|
||||||
|
<div class="waybill-cell--line">平台 {{ w.platform }}</div>
|
||||||
|
<div class="waybill-cell--line">本地 {{ w.local }}</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="收货人/手机" min-width="120" show-overflow-tooltip>
|
<el-table-column label="收货人/手机" min-width="120" show-overflow-tooltip>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ displayReceiverName(scope.row) }} {{ displayReceiverMobile(scope.row) }}
|
{{ displayReceiverName(scope.row) }} {{ displayReceiverMobile(scope.row) }}
|
||||||
@@ -119,21 +128,20 @@
|
|||||||
{{ displayRecvSplit(scope.row) }}
|
{{ displayRecvSplit(scope.row) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="详细 address" min-width="130" show-overflow-tooltip>
|
<el-table-column label="闲鱼地址" min-width="130" show-overflow-tooltip>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ displayAddressLine(scope.row) }}
|
{{ displayAddressLine(scope.row) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="京东地址(兜底)" prop="jdAddress" min-width="140" show-overflow-tooltip />
|
<el-table-column label="京东地址" prop="jdAddress" min-width="140" show-overflow-tooltip />
|
||||||
<el-table-column label="发货" prop="shipStatus" width="76">
|
<el-table-column label="发货" prop="shipStatus" width="76">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ shipLabel(scope.row.shipStatus) }}
|
{{ shipLabel(scope.row.shipStatus) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="更新时间" prop="modifyTime" width="100">
|
<el-table-column label="更新时间" prop="modifyTime" width="158" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="scope.row.modifyTime">{{ scope.row.modifyTime }}</span>
|
{{ formatModifyTime(scope.row.modifyTime) }}
|
||||||
<span v-else>-</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||||
@@ -148,7 +156,7 @@
|
|||||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||||
|
|
||||||
<el-dialog title="订单详情 JSON(含开放平台原始返回)" :visible.sync="jsonOpen" width="900px" append-to-body>
|
<el-dialog title="订单详情 JSON(含开放平台原始返回)" :visible.sync="jsonOpen" width="900px" append-to-body>
|
||||||
<el-tabs v-model="jsonTab">
|
<el-tabs v-model="jsonTab" @tab-click="onJsonTabClick">
|
||||||
<el-tab-pane label="摘要" name="sum">
|
<el-tab-pane label="摘要" name="sum">
|
||||||
<el-descriptions :column="1" border size="small">
|
<el-descriptions :column="1" border size="small">
|
||||||
<el-descriptions-item label="商品标题 title">
|
<el-descriptions-item label="商品标题 title">
|
||||||
@@ -165,11 +173,34 @@
|
|||||||
<span>{{ displayGoodsTitle(jsonRow) }}</span>
|
<span>{{ displayGoodsTitle(jsonRow) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="运单号 waybill_no">{{ displayWaybillNo(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="运单号(平台 / 本地)">
|
||||||
|
<span v-for="w in [waybillDisplay(jsonRow)]" :key="'jw'">
|
||||||
|
<span v-if="w.kind === 'empty'">—</span>
|
||||||
|
<span v-else-if="w.kind === 'match'" class="waybill-cell--match">{{ w.text }}</span>
|
||||||
|
<span v-else-if="w.kind === 'single'" class="waybill-cell--single">
|
||||||
|
{{ w.text }}<span v-if="w.source === 'local'" class="waybill-cell--hint">(仅本地)</span>
|
||||||
|
</span>
|
||||||
|
<div v-else class="waybill-cell--warn">
|
||||||
|
<div class="waybill-cell--warn-title"><i class="el-icon-warning-outline" /> 平台与本地不一致</div>
|
||||||
|
<div class="waybill-cell--line">平台 {{ w.platform }}</div>
|
||||||
|
<div class="waybill-cell--line">本地 {{ w.local }}</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="快递公司 express_name">{{ displayExpressName(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="快递公司 express_name">{{ displayExpressName(jsonRow) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="实付 pay_amount(分→元)">{{ formatPayDisplay(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="实付 pay_amount(分→元)">{{ formatPayDisplay(jsonRow) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="本地扫描运单">{{ jsonRow.localWaybillNo || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="订单状态">
|
||||||
|
<el-tag
|
||||||
|
:type="orderStatusTagType(jsonRow.orderStatus)"
|
||||||
|
:effect="orderStatusTagEffect(jsonRow.orderStatus)"
|
||||||
|
size="small"
|
||||||
|
disable-transitions
|
||||||
|
>
|
||||||
|
{{ orderStatusLabel(jsonRow.orderStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="买家昵称 buyer_nick">{{ displayBuyerNick(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="买家昵称 buyer_nick">{{ displayBuyerNick(jsonRow) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="会员名(卖家)">{{ privacyHidden }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="收货人 receiver_name">{{ displayReceiverName(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="收货人 receiver_name">{{ displayReceiverName(jsonRow) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="手机 receiver_mobile">{{ displayReceiverMobile(jsonRow) || '—' }}</el-descriptions-item>
|
<el-descriptions-item label="手机 receiver_mobile">{{ displayReceiverMobile(jsonRow) || '—' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="省/市/区/镇 prov…town">{{ displayRecvSplit(jsonRow) }}</el-descriptions-item>
|
<el-descriptions-item label="省/市/区/镇 prov…town">{{ displayRecvSplit(jsonRow) }}</el-descriptions-item>
|
||||||
@@ -184,6 +215,18 @@
|
|||||||
<el-tab-pane label="last_notify_json" name="notify">
|
<el-tab-pane label="last_notify_json" name="notify">
|
||||||
<pre class="json-pre">{{ pretty(jsonRow.lastNotifyJson) }}</pre>
|
<pre class="json-pre">{{ pretty(jsonRow.lastNotifyJson) }}</pre>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="变更日志" name="events">
|
||||||
|
<el-table v-loading="eventLogsLoading" :data="eventLogs" size="small" max-height="440" empty-text="暂无记录">
|
||||||
|
<el-table-column label="时间" prop="createTime" width="168" />
|
||||||
|
<el-table-column label="类型" prop="eventType" width="118" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag :type="eventLogTagType(scope.row.eventType)" size="mini">{{ scope.row.eventType }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="来源" prop="source" width="126" show-overflow-tooltip />
|
||||||
|
<el-table-column label="说明" prop="message" min-width="220" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<p v-if="jsonRow.shipError" style="color:#f56c6c">发货错误:{{ jsonRow.shipError }}</p>
|
<p v-if="jsonRow.shipError" style="color:#f56c6c">发货错误:{{ jsonRow.shipError }}</p>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -191,7 +234,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listGoofishOrder, pullAllGoofishOrders, pullAllGoofishOrdersFull, pullGoofishOrdersFull, refreshGoofishDetail, retryGoofishShip } from '@/api/jarvis/goofish'
|
import { listGoofishOrder, listGoofishOrderEventLogs, pullAllGoofishOrders, pullAllGoofishOrdersFull, pullGoofishOrdersFull, refreshGoofishDetail, retryGoofishShip } from '@/api/jarvis/goofish'
|
||||||
|
import { parseTime } from '@/utils/ruoyi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ErpGoofishOrder',
|
name: 'ErpGoofishOrder',
|
||||||
@@ -217,9 +261,13 @@ export default {
|
|||||||
{ v: 23, l: '已退款' },
|
{ v: 23, l: '已退款' },
|
||||||
{ v: 24, l: '已关闭' }
|
{ v: 24, l: '已关闭' }
|
||||||
],
|
],
|
||||||
|
/** 摘要中卖家会员名不展示(买家见 displayBuyerNick) */
|
||||||
|
privacyHidden: '—',
|
||||||
jsonOpen: false,
|
jsonOpen: false,
|
||||||
jsonTab: 'sum',
|
jsonTab: 'sum',
|
||||||
jsonRow: {}
|
jsonRow: {},
|
||||||
|
eventLogs: [],
|
||||||
|
eventLogsLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -228,7 +276,50 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
orderStatusLabel(s) {
|
orderStatusLabel(s) {
|
||||||
const o = this.orderStatusOptions.find(x => x.v === s)
|
const o = this.orderStatusOptions.find(x => x.v === s)
|
||||||
return o ? o.l : (s == null ? '-' : s)
|
return o ? o.l : (s == null ? '-' : String(s))
|
||||||
|
},
|
||||||
|
/** Element 标签类型(仅 success/info/warning/danger):与闲管家 order_status 对齐 */
|
||||||
|
orderStatusTagType(s) {
|
||||||
|
const m = {
|
||||||
|
11: 'info',
|
||||||
|
12: 'warning',
|
||||||
|
21: 'success',
|
||||||
|
22: 'success',
|
||||||
|
23: 'danger',
|
||||||
|
24: 'info'
|
||||||
|
}
|
||||||
|
if (s == null || s === '') return 'info'
|
||||||
|
return m[s] !== undefined ? m[s] : 'info'
|
||||||
|
},
|
||||||
|
/** 已完成用深色实心,与已发货(浅色 success)区分 */
|
||||||
|
orderStatusTagEffect(s) {
|
||||||
|
return s === 22 ? 'dark' : 'light'
|
||||||
|
},
|
||||||
|
/** 开放平台 modify_time:秒级时间戳 → 本地 yyyy-MM-dd HH:mm:ss */
|
||||||
|
formatModifyTime(ts) {
|
||||||
|
if (ts == null || ts === '') return '-'
|
||||||
|
return parseTime(ts) || '-'
|
||||||
|
},
|
||||||
|
eventLogTagType(t) {
|
||||||
|
if (t === 'ORDER_SYNC') return 'info'
|
||||||
|
if (t === 'LOGISTICS_SYNC') return 'warning'
|
||||||
|
if (t === 'SHIP') return 'warning'
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
onJsonTabClick(tab) {
|
||||||
|
if (tab && tab.name === 'events' && this.jsonRow && this.jsonRow.id) {
|
||||||
|
this.loadEventLogs()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadEventLogs() {
|
||||||
|
if (!this.jsonRow || !this.jsonRow.id) return
|
||||||
|
this.eventLogsLoading = true
|
||||||
|
listGoofishOrderEventLogs(this.jsonRow.id).then(res => {
|
||||||
|
this.eventLogs = Array.isArray(res.data) ? res.data : []
|
||||||
|
this.eventLogsLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.eventLogsLoading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
shipLabel(s) {
|
shipLabel(s) {
|
||||||
if (s === 1) return '成功'
|
if (s === 1) return '成功'
|
||||||
@@ -246,6 +337,24 @@ export default {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/** 订单详情/开放平台 data 根对象(无 detailJson 时 null) */
|
||||||
|
detailOrderData(row) {
|
||||||
|
if (!row || !row.detailJson) return null
|
||||||
|
try {
|
||||||
|
const root = JSON.parse(row.detailJson)
|
||||||
|
return root && root.data ? root.data : root
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
firstNonEmptyStr(o, keys) {
|
||||||
|
if (!o) return null
|
||||||
|
for (const k of keys) {
|
||||||
|
const v = o[k]
|
||||||
|
if (v != null && String(v).trim() !== '') return String(v).trim()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
displayGoodsTitle(row) {
|
displayGoodsTitle(row) {
|
||||||
if (!row) return '—'
|
if (!row) return '—'
|
||||||
if (row.goodsTitle) return row.goodsTitle
|
if (row.goodsTitle) return row.goodsTitle
|
||||||
@@ -257,14 +366,33 @@ export default {
|
|||||||
if (!row) return '—'
|
if (!row) return '—'
|
||||||
return row.buyerNick || this.detailDataField(row, 'buyer_nick') || '—'
|
return row.buyerNick || this.detailDataField(row, 'buyer_nick') || '—'
|
||||||
},
|
},
|
||||||
|
/** 收件人:优先订单 detail_json(平台),再退列表/推送落库字段;不用京东侧兜底(京东地址单列展示) */
|
||||||
displayReceiverName(row) {
|
displayReceiverName(row) {
|
||||||
if (!row) return '-'
|
if (!row) return '-'
|
||||||
return row.receiverName || this.detailDataField(row, 'receiver_name') || '-'
|
const d = this.detailOrderData(row)
|
||||||
|
if (d) {
|
||||||
|
const n = this.firstNonEmptyStr(d, ['receiver_name', 'ship_name', 'consignee_name', 'contact_name'])
|
||||||
|
if (n) return n
|
||||||
|
const recv = d.receiver
|
||||||
|
if (recv && recv.name != null && String(recv.name).trim() !== '') return String(recv.name).trim()
|
||||||
|
}
|
||||||
|
if (row.receiverName) return row.receiverName
|
||||||
|
return '-'
|
||||||
},
|
},
|
||||||
displayReceiverMobile(row) {
|
displayReceiverMobile(row) {
|
||||||
if (!row) return ''
|
if (!row) return ''
|
||||||
const m = row.receiverMobile || this.detailDataField(row, 'receiver_mobile')
|
const d = this.detailOrderData(row)
|
||||||
return m || ''
|
if (d) {
|
||||||
|
const m = this.firstNonEmptyStr(d, ['receiver_mobile', 'ship_mobile', 'receiver_phone', 'contact_mobile'])
|
||||||
|
if (m) return m
|
||||||
|
const recv = d.receiver
|
||||||
|
if (recv) {
|
||||||
|
const mm = recv.mobile || recv.phone
|
||||||
|
if (mm != null && String(mm).trim() !== '') return String(mm).trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (row.receiverMobile) return row.receiverMobile
|
||||||
|
return ''
|
||||||
},
|
},
|
||||||
displayRecvSplit(row) {
|
displayRecvSplit(row) {
|
||||||
if (!row) return '—'
|
if (!row) return '—'
|
||||||
@@ -275,14 +403,49 @@ export default {
|
|||||||
const s = [p, c, a, t].filter(x => x != null && String(x).trim() !== '').map(x => String(x).trim()).join(' ')
|
const s = [p, c, a, t].filter(x => x != null && String(x).trim() !== '').map(x => String(x).trim()).join(' ')
|
||||||
return s || '—'
|
return s || '—'
|
||||||
},
|
},
|
||||||
|
/** 详细地址:优先平台详情字段,再用列表字段;京东整段地址见「京东地址」列 */
|
||||||
displayAddressLine(row) {
|
displayAddressLine(row) {
|
||||||
if (!row) return '—'
|
if (!row) return '—'
|
||||||
const a = row.receiverAddress || this.detailDataField(row, 'address')
|
const d = this.detailOrderData(row)
|
||||||
return a || '—'
|
if (d) {
|
||||||
|
const a = this.firstNonEmptyStr(d, ['receiver_address', 'ship_address', 'detail_address', 'full_address', 'address'])
|
||||||
|
if (a) return a
|
||||||
|
const recv = d.receiver
|
||||||
|
if (recv && recv.address != null && String(recv.address).trim() !== '') return String(recv.address).trim()
|
||||||
|
}
|
||||||
|
if (row.receiverAddress) return row.receiverAddress
|
||||||
|
return '—'
|
||||||
},
|
},
|
||||||
displayWaybillNo(row) {
|
normalizeWaybill(v) {
|
||||||
if (!row) return '—'
|
if (v == null || v === '') return ''
|
||||||
return row.detailWaybillNo || this.detailDataField(row, 'waybill_no') || '—'
|
return String(v).trim()
|
||||||
|
},
|
||||||
|
/** 开放平台 / 详情中的运单号 */
|
||||||
|
platformWaybillRaw(row) {
|
||||||
|
if (!row) return ''
|
||||||
|
if (row.detailWaybillNo != null && String(row.detailWaybillNo).trim() !== '') {
|
||||||
|
return this.normalizeWaybill(row.detailWaybillNo)
|
||||||
|
}
|
||||||
|
return this.normalizeWaybill(this.detailDataField(row, 'waybill_no'))
|
||||||
|
},
|
||||||
|
/** 物流扫描写入 Redis 后同步的本地运单 */
|
||||||
|
localWaybillRaw(row) {
|
||||||
|
if (!row || row.localWaybillNo == null) return ''
|
||||||
|
return this.normalizeWaybill(row.localWaybillNo)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 运单展示:双方一致→绿色单行;仅有一边→单行提示;不一致→红色双行
|
||||||
|
*/
|
||||||
|
waybillDisplay(row) {
|
||||||
|
const platform = this.platformWaybillRaw(row)
|
||||||
|
const local = this.localWaybillRaw(row)
|
||||||
|
if (!platform && !local) return { kind: 'empty' }
|
||||||
|
if (platform && local) {
|
||||||
|
if (platform === local) return { kind: 'match', text: platform }
|
||||||
|
return { kind: 'mismatch', platform, local }
|
||||||
|
}
|
||||||
|
if (platform) return { kind: 'single', text: platform, source: 'platform' }
|
||||||
|
return { kind: 'single', text: local, source: 'local' }
|
||||||
},
|
},
|
||||||
displayExpressName(row) {
|
displayExpressName(row) {
|
||||||
if (!row) return '—'
|
if (!row) return '—'
|
||||||
@@ -392,6 +555,7 @@ export default {
|
|||||||
openJson(row) {
|
openJson(row) {
|
||||||
this.jsonRow = { ...row }
|
this.jsonRow = { ...row }
|
||||||
this.jsonTab = 'sum'
|
this.jsonTab = 'sum'
|
||||||
|
this.eventLogs = []
|
||||||
this.jsonOpen = true
|
this.jsonOpen = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,4 +627,35 @@ export default {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
}
|
}
|
||||||
|
.waybill-cell {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.waybill-cell--match {
|
||||||
|
color: #67c23a;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.waybill-cell--single {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
.waybill-cell--hint {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.waybill-cell--warn {
|
||||||
|
color: #f56c6c;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.45;
|
||||||
|
}
|
||||||
|
.waybill-cell--warn-title {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
.waybill-cell--warn-title .el-icon-warning-outline {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.waybill-cell--line {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -17,13 +17,24 @@
|
|||||||
<el-input v-model="form.model" placeholder="必填" clearable />
|
<el-input v-model="form.model" placeholder="必填" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="下单地址" required>
|
<el-form-item label="下单地址" required>
|
||||||
<el-input v-model="form.address" type="textarea" :rows="3" placeholder="必填,与中控「生」指令第 6 行一致" clearable />
|
<el-input
|
||||||
|
v-model="form.address"
|
||||||
|
type="textarea"
|
||||||
|
:rows="2"
|
||||||
|
placeholder="必填;可粘贴多行,失焦或点击录单时会压成一行(去逗号、多空格合并)"
|
||||||
|
clearable
|
||||||
|
@blur="normalizeAddressField"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="转链链接(可空)">
|
<el-form-item label="转链链接(可空)">
|
||||||
<el-input v-model="form.link" type="textarea" :rows="2" placeholder="可空;留空则后台按型号尝试自动填充京粉链接" clearable />
|
<el-input v-model="form.link" type="textarea" :rows="2" placeholder="可空;留空则后台按型号尝试自动填充京粉链接" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数量">
|
<el-form-item label="第三方单号(选填)">
|
||||||
<el-input-number v-model="form.qty" :min="1" :max="99" controls-position="right" :style="qtyInputStyle" />
|
<el-input
|
||||||
|
v-model="form.thirdPartyOrderNoText"
|
||||||
|
placeholder="选填;写入录单文案「第三方单号:」行,可覆盖「生」自动带出内容"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-divider content-position="left">落库必填(与中控录单一致)</el-divider>
|
<el-divider content-position="left">落库必填(与中控录单一致)</el-divider>
|
||||||
@@ -95,7 +106,7 @@ export default {
|
|||||||
model: '',
|
model: '',
|
||||||
address: '',
|
address: '',
|
||||||
link: '',
|
link: '',
|
||||||
qty: 1,
|
thirdPartyOrderNoText: '',
|
||||||
buyer: '',
|
buyer: '',
|
||||||
paymentText: '',
|
paymentText: '',
|
||||||
rebateText: '',
|
rebateText: '',
|
||||||
@@ -116,11 +127,6 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
dialogWidth() {
|
dialogWidth() {
|
||||||
return this.isMobile ? '92%' : '480px'
|
return this.isMobile ? '92%' : '480px'
|
||||||
},
|
|
||||||
qtyInputStyle() {
|
|
||||||
return this.isMobile
|
|
||||||
? { width: '100%' }
|
|
||||||
: { width: '200px' }
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -142,10 +148,14 @@ export default {
|
|||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.trim()
|
.trim()
|
||||||
},
|
},
|
||||||
|
normalizeAddressField() {
|
||||||
|
this.form.address = this.compressAddressOneLine(this.form.address)
|
||||||
|
},
|
||||||
buildCommand() {
|
buildCommand() {
|
||||||
const mark = this.buildDistributionMark()
|
const mark = this.buildDistributionMark()
|
||||||
const model = (this.form.model || '').trim()
|
const model = (this.form.model || '').trim()
|
||||||
const address = this.compressAddressOneLine(this.form.address)
|
this.normalizeAddressField()
|
||||||
|
const address = (this.form.address || '').trim()
|
||||||
if (!model) {
|
if (!model) {
|
||||||
this.$modal.msgError('请填写型号')
|
this.$modal.msgError('请填写型号')
|
||||||
return null
|
return null
|
||||||
@@ -155,8 +165,7 @@ export default {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const link = (this.form.link || '').trim()
|
const link = (this.form.link || '').trim()
|
||||||
const qty = Number(this.form.qty) > 0 ? Number(this.form.qty) : 1
|
const lines = ['生', mark, model, link, '1', address]
|
||||||
const lines = ['生', mark, model, link, String(qty), address]
|
|
||||||
return lines.join('\n')
|
return lines.join('\n')
|
||||||
},
|
},
|
||||||
injectOptional(raw) {
|
injectOptional(raw) {
|
||||||
@@ -167,6 +176,11 @@ export default {
|
|||||||
const rebate = (this.form.rebateText || '').trim()
|
const rebate = (this.form.rebateText || '').trim()
|
||||||
const orderId = (this.form.orderIdText || '').trim()
|
const orderId = (this.form.orderIdText || '').trim()
|
||||||
const logistics = (this.form.logisticsLink || '').trim()
|
const logistics = (this.form.logisticsLink || '').trim()
|
||||||
|
const thirdPartyOrderNo = (this.form.thirdPartyOrderNoText || '').trim()
|
||||||
|
if (thirdPartyOrderNo) {
|
||||||
|
const re = /(第三方单号:)\n([^\n]*)\n(—————————)/g
|
||||||
|
t = t.replace(re, (_, a, _line, sep) => `${a}\n${thirdPartyOrderNo}\n${sep}`)
|
||||||
|
}
|
||||||
if (buyer) {
|
if (buyer) {
|
||||||
t = t.replace(/(下单人(需填):)\n\n/, `$1\n${buyer}\n\n`)
|
t = t.replace(/(下单人(需填):)\n\n/, `$1\n${buyer}\n\n`)
|
||||||
}
|
}
|
||||||
@@ -352,7 +366,7 @@ export default {
|
|||||||
model: '',
|
model: '',
|
||||||
address: '',
|
address: '',
|
||||||
link: '',
|
link: '',
|
||||||
qty: 1,
|
thirdPartyOrderNoText: '',
|
||||||
buyer: '',
|
buyer: '',
|
||||||
paymentText: '',
|
paymentText: '',
|
||||||
rebateText: '',
|
rebateText: '',
|
||||||
|
|||||||
@@ -297,9 +297,21 @@
|
|||||||
<span class="field-label">订单号</span>
|
<span class="field-label">订单号</span>
|
||||||
<span class="field-value">{{ row.orderId }}</span>
|
<span class="field-value">{{ row.orderId }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-row" v-if="row.thirdPartyOrderNo">
|
<div class="field-row field-row--third-party">
|
||||||
<span class="field-label">第三方单号</span>
|
<span class="field-label">第三方单号</span>
|
||||||
|
<template v-if="row.thirdPartyOrderNo">
|
||||||
<span class="field-value">{{ row.thirdPartyOrderNo }}</span>
|
<span class="field-value">{{ row.thirdPartyOrderNo }}</span>
|
||||||
|
</template>
|
||||||
|
<div v-else class="field-value field-value--third-party-edit">
|
||||||
|
<el-input
|
||||||
|
v-model="row.thirdPartyOrderNo"
|
||||||
|
size="small"
|
||||||
|
clearable
|
||||||
|
placeholder="可粘贴,失焦或点保存写入"
|
||||||
|
@blur="onThirdPartyOrderNoBlur(row)"
|
||||||
|
/>
|
||||||
|
<el-button type="primary" size="mini" plain @click="onThirdPartyOrderNoSave(row)">保存</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-row">
|
<div class="field-row">
|
||||||
<span class="field-label">标记</span>
|
<span class="field-label">标记</span>
|
||||||
@@ -466,10 +478,20 @@
|
|||||||
<!-- 核心信息列 -->
|
<!-- 核心信息列 -->
|
||||||
<el-table-column label="内部单号" prop="remark" width="120" sortable :fixed="isMobile ? false : 'left'"/>
|
<el-table-column label="内部单号" prop="remark" width="120" sortable :fixed="isMobile ? false : 'left'"/>
|
||||||
<el-table-column label="订单号" prop="orderId" width="160"/>
|
<el-table-column label="订单号" prop="orderId" width="160"/>
|
||||||
<el-table-column label="第三方单号" prop="thirdPartyOrderNo" width="140">
|
<el-table-column label="第三方单号" prop="thirdPartyOrderNo" min-width="188">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span v-if="scope.row.thirdPartyOrderNo">{{ scope.row.thirdPartyOrderNo }}</span>
|
<template v-if="scope.row.thirdPartyOrderNo">
|
||||||
<span v-else style="color: #999;">-</span>
|
<span>{{ scope.row.thirdPartyOrderNo }}</span>
|
||||||
|
</template>
|
||||||
|
<div v-else class="jd-third-party-empty">
|
||||||
|
<el-input
|
||||||
|
v-model="scope.row.thirdPartyOrderNo"
|
||||||
|
size="mini"
|
||||||
|
clearable
|
||||||
|
placeholder="粘贴后失焦保存"
|
||||||
|
@blur="onThirdPartyOrderNoBlur(scope.row)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@@ -1678,6 +1700,22 @@ export default {
|
|||||||
this.getList()
|
this.getList()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/** 第三方单号为空时粘贴补录:去空白后写入 */
|
||||||
|
saveThirdPartyOrderNoIfFilled(row, successMsg) {
|
||||||
|
const v = row.thirdPartyOrderNo == null ? '' : String(row.thirdPartyOrderNo).trim().replace(/\s+/g, '')
|
||||||
|
if (!v) {
|
||||||
|
row.thirdPartyOrderNo = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
row.thirdPartyOrderNo = v
|
||||||
|
this.persistOrderRow(row, successMsg)
|
||||||
|
},
|
||||||
|
onThirdPartyOrderNoBlur(row) {
|
||||||
|
this.saveThirdPartyOrderNoIfFilled(row)
|
||||||
|
},
|
||||||
|
onThirdPartyOrderNoSave(row) {
|
||||||
|
this.saveThirdPartyOrderNoIfFilled(row, '第三方单号已保存')
|
||||||
|
},
|
||||||
onOrderSellingPriceTypeChange(row) {
|
onOrderSellingPriceTypeChange(row) {
|
||||||
row.sellingPriceManual = 0
|
row.sellingPriceManual = 0
|
||||||
row.profitManual = 0
|
row.profitManual = 0
|
||||||
@@ -3944,6 +3982,31 @@ export default {
|
|||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 第三方单号为空:表格内粘贴补录 */
|
||||||
|
.jd-third-party-empty {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.jd-third-party-empty ::v-deep .el-input {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端卡片:第三方单号补录 */
|
||||||
|
.field-value--third-party-edit {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.field-value--third-party-edit ::v-deep .el-button {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user