Files
temu-plugin/src/view/NormalSendGoods.vue
liushiwei 3d78d229b2 调整
2023-08-17 09:01:30 +08:00

732 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<ai-list class="list">
<ai-title
slot="title"
title="普通备货单"
tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态"
isShowBottomBorder>
</ai-title>
<template slot="content">
<ai-search-bar>
<template #left>
<el-dropdown @command="handleClick">
<el-button type="primary" :disabled="isBegin">添加备货单</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="byStore">按店铺添加</el-dropdown-item>
<el-dropdown-item command="loadAll">一键添加所有</el-dropdown-item>
</el-dropdown-menu>
<!--<el-button type="primary" :disabled="isBegin" @click="isShow = true">添加备货单</el-button>
<el-button type="primary" :disabled="isBegin" @click="loadAll">一键加载全部</el-button>-->
</el-dropdown>
<el-button v-if="!isBegin" type="button" :class="'el-button el-button--primary'" @click="handleRobClick('normal')">开始抢仓</el-button>
<!--<el-dropdown @command="handleRobClick" v-if="!isBegin">
<el-button type="button" :class="'el-button el-button--primary'">开始抢仓</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :disabled="isBegin" command="normal">普通抢仓</el-dropdown-item>
<el-dropdown-item :disabled="isBegin" command="faster">极速抢仓</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>-->
<el-button v-else type="button" :icon="isBegin? 'el-icon-loading': ''" :class="isBegin ? 'el-button el-button--danger': 'el-button el-button--primary'" @click="beginRob()">{{ `结束抢仓(${choosedList.length}/${robTotal})` }}</el-button>
<!--<el-checkbox :disabled="isBegin" v-model="isCreateDeliveryBill">立即创建发货单</el-checkbox>-->
</template>
<template #right>
<el-badge v-if="networkErrorCount > 0" :value="networkErrorCount" style="margin-right: 10px">
<div class="tips">
<div></div>
</div>
</el-badge>
<el-badge :value="successList.length" class="item">
<el-button :icon="'el-icon-tickets'" @click="successDlgShow = true" circle></el-button>
</el-badge>
</template>
</ai-search-bar>
<ai-table
:tableData="choosedList"
:col-configs="robColConfigs"
:total="total"
:isShowPagination="false"
style="margin-top: 8px;">
<el-table-column slot="productName" width="480px" label="商品信息" align="center">
<template slot-scope="scope">
<div class="product">
<img :src="scope.row.productSkcPicture">
<div class="right">
<div>备货母单号: {{ scope.row.originalPurchaseOrderSn }}</div>
<el-tooltip effect="dark" :content="scope.row.productName" placement="top-start">
<div class="textoverflow">{{ scope.row.productName }}</div>
</el-tooltip>
<div>SKC: {{ scope.row.productSkcId }}</div>
<div>货号: {{ scope.row.productSn }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="robInfo" label="抢仓信息" width="140px" show-overflow-tooltip fixed="right" align="center">
<template slot-scope="scope">
<div data-testid="beast-core-box" style="margin-right: 2px;">
已抢仓 <div style="color: red; display: inline;">{{ scope.row.robTotal }}</div>
</div>
</template>
</el-table-column>
<el-table-column slot="className" label="SKU信息" width="440px" show-overflow-tooltip align="center">
<template slot-scope="scope">
<div class="order-manage_skuInfo__FW-Nd" v-for="(item, index) in scope.row.detailList" :key="index">
<div>
<div data-testid="beast-core-box" class="outerWrapper-1-3-1 outerWrapper-d18-1-3-20 index-module__image-preview___2fiZX">
<div class="index-module__img___p3B1N" :style="getStyle(item.thumbUrlList[0])"></div>
</div>
</div>
<div class="order-manage_contentInfo__1Cjd6" style="max-width: 150px;">
<div class="order-manage_title__1VTO5">属性{{ item.className }}</div>
<div>下单数量{{ item.purchaseQuantity }}</div>
<div>SKU ID {{ item.productSkuId }}</div>
<div class="order-manage_productSku__XP_ke">SKU 货号 {{ item.extCode }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="status" label="状态" show-overflow-tooltip align="center" width="120px">
<template slot-scope="scope">
<div data-testid="beast-core-box" class="outerWrapper-1-3-1 outerWrapper dot-module__dot___M-RuH " style="margin-right: 2px;">
<div class="dot-module__circle___2l2UV" style="background-color: var(--pc-dot-warn-bg-color,#ff6800);"></div>待发货
</div>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" width="80px" v-if="!isBegin" show-overflow-tooltip align="center" fixed="right">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="remove(row.subPurchaseOrderSn)">移除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
<AiDialog
title="添加备货单"
:visible.sync="isShow"
:close-on-click-modal="false"
customFooter
@confirm="onConfirm"
width="1290px">
<label style="width:90px">店铺</label>
<el-select v-model="mallId" placeholder="请选择" @change="mallChange">
<el-option
v-for="item in mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
{{ item.mallName }}
</el-option>
</el-select>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:isShowPagination="false"
style="margin-top: 8px;"
@selection-change="onChooseChange">
<el-table-column slot="productName" width="400px" label="商品信息" align="center">
<template slot-scope="scope">
<div class="product">
<img :src="scope.row.productSkcPicture">
<div class="right">
<div>备货母单号: {{ scope.row.originalPurchaseOrderSn }}</div>
<el-tooltip effect="dark" :content="scope.row.productName" placement="top-start">
<div class="textoverflow">{{ scope.row.productName }}</div>
</el-tooltip>
<div>SKC: {{ scope.row.productSkcId }}</div>
<div>货号: {{ scope.row.productSn }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="className" label="SKU信息" width="440px" show-overflow-tooltip align="center">
<template slot-scope="scope">
<div class="order-manage_skuInfo__FW-Nd" v-for="(item, index) in scope.row.detailList" :key="index">
<div>
<div data-testid="beast-core-box" class="outerWrapper-1-3-1 outerWrapper-d18-1-3-20 index-module__image-preview___2fiZX">
<div class="index-module__img___p3B1N" :style="getStyle(item.thumbUrlList[0])"></div>
</div>
</div>
<div class="order-manage_contentInfo__1Cjd6">
<div>属性{{ item.className }}</div>
<div>下单数量{{ item.purchaseQuantity }}</div>
<div>SKU ID {{ item.productSkuId }}</div>
<div class="order-manage_productSku__XP_ke">SKU 货号 {{ item.extCode }}</div>
</div>
</div>
</template>
</el-table-column>
</ai-table>
<span slot="footer" class="dialog-footer">
<el-button @click="isShow = false"> </el-button>
<el-button type="primary" @click="onConfirm">添加</el-button>
</span>
</AiDialog>
<AiDialog
title="抢单成功列表"
:visible.sync="successDlgShow"
:close-on-click-modal="false"
customFooter
width="1290px">
<label style="width:90px">店铺</label>
<el-select clearable v-model="successMallId" placeholder="请选择">
<el-option
v-for="item in mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
{{ item.mallName }}
</el-option>
</el-select>
<ai-table
:tableData="successData"
:col-configs="successColConfigs"
:total="total"
:isShowPagination="false"
style="margin-top: 8px;">
</ai-table>
<span slot="footer" class="dialog-footer">
<el-button @click="successDlgShow = false"> </el-button>
</span>
</AiDialog>
</template>
</ai-list>
</div>
</template>
<script>
import { mapState } from 'vuex'
import {sendChromeAPIMessage, sendChromeNotification} from '@/api/chromeApi'
import { Message } from 'element-ui'
export default {
name: 'NormalSendGoods',
data () {
return {
isShow: false,
colConfigs: [
{ type: "selection", width: '70px', align: 'left' },
{ prop: 'subPurchaseOrderSn', label: '备货单号', align: 'left' },
{ slot: 'productName' },
{ slot: 'className'},
{ slot: 'robInfo'},
{ slot: 'status' }
],
robColConfigs: [
{ prop: 'subPurchaseOrderSn', width: '180px', label: '备货单号', align: 'left' },
{ slot: 'productName' },
{ prop: 'mallName', label: '店铺来源', align: 'center' },
{ slot: 'className'},
{ slot: 'robInfo'},
{ slot: 'status' }
],
successColConfigs: [
{ prop: 'subPurchaseOrderSn', width: '180px', label: '备货单号', align: 'left' },
{ prop: 'mallName', label: '店铺来源', width: '180px', align: 'center' },
{ prop: 'productName', label: '商品名称', "show-overflow-tooltip": true, width: '580px' },
{ prop: 'productSn', label: '货号' }
],
mallId: '',
mallName: '',
tableData: [],
total: 0,
isBegin: false,
choosedList: [],
choosedSnMallList: [],
arr: [],
robTotal: 0,
pageSize: 100,
currentPage: 1,
step: 500,
randomValue: 500,
timer: [],
loadMallIndex: 0,
loadMode: 0, // 加载模式0表示单个店铺加载1表示一键加载
robMode: 0, // 抢仓模式0表示普通抢仓1表示极速抢仓
isCreateDeliveryBill: false,
// 网络超时次数
networkErrorCount: 0,
successDlgShow: false,
successMallId: '',
successList: [],
}
},
computed: {
...mapState(['mallList']),
successData() {
if (!this.successMallId) {
return this.successList
}
return this.successList.filter(item => {
return item.mallId == this.successMallId
})
}
},
created () {
},
methods: {
onChooseChange (e) {
this.arr = e
},
mallChange() {
this.$userCheck(this.mallId).then(() => {
let mallInfo = this.mallList.filter(item => {
return item.mallId == this.mallId
})
this.mallName = mallInfo[0].mallName
// 下载数据
this.loadMode = 0
this.tableData = []
this.currentPage = 1
this.getList(this.tableData, this.mallId, this.mallName, 1)
}).catch((err) => {
console.log(err)
})
},
onConfirm () {
if (this.arr.length == 0) {
Message.error("请选择备货单")
return
}
this.arr.map(item => {
let temp = this.choosedList.filter(i => {
return i.subPurchaseOrderSn == item.subPurchaseOrderSn
})
if (temp.length == 0) {
this.choosedList.push(item)
}
})
Message.success("添加成功,可继续添加")
},
loadAll() {
this.$userCheck().then(() => {
this.choosedList = []
this.loadMallIndex = 0
this.loadMode = 1
this.getList(this.choosedList, this.mallList[this.loadMallIndex].mallId, this.mallList[this.loadMallIndex].mallName, 1)
});
},
handleClick (e) {
if (e === 'byStore') {
this.isShow = true
} else if (e === 'loadAll') {
this.loadAll()
}
},
handleRobClick (e) {
this.networkErrorCount = 0
if (e === 'normal') {
this.robMode = 0
} else if (e === 'faster') {
this.robMode = 1
}
this.beginRob()
},
getList (data, mallId, mallName, currentPage) {
sendChromeAPIMessage({
url: 'oms/bg/venom/api/supplier/purchase/manager/querySubOrderList',
needMallId: true,
mallId: mallId,
data: {
"pageNo": currentPage,
"pageSize": this.pageSize,
"urgencyType": 0,
"isCustomGoods": false,
"statusList": [
1
]
}}).then((res) => {
if (res.errorCode == 1000000) {
let length = res.result.subOrderForSupplierList.length
res.result.subOrderForSupplierList = res.result.subOrderForSupplierList.filter((item) => {
return item.isCanJoinDeliverPlatform;
})
res.result.subOrderForSupplierList.map((item) => {
data.push({
robTotal: 0,
subPurchaseOrderSn: item.subPurchaseOrderSn,
originalPurchaseOrderSn: item.originalPurchaseOrderSn,
productName: item.productName,
productSn: item.productSn,
productSkcId: item.productSkcId,
productSkcPicture: item.productSkcPicture,
status: item.status,
detailList: item.skuQuantityDetailList,
category: item.category,
mallId: mallId,
mallName: mallName
})
})
if (this.pageSize == length) {
currentPage ++
this.getList(data, mallId, mallName, currentPage)
} else {
if (this.loadMode == '1') {
this.loadMallIndex ++
if (this.loadMallIndex < this.mallList.length) {
this.getList(data, this.mallList[this.loadMallIndex].mallId, this.mallList[this.loadMallIndex].mallName, 1)
} else {
Message.success("所有店铺备货单已加载完成")
}
}
}
} else {
Message.error("【拼多多】" + res.errorMsg)
}
})
},
remove(sn) {
for (let i = 0; i < this.choosedList.length; i++) {
if (this.choosedList[i].subPurchaseOrderSn == sn) {
this.choosedList.splice(i, 1)
break
}
}
},
getStyle(url) {
return "background-image: url(" + url + "); width: 72px; height: 72px; cursor: pointer; border-radius: 6px; border: 1px solid rgba(0, 0, 0, 0.14);";
},
beginRob() {
if (this.isBegin) {
this.isBegin = false;
for (let i = 0;i < this.timer.length; i++) {
clearInterval(this.timer[i].timer);
}
return;
}
if (this.choosedList.length <= 0) {
Message.error('请添加备货单');
return;
}
this.choosedSnMallList = this.choosedList.map(item => {
return {sn: item.subPurchaseOrderSn, mallId: item.mallId}
})
this.robTotal = this.choosedList.length
this.isBegin = true;
this.timer = [];
if (0 == this.robMode) {
this.rob()
}
/*for (let i = 0;i < this.choosedList.length; i++) {
if (0 == this.robMode) {
setTimeout(() => {
this.rob(this.choosedList[i].subPurchaseOrderSn, this.choosedList[i].mallId)
}, this.step * i)
} else {
setTimeout(() => {
let t = setInterval(this.robFunc(this.choosedList[i].subPurchaseOrderSn, this.choosedList[i].mallId), 1000);
this.timer.push({id: this.choosedList[i].subPurchaseOrderSn, timer: t})
}, 100 * i)
}
}*/
let _this = this;
let tt = setInterval(function() {
if (_this.choosedList.length == 0) {
_this.isBegin = false;
clearInterval(tt);
}
}, 1000)
},
robFunc(sn, mallId) {
let _this = this;
return function() {
_this.rob(sn, mallId);
}
},
rob() {
let obj = this.choosedSnMallList.shift()
if (!obj || !this.isBegin) {
return
}
let sn = obj.sn
let mallId = obj.mallId
sendChromeAPIMessage({
url: 'oms/bg/venom/api/supplier/purchase/manager/joinDeliveryGoodsOrderPlatform',
needMallId: true,
anti: true,
mallId: mallId,
data: {
"subPurchaseOrderSn": sn
}}).then((res) => {
if (res.errorCode == 1000000) {
if (1 == this.robMode) {
let t = this.timer.filter((item) => {
return item.id == sn;
})
if (t.length > 0) {
clearInterval(t[0].timer)
}
}
for (let j = 0; j < this.choosedList.length; j++) {
if (this.choosedList[j].subPurchaseOrderSn == sn) {
this.successList.push(this.choosedList[j])
this.addSuccessInfo(this.choosedList[j]);
this.sendNotification(this.choosedList[j]);
this.choosedList.splice(j, 1);
break;
}
}
// 如果需要创建发货单
if (this.isCreateDeliveryBill) {
this.createDeliveryBill(sn, mallId)
}
} else {
this.choosedSnMallList.push(obj)
for (let j = 0; j < this.choosedList.length; j++) {
if (this.choosedList[j].subPurchaseOrderSn == sn) {
this.choosedList[j].robTotal ++;
break;
}
}
/*if (0 == this.robMode) {
if (this.isBegin) {
setTimeout(() => {
this.rob(sn, mallId)
}, this.choosedList.length * this.step)
}
}*/
}
if (!res.errorCode && res.error_code) {
this.networkErrorCount ++
}
if (0 == this.robMode) {
// 继续抢
setTimeout(() => {
this.rob()
}, this.step + Math.floor(Math.random() * this.randomValue))
}
})
},
createDeliveryBill(sn, mallId) {
sendChromeAPIMessage({
url: 'bgSongbird-api/supplier/deliverGoods/platform/pageQuerySubPurchaseOrder',
needMallId: true,
mallId: mallId,
data: {
"pageNo": 1,
"pageSize": 10,
"subPurchaseOrderSnList": [
sn
]
}}).then((res) => {
if (res.errorCode == 1000000) {
let data = res.result.list[0]
let deliverOrderDetailInfos = data.orderDetailVOList.map(item => {
return {
productSkuId: item.productSkuId,
deliverSkuNum: item.productSkuPurchaseQuantity
}
})
let packageDetailSaveInfos = data.orderDetailVOList.map(item => {
return {
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
}
})
let packageInfos = []
packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos})
let deliveryOrderCreateInfos = []
deliveryOrderCreateInfos.push({
deliverOrderDetailInfos: deliverOrderDetailInfos,
subPurchaseOrderSn: data.subPurchaseOrderBasicVO.subPurchaseOrderSn,
packageInfos: packageInfos
})
let deliveryOrderCreateGroupList = []
deliveryOrderCreateGroupList.push({
deliveryOrderCreateInfos: deliveryOrderCreateInfos,
receiveAddressInfo: data.subPurchaseOrderBasicVO.receiveAddressInfo,
subWarehouseId: data.subPurchaseOrderBasicVO.subWarehouseId
})
console.log(deliveryOrderCreateGroupList)
} else {
// setTimeout(this.createDeliveryBillFun(sn, mallId), 1000)
}
})
},
createDeliveryBillFun(sn, mallId) {
let _this = this;
return function() {
_this.createDeliveryBill(sn, mallId);
}
},
addSuccessInfo(obj) {
this.$http.post(`/api/successInfo/add`, {
productName: obj.productName,
subPurchaseOrderSn: obj.subPurchaseOrderSn,
mallId: obj.mallId,
mallName: obj.mallName,
categoryName: obj.category
}).then(res => {
console.log(res)
})
},
sendNotification(obj) {
sendChromeNotification({productName: obj.productName, mallName: obj.mallName})
}
}
}
</script>
<style scoped lang="scss">
.product {
display: flex;
align-items: center;
justify-content: center;
.right {
flex: 1;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
img {
width: 60px;
margin-right: 10px;
}
}
.tips {
position: relative;
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(243, 8, 8, .4);
@keyframes warn {
0% {
transform: translate(-50%, -50%) scale(0);
opacity: 1;
}
100% {
transform: translate(-50%, -50%) scale(1.1);
opacity: 0;
}
}
div {
position: absolute;
left: 50%;
top: 50%;
z-index: 11;
width: 100px;
height: 100px;
border-radius: 50%;
animation: warn 0.9s ease-out;
animation-iteration-count: infinite;
box-shadow: 1px 1px 30px #EF2D02;
transform: translate(-50%, -50%) scale(0.2);
transition: all ease-in-out 0.6s;
background: rgba(243, 8, 8, .6);
}
}
.order-manage_productInfo__1pD83>img {
width: 60px;
margin-right: 10px;
}
.order-manage_productInfo__1pD83 {
min-height: 60px;
padding-left: 70px;
position: relative;
}
.order-manage_productInfo__1pD83>div:nth-child(2) {
color: rgba(0,0,0,.8);
}
.outerWrapper {
margin: 4px 4px 0px 0px;
}
.dot-module__dot___M-RuH .dot-module__circle___2l2UV {
flex-shrink: 0;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 8px;
}
.dot-module__dot___M-RuH {
display: inline-flex;
align-items: center;
}
.index-module__image-preview___2fiZX .index-module__img___p3B1N {
width: 60px;
height: 60px;
margin-right: 10px;
background-repeat: no-repeat;
background-size: cover;
background-color: #f5f5f5;
font-size: 12px;
display: flex;
justify-content: center;
align-items: center;
color: var(--bc-Table-emptyTextColor);
position: relative;
}
.textoverflow {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
.order-manage_skuInfo__FW-Nd {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
.order-manage_contentInfo__1Cjd6 {
display: flex;
flex-direction: column;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 240px;
}
}
.order-manage_skuInfo__FW-Nd .order-manage_contentInfo__1Cjd6 .order-manage_title__1VTO5 {
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
color: rgba(0,0,0,.8);
}
</style>