Files
temu-plugin/src/view/semi/SemiSendGoods_XC.vue
liushiwei 74043c55ae 调整
2024-11-05 21:20:05 +08:00

830 lines
28 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" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
<ai-title
slot="title"
title="发货(芯仓)"
tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态"
isShowBottomBorder>
</ai-title>
<template slot="content">
<ai-search-bar>
<template #left>
<el-radio-group v-model="type">
<el-radio-button label="0">数据同步</el-radio-button>
<el-radio-button label="1">发货</el-radio-button>
</el-radio-group>
</template>
<template #right>
</template>
</ai-search-bar>
<ai-card :key="0" v-if="type == '0'" title="数据明细" style="padding-bottom: 40px;">
<template #right>
<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 type="button" :class="'el-button el-button--primary'" @click="beginCreate">订单同步</el-button>
</template>
<ai-table
:tableData="choosedList"
:col-configs="robColConfigs"
:total="total"
height="500"
: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.parentOrderMap.parentOrderSn }}</div>
<div>站点名: {{ scope.row.parentOrderMap.siteName }}</div>
<div>国家/地区: {{ scope.row.parentOrderMap.regionName1 }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="purchaseTime" width="180px" label="订单创建时间" align="center">
<template slot-scope="scope">
{{ scope.row.parentOrderMap.parentOrderTimeStr }}
</template>
</el-table-column>
<el-table-column slot="className" label="子订单信息" 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.orderList" :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.thumbUrl)"></div>
</div>
</div>
<div class="order-manage_contentInfo__1Cjd6">
<div>子订单号{{ item.orderSn}}</div>
<div>SKU ID{{ item.productInfoList[0].productSkuId }}</div>
<div>SKC ID{{ item.productInfoList[0].productSkcId }}</div>
<div>SKU 货号 {{ item.extCodeList[0] }}</div>
<div>属性 {{ item.spec }}</div>
<div>库存扣减仓库 {{ item.warehouseName }}</div>
</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.parentOrderMap.parentOrderSn)">移除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</ai-card>
<ai-card :key="1" v-if="type == '1'" title="待发货列表" style="padding-bottom: 40px;">
<template #title>
<el-button type="button" v-if="form.status == '0'" :class="'el-button el-button--primary'" @click="sendGoods">发货</el-button>
<el-button type="button" v-if="form.status == '1'" :class="'el-button el-button--primary'" @click="getLogisticInfo">取号</el-button>
<el-button type="button" v-if="form.status == '1'" :class="'el-button el-button--primary'" @click="writeBack">回传</el-button>
</template>
<template #right>
<ai-search-bar>
<template #right>
<div>
<div class="search-item" style="margin-top: 20px" >
<ai-select clearable :selectList="$dict.getDict('order_info_status')" v-model="form.status" @change="getOrderList"></ai-select>
</div>
</div>
</template>
</ai-search-bar>
</template>
<ai-table
:tableData="orderDataList"
:col-configs="orderColConfig"
height="700"
:size="100"
:current.sync="form.current"
:size.sync="form.size"
:total="orderTotal"
@getList="getOrderList"
style="margin-top: 8px;">
<el-table-column slot="options" label="操作" align="center" fixed="right" width="140px">
<template v-slot="{ row }">
<div class="table-options">
<el-button type="text" v-if="form.status == '1'" @click="toSend(row)">重新发货</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</ai-card>
<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;"
v-loading="isDlgLoading"
@selection-change="onChooseChange">
<el-table-column slot="productName" width="320px" label="订单信息" align="center">
<template slot-scope="scope">
<div class="product">
<img :src="scope.row.productSkcPicture">
<div class="right">
<div>{{ scope.row.parentOrderMap.parentOrderSn }}</div>
<div>站点名: {{ scope.row.parentOrderMap.siteName }}</div>
<div>国家/地区: {{ scope.row.parentOrderMap.regionName1 }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="purchaseTime" width="180px" label="订单创建时间" align="center">
<template slot-scope="scope">
{{ scope.row.parentOrderMap.parentOrderTimeStr }}
</template>
</el-table-column>
<el-table-column slot="className" label="子订单信息" 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.orderList" :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.thumbUrl)"></div>
</div>
</div>
<div class="order-manage_contentInfo__1Cjd6">
<div>子订单号{{ item.orderSn}}</div>
<div>SKU ID{{ item.productInfoList[0].productSkuId }}</div>
<div>SKC ID{{ item.productInfoList[0].productSkcId }}</div>
<div>SKU 货号 {{ item.extCodeList[0] }}</div>
<div>属性 {{ item.spec }}</div>
<div>库存扣减仓库 {{ item.warehouseName }}</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>
</template>
</ai-list>
</div>
</template>
<script>
import { mapState } from 'vuex'
import {sendChromeAPIMessage, sendTemuSellerAgentMessage, sendXcAPIMessage} from '@/api/chromeApi'
import { Message } from 'element-ui'
import {timestampToTime} from '@/utils/date'
export default {
name: 'SemiSendGoods_XC',
data () {
return {
isShow: false,
orderDataList: [],
orderTotal: 0,
colConfigs: [
{ type: "selection", width: '70px', align: 'left' },
{ slot: 'productName' },
{ slot: 'subWarehouseName'},
{ prop: 'mallName', label: '店铺来源', align: 'center' },
{ slot: 'className'},
{ slot: 'purchaseTime'}
],
robColConfigs: [
{ slot: 'productName' },
{ slot: 'subWarehouseName'},
{ prop: 'mallName', label: '店铺来源', align: 'center' },
{ slot: 'className'},
{ slot: 'purchaseTime'}
],
orderColConfig: [
{ prop: 'mallName', label: '店铺名称', align: 'center' },
{ prop: 'orderId', label: '订单号', width: '220px'},
{ prop: 'receiveName', label: '收货人'},
{ prop: 'receivePhone', label: '收货人手机号', width: '160px'},
{ prop: 'logisticId', label: '物流单号', width: '160px'},
{ prop: 'expressCompany', label: '物流方式', width: '120px'},
{ prop: 'expressId', label: '物流公司', width: '100px'},
{ prop: 'status', label: '状态', format: v => this.$dict.getLabel('order_info_status', v)},
{ prop: 'createTime', label: '下单时间'}
],
form: {
warehouseId: 'XinCang',
status: '',
current: 1,
size: 100
},
mallId: '',
mallName: '',
tableData: [],
total: 0,
isBegin: false,
choosedList: [],
choosedSnMallList: [],
arr: [],
createTotal: 0,
pageSize: 100,
currentPage: 1,
type: 0,
loadMallIndex: 0,
loadMode: 0, // 加载模式0表示单个店铺加载1表示一键加载
// 加载数据
isLoading: false,
isDlgLoading: false,
addressList: []
}
},
computed: {
...mapState(['mallList'])
},
created () {
this.$dict.load('order_info_status');
},
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.isDlgLoading = true
this.getList(this.tableData, this.mallId, this.mallName, 1)
}).catch((err) => {
this.mallId = ''
console.log(err)
})
},
onConfirm () {
if (this.arr.length == 0) {
Message.error("请选择待创建备货单")
return
}
this.arr.map(item => {
let temp = this.choosedList.filter(i => {
return i.parentOrderMap.parentOrderSn == item.parentOrderMap.parentOrderSn
})
if (temp.length == 0) {
this.choosedList.push(item)
}
})
Message.success("添加成功,可继续添加")
},
loadAll() {
this.$userCheck().then(() => {
this.choosedList = []
this.currentPage = 1
this.isLoading = true
if (this.$store.state.userInfo.type == 3) {
this.loadMode = 0
this.getList(this.choosedList, this.$store.state.mallId, this.$store.state.mallName, 1)
} else {
this.loadMallIndex = 0
this.loadMode = 1
this.getList(this.choosedList, this.mallList[this.loadMallIndex].mallId, this.mallList[this.loadMallIndex].mallName, 1)
}
});
},
getOrderList() {
this.orderDataList = []
let res = this.$http.post('/api/semi/semiOrder/pageWaitSend',null,{
params: {
...this.form
}
}).then(res => {
this.orderDataList = res.data.records
this.orderTotal = res.data.total
})
},
handleClick (e) {
if (e === 'byStore') {
this.isShow = true
} else if (e === 'loadAll') {
this.loadAll()
}
},
beforeBegin() {
if (this.choosedList.length <= 0) {
Message.error('请先添加待发货订单');
return;
}
this.beginCreate()
},
async getList (data, mallId, mallName, currentPage) {
let res = await sendTemuSellerAgentMessage({
url: 'kirogi/bg/mms/recentOrderList',
needMallId: true,
mallId: mallId,
data: {
fulfillmentMode: 0,
pageNumber: this.currentPage,
pageSize: this.pageSize,
queryType: 2,
sortType: 1,
timeZone: "UTC+8",
parentAfterSalesTag: 0,
needBuySignService: 0,
sellerNoteLabelList: []
}})
if (res.errorCode == 0) {
res.result.pageItems.map((item) => {
data.push({...item, mallId: mallId, mallName: mallName})
})
if (this.pageSize == res.result.pageItems.length) {
currentPage ++
await this.getList(data, mallId, mallName, currentPage)
} else {
if (this.loadMode == 1) {
this.loadMallIndex ++
if (this.loadMallIndex < this.mallList.length) {
await this.$sleepSync(500)
await this.getList(data, this.mallList[this.loadMallIndex].mallId, this.mallList[this.loadMallIndex].mallName, 1)
} else {
this.isLoading = false
this.isDlgLoading = false
Message.success("所有店铺待发货订单已加载完成")
}
} else {
this.isLoading = false
this.isDlgLoading = false
}
}
} else {
await this.getList(data, mallId, mallName, currentPage)
}
},
remove(parentOrderSn) {
for (let i = 0; i < this.choosedList.length; i++) {
if (this.choosedList[i].parentOrderMap.parentOrderSn == parentOrderSn) {
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);";
},
async beginCreate() {
let waitCreateList = []
this.choosedList.map(item => {
waitCreateList.push(item.parentOrderMap.parentOrderSn)
})
for (let j = 0; j < waitCreateList.length; j++) {
let obj = this.choosedList.filter(item => {
return item.parentOrderMap.parentOrderSn == waitCreateList[j]
})
let res = await sendTemuSellerAgentMessage({
url: 'mms/orchid/address/snapshot/order_shipping_address_query',
needMallId: true,
mallId: obj[0].mallId,
data: {
parent_order_sn: obj[0].parentOrderMap.parentOrderSn
}})
if (res.error_code == 1000000 && res.success) {
let data = {
source: 0,
receiveName: res.result.receipt_name,
receiveAddress1: res.result.address_line1,
receiveAddress2: res.result.address_line2,
receivePhone: res.result.mobile,
receiveEmail: res.result.mail,
receiveCity: res.result.region_name3,
receiveProvince: res.result.region_name2,
receiveZipcode: res.result.post_code,
mallId: obj[0].mallId,
mallName: obj[0].mallName,
orderId: obj[0].parentOrderMap.parentOrderSn,
status: 0,
type: 1,
details: [],
createTime: obj[0].parentOrderMap.parentOrderTimeStr
}
for (let k = 0; k < obj[0].orderList.length; k++) {
data.details.push({
temuWarehouseId: obj[0].orderList[k].warehouseId,
sku: obj[0].orderList[k].productInfoList[0].productSkuId,
num: obj[0].orderList[k].quantity,
createTime: obj[0].parentOrderMap.parentOrderTimeStr
})
}
let res1 = await this.$http.post(`/api/semi/semiOrder/addXc`, data)
if (res1.code == 0) {
this.remove(obj[0].parentOrderMap.parentOrderSn)
}
}
}
},
async sendGoods() {
for (let i = 0; i < this.orderDataList.length; i++) {
await this.toSend(this.orderDataList[i])
await this.$sleepSync(200)
}
this.getOrderList()
},
async toSend(obj) {
let params = {
warehouse_code: obj.details[0].warehouseCode,
name: obj.receiveName,
company: '',
address1: obj.receiveAddress1,
email: obj.receiveEmail,
address2: obj.receiveAddress2,
phone: obj.receivePhone,
address3: '',
consignee_phone_extension: '',
city: obj.receiveCity,
phone2: '',
province: obj.receiveProvince,
doorplate: '',
district: '',
license: '',
zipcode: obj.receiveZipcode,
country: 'US',
consignee_tax_type: '',
consignee_eori: '',
platform: '',
order_cod_price: '',
order_cod_currency: '',
shop: '',
refrence_no: obj.orderId,
courier: 'USPS-GALA',
calculation: 1,
is_discount: 1,
ignore_address: 0,
default_insurance_type: 1,
filter_sta_shipping: 1,
shipping_method_no: '',
is_insurance: '',
insurance_value: '',
insurance_value_currency: 'USD',
order_sale_amount: '',
order_sale_currency: '',
channel_code: '',
lifting_cabinet: '',
order_battery_type: '',
vat_tax_code: '',
is_platform_ebay: 0,
ebay_item_id: '',
ebay_transaction_id: '',
distribution_information: '',
IOSS: '',
insurance_type: '',
multiple_tracking_number: '',
is_allow_open: 0,
insurance_type_goods_value: '',
refrence_no_warehouse: '',
is_prime: '',
order_desc: '',
del_order_attached_ids: '',
order_type: 'sale',
order_business_type: 'b2c'
}
params['invoice[product_sku][]'] = ''
params['invoice[product_title_en][]'] = ''
params['invoice[product_title][]'] = ''
params['invoice[product_quantity][]'] = ''
params['invoice[unit_code][]'] = ''
params['invoice[product_declared_value][]'] = ''
params['invoice[product_weight][]'] = ''
if (obj.details[0].warehouseCode == 'UAXC002') {
params.courier = 'USPS'
}
for (let i = 0; i < obj.details.length; i++) {
params[`platform_barcode[${obj.details[i].productId}]`] = ''
params[`product_title_en[${obj.details[i].productId}]`] = obj.details[i].productTitleEn
params[`product_title[${obj.details[i].productId}]`] = obj.details[i].productTitle
params[`declared_value[${obj.details[i].productId}]`] = obj.details[i].declaredValue
params[`op_quantity[${obj.details[i].productId}]`] = obj.details[i].num
}
let res = await sendXcAPIMessage({
url: 'order/order/create/operation/0',
isFormData: true,
method: 'POST',
data: params})
if (res.ask == 1) {
let res1 = await this.$http.post(`/api/semi/semiOrder/updateStatus`, null, {params: {
id: obj.id,
status: 1
}})
if (res1.code != 0) {
Message.error(res1.msg)
}
} else {
Message.error(res.message)
}
},
async getLogisticInfo () {
for (let i = 0; i < this.orderDataList.length; i++) {
let params = {
warehouse_note: '',
is_vip: '',
allot_logistics_for_lg: '',
order_attachment: '',
is_cut_off: '',
large_order: '',
is_temu_warehouse: '',
'time-type': 'date_create',
'order-type': 'DESC',
ORDER_TRIAL_FEE_SHOW: 1,
type: 1,
code: this.orderDataList[i].orderId,
SKU: '',
channel_code: '',
platform_shop: '',
account_name: '',
deliveryFeeFor: '',
deliveryFeeTo: '',
serial_number: '',
create_type: '',
remark: '',
is_one_piece: '',
platform: '',
seller: '',
is_shared: '',
is_ques: '',
country: '',
warehouse_id: '',
shipping_method: '',
is_oda: '',
is_cod: '',
is_prime: '',
process_again: '',
ot_id: '',
abnormal_type: '',
sub_status: 0,
picking_status: '',
order_type: '',
longest_aging: '',
recipient_type: 'buyer_name',
recipient_info: '',
buyer_type: 'buyer_id',
buyer_info: '',
reference_no: '',
is_repeat: '',
is_return: '',
timeType: 'create',
DateFrom: '',
DateEnd: '',
E35: '',
insurance_status: '',
have_tracking_no: '',
keyword: '',
status: 3,
is_more: 0
}
let res = await sendXcAPIMessage({
url: 'order/order-list/list/a/a/page/1/pageSize/50',
isFormData: true,
method: 'POST',
data: params})
if (res.state == 1) {
let res1 = await this.$http.post(`/api/semi/semiOrder/updateLogistic`, null, {params: {
orderId: this.orderDataList[i].orderId,
logisticId: res.data[0].shipping_method_no,
expressCompany: res.data[0].shipping_method,
expressId: res.data[0].carrier_name
}})
if (res1.code != 0) {
Message.error(`${this.orderDataList[i].orderId}】订单取号失败`)
}
}
await this.$sleepSync(200)
}
this.getOrderList()
},
async writeBack() {
for (let i = 0; i < this.orderDataList.length; i++) {
let res = await sendTemuSellerAgentMessage({
url: 'mms/orchid/address/snapshot/order_shipping_address_query',
needMallId: true,
mallId: obj[0].mallId,
data: {
fulfillmentMode: 0,
pageNumber: 1,
pageSize: 20,
queryType: 2,
sortType: 1,
parentOrderSnList: [
this.orderDataList[i].orderId
],
timeZone: "UTC+8",
parentAfterSalesTag: 0,
needBuySignService: 0,
sellerNoteLabelList: []
}})
if (res.errorCode == 0) {
}
}
}
}
}
</script>
<style scoped lang="scss">
.list {
.title-right {
display: flex;
align-items: center;
& > div:first-child {
margin-right: 20px;
}
}
::v-deep.ai-list {
.ai-list__content--right-wrapper {
background: transparent;
box-shadow: none;
padding: 0!important;
}
}
}
.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>