1
This commit is contained in:
@@ -27,12 +27,39 @@ export function getJDOrder(id) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表编辑行为 Vue 响应式对象时,axios 内部 JSON.stringify 可能遗漏部分枚举字段;
|
||||||
|
* 先转为普通对象,并始终带上 extraCost(对应后端 JDOrder.extraCost / jd_order.extra_cost)。
|
||||||
|
*/
|
||||||
|
export function normalizeJDOrderPutPayload(data) {
|
||||||
|
if (!data || typeof data !== 'object') return {}
|
||||||
|
let plain
|
||||||
|
try {
|
||||||
|
plain = JSON.parse(JSON.stringify(data))
|
||||||
|
} catch (e) {
|
||||||
|
plain = Object.assign({}, data)
|
||||||
|
}
|
||||||
|
const pick = v => {
|
||||||
|
if (v === undefined || v === null || v === '') return undefined
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
const raw =
|
||||||
|
pick(data.extraCost) ??
|
||||||
|
pick(data.extra_cost) ??
|
||||||
|
pick(plain.extraCost) ??
|
||||||
|
pick(plain.extra_cost)
|
||||||
|
const num = raw !== undefined ? Number(raw) : NaN
|
||||||
|
plain.extraCost = Number.isFinite(num) ? num : 0
|
||||||
|
delete plain.extra_cost
|
||||||
|
return plain
|
||||||
|
}
|
||||||
|
|
||||||
// 更新JD订单
|
// 更新JD订单
|
||||||
export function updateJDOrder(data) {
|
export function updateJDOrder(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/jdorder',
|
url: '/system/jdorder',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: normalizeJDOrderPutPayload(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1298,7 +1298,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listJDOrders, getJDOrder, updateJDOrder, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcelBatch, listGroupRebateExcelUploads, deleteGroupRebateUpload, recalcProfitBatch, syncAutoProfitBatch } from '@/api/system/jdorder'
|
import { listJDOrders, getJDOrder, updateJDOrder, normalizeJDOrderPutPayload, delJDOrder, fetchLogisticsManually, batchMarkRebateReceived, generateExcelText, importGroupRebateExcelBatch, listGroupRebateExcelUploads, deleteGroupRebateUpload, recalcProfitBatch, syncAutoProfitBatch } from '@/api/system/jdorder'
|
||||||
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
|
import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserInfo, getAutoWriteConfig, reverseSyncThirdPartyOrderNo } from '@/api/jarvis/tendoc'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import ListLayout from '@/components/ListLayout'
|
import ListLayout from '@/components/ListLayout'
|
||||||
@@ -1410,6 +1410,12 @@ export default {
|
|||||||
/** 单行 PUT 防抖(避免 change+blur 连击触发若依重复提交拦截) */
|
/** 单行 PUT 防抖(避免 change+blur 连击触发若依重复提交拦截) */
|
||||||
_persistOrderTimers: null,
|
_persistOrderTimers: null,
|
||||||
_persistOrderPendingMsg: null,
|
_persistOrderPendingMsg: null,
|
||||||
|
/** 列表刚从接口赋值后的短时间内:忽略金额组件误触发的 change,避免误 PUT */
|
||||||
|
_listHydrating: false,
|
||||||
|
_hydrateUnlockTimer: null,
|
||||||
|
/** 与后端 SameUrlDataInterceptor 对齐:极短时间内相同 JSON body 不重复发送 */
|
||||||
|
_jdPutDedupeFingerprint: null,
|
||||||
|
_jdPutDedupeAt: 0,
|
||||||
/** 移动端卡片:当前展开的订单 id(null 表示全部收起,同时只展开一条) */
|
/** 移动端卡片:当前展开的订单 id(null 表示全部收起,同时只展开一条) */
|
||||||
mobileExpandedOrderId: null,
|
mobileExpandedOrderId: null,
|
||||||
/** 视口高度(桌面端用于矮窗口下自动收起「跟进状态」筛选) */
|
/** 视口高度(桌面端用于矮窗口下自动收起「跟进状态」筛选) */
|
||||||
@@ -1558,6 +1564,10 @@ export default {
|
|||||||
if (this._persistOrderTimers) {
|
if (this._persistOrderTimers) {
|
||||||
Object.keys(this._persistOrderTimers).forEach(k => clearTimeout(this._persistOrderTimers[k]))
|
Object.keys(this._persistOrderTimers).forEach(k => clearTimeout(this._persistOrderTimers[k]))
|
||||||
}
|
}
|
||||||
|
if (this._hydrateUnlockTimer) {
|
||||||
|
clearTimeout(this._hydrateUnlockTimer)
|
||||||
|
this._hydrateUnlockTimer = null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onJdFilterViewportResize() {
|
onJdFilterViewportResize() {
|
||||||
@@ -1715,10 +1725,29 @@ export default {
|
|||||||
isReviewPosted: item.isReviewPosted != null ? item.isReviewPosted : 0,
|
isReviewPosted: item.isReviewPosted != null ? item.isReviewPosted : 0,
|
||||||
sellingPriceManual: item.sellingPriceManual != null ? item.sellingPriceManual : 0,
|
sellingPriceManual: item.sellingPriceManual != null ? item.sellingPriceManual : 0,
|
||||||
profitManual: item.profitManual != null ? item.profitManual : 0,
|
profitManual: item.profitManual != null ? item.profitManual : 0,
|
||||||
extraCost: item.extraCost != null ? Number(item.extraCost) : 0
|
extraCost: item.extraCost != null ? Number(item.extraCost) : 0,
|
||||||
|
/** null 库内也表示「参与统计」,Switch 只能绑 0/1,统一成整数避免挂载时抖动触发 change */
|
||||||
|
isCountEnabled: item.isCountEnabled === 0 ? 0 : 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
assignListFromResponse(res) {
|
assignListFromResponse(res) {
|
||||||
|
this._listHydrating = true
|
||||||
|
if (this._hydrateUnlockTimer) {
|
||||||
|
clearTimeout(this._hydrateUnlockTimer)
|
||||||
|
this._hydrateUnlockTimer = null
|
||||||
|
}
|
||||||
|
if (this._persistOrderTimers) {
|
||||||
|
Object.keys(this._persistOrderTimers).forEach(k => {
|
||||||
|
clearTimeout(this._persistOrderTimers[k])
|
||||||
|
delete this._persistOrderTimers[k]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this._persistOrderPendingMsg) {
|
||||||
|
Object.keys(this._persistOrderPendingMsg).forEach(k => delete this._persistOrderPendingMsg[k])
|
||||||
|
}
|
||||||
|
this._jdPutDedupeFingerprint = null
|
||||||
|
this._jdPutDedupeAt = 0
|
||||||
|
|
||||||
this._distMarkBaseline = {}
|
this._distMarkBaseline = {}
|
||||||
this._modelNumberBaseline = {}
|
this._modelNumberBaseline = {}
|
||||||
const list = (res.rows || res.data || [])
|
const list = (res.rows || res.data || [])
|
||||||
@@ -1727,6 +1756,12 @@ export default {
|
|||||||
if (this.isMobile) {
|
if (this.isMobile) {
|
||||||
this.mobileExpandedOrderId = null
|
this.mobileExpandedOrderId = null
|
||||||
}
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this._hydrateUnlockTimer = setTimeout(() => {
|
||||||
|
this._hydrateUnlockTimer = null
|
||||||
|
this._listHydrating = false
|
||||||
|
}, 120)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
toggleMobileOrderExpand(row) {
|
toggleMobileOrderExpand(row) {
|
||||||
if (!row || row.id == null) return
|
if (!row || row.id == null) return
|
||||||
@@ -2075,6 +2110,9 @@ export default {
|
|||||||
if (!row || row.id == null) {
|
if (!row || row.id == null) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
if (this._listHydrating) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
this.ensureMoneyFieldsForPersist(row)
|
this.ensureMoneyFieldsForPersist(row)
|
||||||
const sid = String(row.id)
|
const sid = String(row.id)
|
||||||
if (!this._persistOrderTimers) this._persistOrderTimers = {}
|
if (!this._persistOrderTimers) this._persistOrderTimers = {}
|
||||||
@@ -2095,14 +2133,51 @@ export default {
|
|||||||
this.flushPersistOrderRow(row, msg)
|
this.flushPersistOrderRow(row, msg)
|
||||||
}, 340)
|
}, 340)
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* PUT /system/jdorder:若依 SameUrlDataInterceptor 判定「同 URL + 同 body + 短间隔」为重复提交;
|
||||||
|
* 移动端多张卡片内控件挂载时可能对同一行连发两次相同 payload,此处丢弃后者。
|
||||||
|
*/
|
||||||
|
performJDOrderUpdate(row) {
|
||||||
|
if (!row || row.id == null) {
|
||||||
|
return Promise.reject(new Error('无效订单'))
|
||||||
|
}
|
||||||
|
const plain = normalizeJDOrderPutPayload(row)
|
||||||
|
let serialized = ''
|
||||||
|
try {
|
||||||
|
serialized = JSON.stringify(plain)
|
||||||
|
} catch (e) {
|
||||||
|
serialized = ''
|
||||||
|
}
|
||||||
|
const fp = `${plain.id}\u0000${serialized}`
|
||||||
|
const now = Date.now()
|
||||||
|
const windowMs = 550
|
||||||
|
if (
|
||||||
|
fp === this._jdPutDedupeFingerprint &&
|
||||||
|
now - this._jdPutDedupeAt < windowMs
|
||||||
|
) {
|
||||||
|
return Promise.resolve({ skipped: true })
|
||||||
|
}
|
||||||
|
this._jdPutDedupeFingerprint = fp
|
||||||
|
this._jdPutDedupeAt = now
|
||||||
|
return updateJDOrder(row)
|
||||||
|
.then(res => ({ skipped: false, res }))
|
||||||
|
.catch(err => {
|
||||||
|
if (`${plain.id}\u0000${serialized}` === this._jdPutDedupeFingerprint) {
|
||||||
|
this._jdPutDedupeFingerprint = null
|
||||||
|
this._jdPutDedupeAt = 0
|
||||||
|
}
|
||||||
|
return Promise.reject(err)
|
||||||
|
})
|
||||||
|
},
|
||||||
flushPersistOrderRow(row, successMsg) {
|
flushPersistOrderRow(row, successMsg) {
|
||||||
if (!row || row.id == null) {
|
if (!row || row.id == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.ensureMoneyFieldsForPersist(row)
|
this.ensureMoneyFieldsForPersist(row)
|
||||||
this.invalidatePendingSyncAutoProfit()
|
this.invalidatePendingSyncAutoProfit()
|
||||||
updateJDOrder(row)
|
this.performJDOrderUpdate(row)
|
||||||
.then(() => {
|
.then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
if (successMsg) this.$message.success(successMsg)
|
if (successMsg) this.$message.success(successMsg)
|
||||||
this.schedulePatchOrderRowFromServer(row.id)
|
this.schedulePatchOrderRowFromServer(row.id)
|
||||||
})
|
})
|
||||||
@@ -2286,8 +2361,9 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 处理统计开关变化 */
|
/** 处理统计开关变化 */
|
||||||
handleCountEnabledChange(row) {
|
handleCountEnabledChange(row) {
|
||||||
// 调用后端API更新数据库
|
if (this._listHydrating) return
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的统计状态已更新为:${row.isCountEnabled ? '参与统计' : '不参与统计'}`)
|
this.$message.success(`订单 ${row.remark} 的统计状态已更新为:${row.isCountEnabled ? '参与统计' : '不参与统计'}`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2309,7 +2385,8 @@ export default {
|
|||||||
}
|
}
|
||||||
this.invalidatePendingSyncAutoProfit()
|
this.invalidatePendingSyncAutoProfit()
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
|
||||||
this.schedulePatchOrderRowFromServer(row.id)
|
this.schedulePatchOrderRowFromServer(row.id)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@@ -2332,7 +2409,8 @@ export default {
|
|||||||
row.refundDate = null
|
row.refundDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的退款状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2356,7 +2434,8 @@ export default {
|
|||||||
row.refundReceivedDate = null
|
row.refundReceivedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2378,7 +2457,8 @@ export default {
|
|||||||
row.refundReceivedDate = null
|
row.refundReceivedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的退款到账状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2402,7 +2482,8 @@ export default {
|
|||||||
row.rebateReceivedDate = null
|
row.rebateReceivedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2424,7 +2505,8 @@ export default {
|
|||||||
row.rebateReceivedDate = null
|
row.rebateReceivedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的后返到账状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2448,7 +2530,8 @@ export default {
|
|||||||
row.priceProtectedDate = null
|
row.priceProtectedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的点过价保状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的点过价保状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2472,7 +2555,8 @@ export default {
|
|||||||
row.invoiceOpenedDate = null
|
row.invoiceOpenedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的开过专票状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的开过专票状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
@@ -2496,7 +2580,8 @@ export default {
|
|||||||
row.reviewPostedDate = null
|
row.reviewPostedDate = null
|
||||||
}
|
}
|
||||||
// 调用后端API更新数据库
|
// 调用后端API更新数据库
|
||||||
updateJDOrder(row).then(() => {
|
this.performJDOrderUpdate(row).then(pack => {
|
||||||
|
if (pack.skipped) return
|
||||||
this.$message.success(`订单 ${row.remark} 的晒过评价状态已更新`)
|
this.$message.success(`订单 ${row.remark} 的晒过评价状态已更新`)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$message.error('更新失败,请稍后重试')
|
this.$message.error('更新失败,请稍后重试')
|
||||||
|
|||||||
Reference in New Issue
Block a user