This commit is contained in:
liushiwei
2024-09-19 21:28:59 +08:00
parent 5e8b1ea682
commit 4a90536696
26 changed files with 1604 additions and 472 deletions

View File

@@ -84,9 +84,9 @@ function init() {
}
}
/*let models2 = document.querySelectorAll('div[class^="price-adjust-confirm-system_contentWrp"]')
let models2 = document.querySelectorAll('div[class^="modal-content_platBanner"]')
for (let i = 0; i < models2.length; i++) {
let tipsObj = models2[i].querySelector('div[class^="price-adjust-confirm-system_tips"]')
let tipsObj = models2[i].parentElement.querySelector('div[class^="modal-content_content"]')
let spanObj = tipsObj.querySelector('div span:last-child')
if (spanObj) {
const popup = document.createElement("div")
@@ -105,12 +105,12 @@ function init() {
spanObj.appendChild(popup)
popup.addEventListener('click', async () => {
let tbodyObj = models2[i].querySelector('tbody')
let tbodyObj = models2[i].parentElement.querySelector('tbody')
let trList = tbodyObj.querySelectorAll('tr')
for (let i = 0; i < trList.length; i++) {
let tdObj = trList[i].querySelector('td:last-child')
let firstLabelObj = tdObj.querySelector('div label:first-child')
if (firstLabelObj.getAttribute("data-checked")) {
if (firstLabelObj && firstLabelObj.getAttribute("data-checked")) {
let labelObj = tdObj.querySelector('div label:nth-child(2)')
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
// await sleepSync(50)
@@ -122,7 +122,45 @@ function init() {
}
}
let models3 = document.querySelectorAll('div[class^="price-adjust-confirm-new_content"]')
let models3 = document.querySelectorAll('div[class^="modal-content_content"]')
for (let i = 0; i < models2.length; i++) {
let tipsObj = models2[i].parentElement.querySelector('div[class^="modal-content_content"]')
let spanObj = tipsObj.querySelector('div span:last-child')
if (spanObj) {
const popup = document.createElement("div")
popup.innerText = "拒绝调价"
const styles = {
padding: "8px",
background: "#fb7701",
color: "#fff",
display: 'inline',
borderRadius: "8px",
cursor: "pointer"
}
for (const e in styles) {
popup.style[e] = styles[e]
}
spanObj.appendChild(popup)
popup.addEventListener('click', async () => {
let tbodyObj = models2[i].parentElement.querySelector('tbody')
let trList = tbodyObj.querySelectorAll('tr')
for (let i = 0; i < trList.length; i++) {
let tdObj = trList[i].querySelector('td:last-child')
let firstLabelObj = tdObj.querySelector('div label:first-child')
if (firstLabelObj && firstLabelObj.getAttribute("data-checked")) {
let labelObj = tdObj.querySelector('div label:nth-child(2)')
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
// await sleepSync(50)
radioObj.click()
}
}
})
flag = true
}
}
/*let models3 = document.querySelectorAll('div[class^="price-adjust-confirm-new_content"]')
for (let i = 0; i < models3.length; i++) {
let tipsObj = models3[i].querySelector('div[class^="price-adjust-confirm-new_tips"]')
let spanObj = tipsObj.querySelector('div span:last-child')

24
public/rules_11.json Normal file
View File

@@ -0,0 +1,24 @@
[
{
"id": 22,
"priority": 1,
"action": {
"type": "modifyHeaders",
"requestHeaders": [
{
"header": "Origin",
"operation": "set",
"value": "https://sellerhub.shein.com/"
},
{
"header": "Referer",
"operation": "set",
"value": "https://sellerhub.shein.com/"
}
]
},
"condition": {
"urlFilter": "||sellerhub.shein.com"
}
}
]

View File

@@ -4,7 +4,7 @@ import store from '@/store'
var instance = axios.create({
baseURL: process.env.NODE_ENV === 'production' ? 'http://temu.jjcp52.com' : 'http://temu.jjcp52.com',
baseURL: process.env.NODE_ENV === 'production' ? 'http://124.71.2.127:8888' : 'http://124.71.2.127:8888',
timeout: 50000,
validateStatus: function (status) {
return status < 500

View File

@@ -9,10 +9,19 @@
<el-form-item v-if="!isMultiCopy" label="商品地址:" style="width: 100%;" prop="url" :rules="[{ required: true, message: '请输入商品地址', trigger: 'blur' }]">
<el-input type="textarea" :rows="5" v-model="form.url"></el-input>
</el-form-item>
<el-form-item
prop="isSemi"
label="是否半托管:"
:rules="[{ required: true, message: '请选择是否半托管', trigger: 'blur' }]">
<el-radio-group v-model="form.isSemi" size="medium">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="店铺:" style="width: 100%;" prop="targetMallId" :rules="[{ required: true, message: '请选择店铺', trigger: 'blur' }]">
<el-select style="width: 380px" v-model="form.targetMallId" @change="onMallChange" placeholder="请选择">
<el-select style="width: 380px" multiple v-model="form.targetMallId" placeholder="请选择">
<el-option
v-for="item in $store.state.mallList"
v-for="item in mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
@@ -136,6 +145,15 @@ export default {
siteList: []
}
},
computed: {
mallList () {
const filteredData = this.$store.state.mallList.filter(item => {
return item.isSemiManagedMall == this.form.isSemi
})
return filteredData
}
},
created () {
this.getSiteList()
if (this.params?.url) {
@@ -143,21 +161,6 @@ export default {
}
},
methods: {
onMallChange() {
if (!this.form.targetMallId) {
Message.error("请先选择店铺")
return
}
let tempMall = this.$store.state.mallList.filter(item => {
return item.mallId == this.form.targetMallId
})
if (null == tempMall || tempMall.length == 0) {
Message.error("请先选择店铺")
return
} else {
this.form.isSemi = tempMall[0].isSemiManagedMall
}
},
getSiteList() {
sendChromeAPIMessage({
url: 'bg-visage-mms/config/common/site/query',
@@ -250,7 +253,7 @@ export default {
})
})
Promise.all(specIds.map(item => this.getSpecIdNew(item).then(res => {
/*Promise.all(specIds.map(item => this.getSpecIdNew(item).then(res => {
this.sku.forEach(item1 => {
item1.specs.forEach(item2 => {
if (item2.spec_value == item.spec_value) {
@@ -265,7 +268,8 @@ export default {
this.createDraft(res.data)
}
})
})
})*/
this.toCreateDraftNew(specIds)
})
},
async addToDraft() {
@@ -319,7 +323,7 @@ export default {
})
})
Promise.all(specIds.map(item => this.getSpecId(item).then(res => {
/*Promise.all(specIds.map(item => this.getSpecId(item).then(res => {
this.sku.forEach(item1 => {
item1.specs.forEach(item2 => {
if (item2.specValue == item.specValue) {
@@ -334,9 +338,9 @@ export default {
this.createDraft(res.data)
}
})
})
})*/
this.toCreateDraft(specIds)
} else if (this.form.type == '2') {
console.log(1)
}
})
} else {
@@ -344,7 +348,45 @@ export default {
}
})
},
async createDraft(data) {
async toCreateDraft(specIds) {
for (let kk = 0; kk < this.form.targetMallId.length; kk++) {
await Promise.all(specIds.map(item => this.getSpecId(item, this.form.targetMallId[kk]).then(res => {
this.sku.forEach(item1 => {
item1.specs.forEach(item2 => {
if (item2.specValue == item.specValue) {
item2.specValueId = res.result.specId
}
})
})
return 0
})))
let res = await this.$http.post('/api/copyProduct/translate',{type: 1, goods: this.goods, sku: this.sku, productDetail: this.productDetail})
if (res.code == 0) {
await this.createDraft(res.data, this.form.targetMallId[kk])
}
await this.$sleepSync(500)
}
},
async toCreateDraftNew(specIds) {
for (let kk = 0; kk < this.form.targetMallId.length; kk++) {
await Promise.all(specIds.map(item => this.getSpecIdNew(item, this.form.targetMallId[kk]).then(res => {
this.sku.forEach(item1 => {
item1.specs.forEach(item2 => {
if (item2.spec_value == item.spec_value) {
item2.spec_value_id = res.result.specId
}
})
})
return 0
})))
let res = await this.$http.post('/api/copyProduct/translateNew',{type: 1, goods: this.goods, sku: this.sku, productDetail: this.productDetail})
if (res.code == 0) {
await this.createDraft(res.data, this.form.targetMallId[kk])
}
await this.$sleepSync(500)
}
},
async createDraft(data, mallId) {
let reqData = {}
let catId = null;
if (this.form.isSameCategory) {
@@ -360,7 +402,7 @@ export default {
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/add',
needMallId: true,
mallId: this.form.targetMallId,
mallId: mallId,
data: reqData})
if (res.errorCode == 1000000) {
@@ -384,7 +426,7 @@ export default {
let res3 = await sendChromeAPIMessage({
url: 'bg-anniston-mms/category/template/query',
needMallId: true,
mallId: this.form.targetMallId,
mallId: mallId,
data: {
catId: reqData.catId,
productCreateTime: null,
@@ -436,50 +478,44 @@ export default {
content.personalizationSwitch = 0
content.productDraftId = draftId
this.createProduct(content)
} else {
setTimeout(() => {
this.createDraft(data)
}, 500)
await this.createProduct(content, mallId)
}
},
createProduct(content) {
async createProduct(content, mallId) {
if (this.form.isSemi) {
content.productSemiManagedReq = {
bindSiteIds: this.form.siteId
}
}
sendChromeAPIMessage({
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/save',
needMallId: true,
mallId: this.form.targetMallId,
mallId: mallId,
data: {
...content
}}).then((res) => {
if (res.errorCode == 1000000) {
this.successList.push(this.currentUrl)
this.saveInfo()
if (this.isMultiCopy) {
this.currentIndex ++
if (this.currentIndex == this.params.urlList.length) {
this.isCopying = false
this.$emit('onSuccess')
MessageBox.alert(`成功添加${this.successList.length}个商品进入草稿箱`)
} else {
this.currentUrl = this.params.urlList[this.currentIndex]
this.execAddToDraft()
}
} else {
}})
if (res.errorCode == 1000000) {
this.successList.push(this.currentUrl)
this.saveInfo(mallId)
if (this.isMultiCopy) {
this.currentIndex ++
if (this.currentIndex == this.params.urlList.length) {
this.isCopying = false
Message.success("成功添加到草稿箱")
this.$emit('onSuccess')
MessageBox.alert(`成功添加${this.successList.length}个商品进入草稿箱`)
} else {
this.currentUrl = this.params.urlList[this.currentIndex]
this.execAddToDraft()
}
} else {
setTimeout(() => {
this.createProduct(content)
}, 500)
this.isCopying = false
Message.success("成功添加到草稿箱")
}
})
} else {
await this.$sleepSync(1000)
this.createProduct(content)
}
},
getSpecIdNew(data) {
return sendChromeAPIMessage({
@@ -497,11 +533,11 @@ export default {
}
})
},
getSpecId(data) {
getSpecId(data, mallId) {
return sendChromeAPIMessage({
url: 'bg-anniston-mms/sku/spec/byName/queryOrAdd',
needMallId: true,
mallId: this.form.targetMallId,
mallId: mallId,
data: {
parentSpecId: data.specKeyId,
specName: data.specValue
@@ -509,13 +545,13 @@ export default {
if (res.errorCode == 1000000) {
return res
} else {
this.getSpecId(data)
this.getSpecId(data, mallId)
}
})
},
saveInfo() {
saveInfo(mallId) {
let mallInfo = this.$store.state.mallList.filter(item => {
return item.mallId == this.form.targetMallId
return item.mallId == mallId
})
this.$http.post('/api/copyProduct/add', {
mallId: mallInfo[0].mallId,

View File

@@ -69,6 +69,10 @@
"id": "10",
"enabled": true,
"path": "rules_10.json"
},{
"id": "11",
"enabled": true,
"path": "rules_11.json"
}]
},
"content_scripts": [

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "TEMU助手",
"description": "TEMU助手 - 自动化提高生产效率",
"version": "3.2.12",
"version": "3.3.0",
"background": {
"service_worker": "/background.js"
},
@@ -14,7 +14,7 @@
"action": {
},
"host_permissions": [
"*://*.jjcp52.com/",
"*://124.71.2.127:8888/",
"*://*.kuajingmaihuo.com/",
"*://*.temu.com/",
"*://*.aliexpress.com/",
@@ -68,6 +68,10 @@
"id": "9",
"enabled": true,
"path": "rules_9.json"
},{
"id": "11",
"enabled": true,
"path": "rules_11.json"
}]
},
"content_scripts": [

View File

@@ -217,6 +217,11 @@ const router = new VueRouter({
name: 'priceAdjustment',
component: () => import('../view/sale/PriceAdjustment.vue')
},
{
path: 'logisticFee',
name: 'logisticFee',
component: () => import('../view/sale/LogisticFee.vue')
},
{
path: 'costManageShein',
name: 'costManageShein',
@@ -247,6 +252,11 @@ const router = new VueRouter({
name: 'orderListShein',
component: () => import('../view/shein/OrderListShein.vue')
},
{
path: 'productListOdm',
name: 'productListOdm',
component: () => import('../view/shein/ProductListOdm.vue')
},
{
path: 'returnRecordShein',
name: 'returnRecordShein',

View File

@@ -137,6 +137,7 @@
<el-menu-item index="/afterSaleStat">售后统计</el-menu-item>
<el-menu-item index="/afterSaleDeductStat">售后赔付统计</el-menu-item>
<el-menu-item index="/priceAdjustment">调价管理</el-menu-item>
<el-menu-item index="/logisticFee">物流统计</el-menu-item>
</el-submenu>
<el-submenu index="/shein">
<template slot="title">
@@ -148,7 +149,8 @@
<el-menu-item index="/certCenterShein">证书中心</el-menu-item>
<el-menu-item index="/copyProductShein">商品复制</el-menu-item>
<el-menu-item index="/orderListShein">发货订单</el-menu-item>
<el-menu-item index="/returnRecordShein">退货与报废单列表</el-menu-item>
<el-menu-item index="/productListOdm">商品列表(ODM)</el-menu-item>
<el-menu-item v-if="$store.state.userInfo.phone == '18571466720' || $store.state.userInfo.phone == '18666013582'" index="/returnRecordShein">退货与报废单列表</el-menu-item>
<el-menu-item v-if="$store.state.userInfo.phone == '18571466720' || $store.state.userInfo.phone == '17607119772'" index="/labelInfoShein">
标签管理
</el-menu-item>

View File

@@ -227,6 +227,11 @@ import BiVueMindmap from "bi-vue-mindmap";
parentId: "01010104",
title: "售后赔付统计:对应“结算管理”->“对账中心”->“扣款详情”,统计过去一段时间内店铺的扣款总金额/次数,支持导出"
},
{
id: "0101010407",
parentId: "01010104",
title: "物流统计:对应“履约服务账单->明细->缴费记录”,以及“发货单列表->物流计费重核实”,统计一段时期内物流费用,以及货物重量,物流费用分布"
},
{
id: "01010105",
parentId: "010101",

View File

@@ -116,10 +116,19 @@
customFooter
@close="handleClose">
<el-form class="ai-form" :model="form" label-width="160px" ref="form">
<el-form-item
prop="isSemi"
label="是否半托管:"
:rules="[{ required: true, message: '请选择是否半托管', trigger: 'blur' }]">
<el-radio-group v-model="form.isSemi" size="medium">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="店铺" style="width: 100%;" prop="targetMallId" :rules="[{ required: true, message: '请选择店铺', trigger: 'blur' }]">
<el-select style="width: 380px" v-model="form.targetMallId" @change="onMallChange" placeholder="请选择">
<el-select multiple style="width: 380px" v-model="form.targetMallId" placeholder="请选择">
<el-option
v-for="item in $store.state.mallList"
v-for="item in mallList"
:key="item.mallId"
:label="item.mallName"
:value="item.mallId">
@@ -264,6 +273,15 @@ import AiLazyCascader from "@/components/AiLazyCascader.vue"
siteList: []
}
},
computed: {
mallList () {
const filteredData = this.$store.state.mallList.filter(item => {
return item.isSemiManagedMall == this.form.isSemi
})
return filteredData
}
},
created () {
this.getList()
@@ -297,21 +315,6 @@ import AiLazyCascader from "@/components/AiLazyCascader.vue"
}
})
},
onMallChange() {
if (!this.form.targetMallId) {
Message.error("请先选择店铺")
return
}
let tempMall = this.$store.state.mallList.filter(item => {
return item.mallId == this.form.targetMallId
})
if (null == tempMall || tempMall.length == 0) {
Message.error("请先选择店铺")
return
} else {
this.form.isSemi = tempMall[0].isSemiManagedMall
}
},
remove () {
if (this.ids.length <= 0) {
alert('请选择要删除的商品');
@@ -522,76 +525,82 @@ import AiLazyCascader from "@/components/AiLazyCascader.vue"
addToDraft() {
this.$refs.form.validate((valid) => {
if (valid) {
this.ids.map((id, index) => {
let product = this.tableData.filter((item) => {
return item.id == id
})
let content = JSON.parse(product[0].content)
let category = null
if (this.form.isSameCategory) {
let i = 1
while(true) {
if (!content['cat'+i+'Id']) {
break
}
i++
}
category = content['cat'+(i-1)+'Id']
} else {
category = this.form.targetCatId[this.form.targetCatId.length - 1]
}
let data = {catId: category}
if (this.form.isSemi) {
data.productSemiManagedReq = {
bindSiteIds: this.form.siteId
}
}
content.personalizationSwitch = content.personalizationSwitch || 0
setTimeout(() => {
sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/add',
needMallId: true,
mallId: this.form.targetMallId,
data: data}).then((res) => {
if (res.errorCode == 1000000) {
let draftId = res.result.productDraftId
if (!this.form.isSameCategory) {
let i = 0
for (; i < this.form.targetCatId.length; i++) {
content['cat' + (i+1) + 'Id'] = this.form.targetCatId[i]
}
for (; i < 10; i++) {
content['cat' + (i+1) + 'Id'] = ''
}
}
content.productDraftId = draftId
if (this.form.isSemi) {
content.productSemiManagedReq = {
bindSiteIds: this.form.siteId
}
}
sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/save',
needMallId: true,
mallId: this.form.targetMallId,
data: {
...content
}}).then((res) => {
if (res.errorCode == 1000000) {
Message.success("商品【" + product[0].productName + "】成功添加到草稿箱")
} else {
Message.error(res.errorMsg)
}
})
} else {
Message.error("【拼多多】" + res.errorMsg)
}
})
}, 1000*index)
})
this.beginAddToDraft()
this.mallDlgShow = false
}
})
},
async beginAddToDraft() {
for (let xx = 0 ; xx < this.ids.length; xx++) {
let id = this.ids[xx]
let product = this.tableData.filter((item) => {
return item.id == id
})
let content = JSON.parse(product[0].content)
let category = null
if (this.form.isSameCategory) {
let i = 1
while(true) {
if (!content['cat'+i+'Id']) {
break
}
i++
}
category = content['cat'+(i-1)+'Id']
} else {
category = this.form.targetCatId[this.form.targetCatId.length - 1]
}
let data = {catId: category}
if (this.form.isSemi) {
data.productSemiManagedReq = {
bindSiteIds: this.form.siteId
}
}
content.personalizationSwitch = content.personalizationSwitch || 0
for (let kk = 0; kk < this.form.targetMallId.length; kk++) {
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/add',
needMallId: true,
mallId: this.form.targetMallId[kk],
data: data})
if (res.errorCode == 1000000) {
let draftId = res.result.productDraftId
if (!this.form.isSameCategory) {
let i = 0
for (; i < this.form.targetCatId.length; i++) {
content['cat' + (i+1) + 'Id'] = this.form.targetCatId[i]
}
for (; i < 10; i++) {
content['cat' + (i+1) + 'Id'] = ''
}
}
content.productDraftId = draftId
if (this.form.isSemi) {
content.productSemiManagedReq = {
bindSiteIds: this.form.siteId
}
}
let res1 = await sendChromeAPIMessage({
url: 'bg-visage-mms/product/draft/save',
needMallId: true,
mallId: this.form.targetMallId[kk],
data: {
...content
}})
if (res1.errorCode == 1000000) {
Message.success("商品【" + product[0].productName + "】成功添加到草稿箱")
} else {
Message.error(res1.errorMsg)
}
} else {
Message.error("【拼多多】" + res.errorMsg)
}
await this.$sleepSync(500)
}
}
}
}
}

View File

@@ -110,15 +110,7 @@
<div class="search-item" style="width: 160px;">
<el-checkbox v-model="showTodaySale">只显示今日有销量</el-checkbox>
</div>
<json-excel
:data="list"
v-if="type === '0'"
:fields="jsonFields"
:before-generate = "startDownload"
name="销售数据.xls"
worksheet="销售统计">
<el-button type="primary">导出数据</el-button>
</json-excel>
<el-button style="margin-right: 10px;" v-if="type === '0'" type="primary" @click="downloadSaleData">导出数据</el-button>
<json-excel
:data="skuSaleNumberList"
v-show="false"
@@ -203,6 +195,8 @@ import {sendChromeAPIMessage} from '@/api/chromeApi'
import JsonExcel from 'vue-json-excel'
import {formatDate} from '@/utils/date'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'ExportSaleData',
@@ -230,65 +224,7 @@ import { Message } from 'element-ui'
startDate: '',
endDate: '',
skuIds: [],
jsonFields: {
"商品名称": "productName",
"SPU": "productId",
"SKC": "productSkcId",
"SKU ID": "productSkuId",
"SKU属性": "className",
"SKU货号": "skuExtCode",
"加入站点时长": "onSalesDurationOffline",
"图片链接": "productSkcPicture",
"申报价格(CNY)": {
"field": "supplierPrice",
callback: (value) => {
return value /100;
}
},
"开款核价状态": {
"field": "isVerifyPrice",
callback: (value) => {
return value ? '核价通过': '核价未通过 / 无法备货';
}
},
"缺货数量": "lackQuantity",
"建议备货量": "adviceQuantity",
"可售天数": "availableSaleDays",
"库存可售天数": "availableSaleDaysFromInventory",
"仓内库存可售天数": "warehouseAvailableSaleDays",
"近7日用户加购数量": "inCartNumber7d",
"用户累计加购数量": "inCardNumber",
"已订阅待提醒到货": "nomsgSubsCntCntSth",
"销售数据 - 今日": "todaySaleVolume",
"销售数据 - 今日销售额": "saleMoney",
"销售数据 - 利润": "profitMoney",
"销售数据 - 利润率": "profitPercent",
"销售数据 - 近7日": "lastSevenDaysSaleVolume",
"销售数据 - 近30天": "lastThirtyDaysSaleVolume",
"库存数据 - 仓内可用库存": "inventoryNumInfo.warehouseInventoryNum",
"库存数据 - 仓内暂不可用库存": "inventoryNumInfo.waitOnShelfNum",
"库存数据 - 已发货库存": "inventoryNumInfo.waitReceiveNum",
"库存数据 - 已下单待发货库存": "inventoryNumInfo.waitDeliveryInventoryNum",
"库存数据 - 待审核备货库存": "inventoryNumInfo.waitApproveInventoryNum",
"VMI备货单数 - 待发货": "vmiOrderInfo.waitDeliveryNum",
"VMI备货单数 - 在途单数": "vmiOrderInfo.transportationNum",
"VMI备货单数 - 发货延迟": "vmiOrderInfo.deliveryDelayNum",
"VMI备货单数 - 到货延迟": "vmiOrderInfo.arrivalDelayNum",
"非VMI备货单数 - 待发货": "notVmiOrderInfo.waitDeliveryNum",
"非VMI备货单数 - 在途单数": "notVmiOrderInfo.transportationNum",
"非VMI备货单数 - 发货延迟": "notVmiOrderInfo.deliveryDelayNum",
"非VMI备货单数 - 到货延迟": "notVmiOrderInfo.arrivalDelayNum",
"备货逻辑": "purchaseConfig",
"可用库存货值(CNY)": "productTotalPrice",
"在途库存货值(CNY)": "inroadTotalPrice",
"店铺名称": "mallName",
"评分": "mark",
"是否热销": 'hotTag',
"生产建议信息 - 建议生产数": 'adviceProduceNum',
"生产建议信息 - 剩余件数": 'availableProduceNum',
"类目": 'category'
},
skuSaleNumberFields: {},
skuSaleNumberList: [],
downloadSkuSaleNumberDlg: false,
@@ -382,6 +318,26 @@ import { Message } from 'element-ui'
return a.todaySaleVolume - b.todaySaleVolume
}
},
{
prop: 'lastSevenDaysSaleVolume',
label: '近7天',
width: '120px',
align: 'center',
sortable: true,
'sort-method': (a, b) => {
return a.lastSevenDaysSaleVolume - b.lastSevenDaysSaleVolume
}
},
{
prop: 'lastThirtyDaysSaleVolume',
label: '近30天',
width: '120px',
align: 'center',
sortable: true,
'sort-method': (a, b) => {
return a.lastThirtyDaysSaleVolume - b.lastThirtyDaysSaleVolume
}
},
{
prop: 'saleMoney',
label: '销售额',
@@ -1032,6 +988,58 @@ import { Message } from 'element-ui'
}
}
return 0
},
async downloadSaleData() {
let res = await this.$http.post('/api/malluser/info')
if (res.code == 0) {
this.$store.commit('setUserInfo', res.data)
if (res.data.flag != 1) {
Message.error('您的账号未激活或已失效,请激活后使用')
this.$store.commit('setActiveDlgShow', true)
return;
}
}
// 假设你有一个表格数据的数组
const data = [
["商品名称", "SPU", "SKC", "SKU ID", "SKU属性", "SKU货号", "加入站点时长", "图片链接", "申报价格(CNY)", "开款核价状态", "缺货数量",
"建议备货量", "可售天数", "库存可售天数", "仓内库存可售天数","近7日用户加购数量", "用户累计加购数量", "已订阅待提醒到货", "销售数据 - 今日",
"销售数据 - 近7天", "销售数据 - 近30天", "销售数据 - 今日销售额", "销售数据 - 利润", "销售数据 - 利润率", "库存数据 - 仓内可用库存",
"库存数据 - 仓内暂不可用库存", "库存数据 - 已发货库存", "库存数据 - 已下单待发货库存", "库存数据 - 待审核备货库存", "VMI备货单数 - 待发货",
"VMI备货单数 - 在途单数", "VMI备货单数 - 发货延迟", "VMI备货单数 - 到货延迟", "非VMI备货单数 - 待发货", "非VMI备货单数 - 在途单数",
"非VMI备货单数 - 发货延迟", "非VMI备货单数 - 到货延迟", "备货逻辑", "可用库存货值(CNY)", "在途库存货值(CNY)", "店铺名称", "评分",
"是否热销", "生产建议信息 - 建议生产数", "生产建议信息 - 剩余件数", "类目"]
]
this.list.map(item => {
data.push([item.productName, item.productId, item.productSkcId, item.productSkuId, item.className, item.skuExtCode, item.onSalesDurationOffline, item.productSkcPicture, item.supplierPrice/ 100, item.isVerifyPrice? '核价通过': '核价未通过 / 无法备货', item.lackQuantity,
item.adviceQuantity, item.availableSaleDays, item.availableSaleDaysFromInventory, item.warehouseAvailableSaleDays, item.inCartNumber7d, item.inCardNumber, item.nomsgSubsCntCntSth, item.todaySaleVolume,
item.lastSevenDaysSaleVolume, item.lastThirtyDaysSaleVolume, item.saleMoney, item.profitMoney, item.profitPercent, item.inventoryNumInfo?.warehouseInventoryNum,
item.inventoryNumInfo?.waitOnShelfNum, item.inventoryNumInfo?.waitReceiveNum, item.inventoryNumInfo?.waitDeliveryInventoryNum, item.inventoryNumInfo?.waitApproveInventoryNum, item.vmiOrderInfo?.waitDeliveryNum,
item.vmiOrderInfo?.transportationNum, item.vmiOrderInfo?.deliveryDelayNum, item.vmiOrderInfo?.arrivalDelayNum, item.notVmiOrderInfo?.waitDeliveryNum, item.notVmiOrderInfo?.transportationNum,
item.notVmiOrderInfo?.deliveryDelayNum, item.notVmiOrderInfo?.arrivalDelayNum, item.purchaseConfig, item.productTotalPrice, item.inroadTotalPrice, item.mallName, item.mark,
item.hotTag, item.adviceProduceNum, item.availableProduceNum, item.category])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '销售数据.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
}
}
}

View File

@@ -0,0 +1,418 @@
<template>
<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">
<div class="content">
<ai-search-bar>
<template #left>
<div class="search-item">
<label>缴费完成时间</label>
<el-date-picker
v-model="searchDate"
type="daterange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间">
</el-date-picker>
</div>
</template>
<template #right>
<el-button type="primary" @click="beforeGetList">加载</el-button>
</template>
</ai-search-bar>
<ai-card title="数据概览" style="padding-bottom: 40px;">
<div>
<el-row :gutter="20">
<el-col :span="6">
<div>
<el-statistic
group-separator=","
:precision="2"
:value="totalLogisticFee"
title="物流总费用"
>
</el-statistic>
</div>
</el-col>
<el-col :span="6">
<div>
<el-statistic
title="备货单总数"
:value="totalOrders"
>
</el-statistic>
</div>
</el-col>
<el-col :span="6">
<div>
<el-statistic
title="发货时填写总重量(KG)"
:value="totalWriteWeight"
>
</el-statistic>
</div>
</el-col>
<el-col :span="6">
<div>
<el-statistic
title="最终计费总重量(KG)"
:value="totalFinalWeight"
>
</el-statistic>
</div>
</el-col>
</el-row>
</div>
</ai-card>
<ai-card title="店铺分布" style="padding-bottom: 40px;">
<ai-table
:isShowPagination="false"
:tableData="tableData"
:col-configs="colConfigs"
:total="tableData.length"
height="500"
style="margin-top: 8px;"
@getList="() => {}">
</ai-table>
</ai-card>
<ai-card title="运费分布" style="padding-bottom: 40px;">
<ai-table
:isShowPagination="false"
:tableData="logisticTableData"
:col-configs="logisticColConfigs"
:total="tableData.length"
height="500"
style="margin-top: 8px;"
@getList="() => {}">
</ai-table>
</ai-card>
</div>
</template>
</ai-list>
</template>
<script>
import { Message } from 'element-ui'
import {sendChromeAPIMessage } from '@/api/chromeApi'
export default {
name: 'LogisticFee',
data () {
return {
searchDate: [],
reqData: {
pageNum: 1,
pageSize: 100
},
totalLogisticFee: 0.0,
totalOrders: 0,
totalWriteWeight: 0.0,
totalFinalWeight: 0.0,
colConfigs: [
{ prop: 'mallName', label: '店铺名称', align: 'left' },
{ prop: 'wayBillCount', label: '备货单数', align: 'left', sortable: true, 'sort-method': (a, b) => a.wayBillCount - b.wayBillCount },
{ prop: 'writeWeight', label: '填写重量(KG)', align: 'left', sortable: true, 'sort-method': (a, b) => a.writeWeight - b.writeWeight },
{ prop: 'weight', label: '实际重量(KG)', align: 'left', sortable: true, 'sort-method': (a, b) => a.weight - b.weight },
{ prop: 'amount', label: '物流费用', align: 'left', sortable: true, 'sort-method': (a, b) => a.amount - b.amount }
],
logisticColConfigs: [
{ prop: 'company', label: '物流公司', align: 'left' },
{ prop: 'writeWeight', label: '填写总重量(KG)', align: 'left', sortable: true, 'sort-method': (a, b) => a.writeWeight - b.writeWeight },
{ prop: 'weight', label: '实际总重量(KG)', align: 'left', sortable: true, 'sort-method': (a, b) => a.weight - b.weight },
{ prop: 'amount', label: '物流费用', align: 'left', sortable: true, 'sort-method': (a, b) => a.amount - b.amount }
],
isLoading: false,
tableData: [],
logisticTableData: [],
transList: [],
mallWayBillList: [],
logisticFeeList: []
}
},
methods: {
beforeGetList() {
this.$userCheck().then(() => {
this.toLoad()
}).catch((err) => {
})
},
async toLoad() {
if (!this.searchDate) {
Message.error("请选择时间范围")
return
}
this.reqData.pageNum = 1
this.tableData = []
this.logisticTableData = []
this.isLoading = true
this.totalLogisticFee = 0.0
this.totalOrders = 0
this.totalWriteWeight = 0.0
this.totalFinalWeight = 0.0
this.transList = []
this.mallWayBillList = []
this.logisticFeeList = []
let startTime = this.searchDate[0].getTime()
let endTime = this.searchDate[1].getTime() + 86400000 - 1
await this.getLogisticFee(startTime, endTime)
this.totalLogisticFee = Math.round(this.totalLogisticFee * 100)/100
this.totalFinalWeight = Math.round(this.totalFinalWeight * 100)/100
this.isLoading = false
},
async getLogisticFee(startTime, endTime) {
let res = await sendChromeAPIMessage({
url: `api/merchant/warehouse/express/pay/bill/list`,
needMallId: true,
mallId: this.$store.state.mallList[0].mallId,
data: {
...this.reqData,
sucTimeStart: startTime,
sucTimeEnd: endTime
}})
if (res.errorCode == 1000000) {
for (let i = 0; i < res.result.list.length; i++) {
let item = res.result.list[i]
this.totalLogisticFee += item.amount
this.transList.push(item.ptransId)
}
if ((this.reqData.pageSize * this.reqData.pageNum) < res.result.total) {
this.reqData.pageNum ++
await this.getLogisticFee(startTime, endTime)
} else {
await this.getLogisticDetail()
await this.getLogisticWeightDetail()
this.calcLogiticData()
}
}
},
async getLogisticDetail() {
for (let i = 0; i < this.transList.length; i++) {
let res = await sendChromeAPIMessage({
url: `api/merchant/warehouse/express/pay/bill/detail/list`,
needMallId: true,
mallId: this.$store.state.mallList[0].mallId,
data: {
chargeType: 0,
pageSize: 100,
pageNum: 1,
ptransId: this.transList[i]
}})
if (res.errorCode == 1000000) {
for (let k = 0; k < res.result.list.length; k++) {
let item = res.result.list[k]
let flag = false
for (let j = 0; j < this.tableData.length; j++) {
if (this.tableData[j].mallId == item.mallId) {
flag = true
this.tableData[j].amount += item.amount
this.tableData[j].wayBillCount += item.wayBillCount
this.tableData[j].amount = Math.round(this.tableData[j].amount * 100)/100
this.totalOrders += item.wayBillCount
break
}
}
if (!flag) {
this.tableData.push({
mallId: item.mallId,
mallName: item.mallName,
amount: item.amount,
wayBillCount: item.wayBillCount,
weight: 0.0,
writeWeight: 0.0
})
this.totalOrders += item.wayBillCount
}
await this.getWayBillList(item.transId, item.mallId)
}
}
}
},
async getWayBillList(transId, mallId) {
let pageNum = 1
let pageSize = 100
while(true) {
let res = await sendChromeAPIMessage({
url: `api/merchant/warehouse/express/bill/detail/list`,
needMallId: true,
mallId: this.$store.state.mallList[0].mallId,
data: {
pageNum: pageNum,
pageSize: pageSize,
billStatus: 2,
mallId: mallId,
transId: transId
}})
if (res.errorCode == 1000000) {
let flag = false
for (let i = 0; i < this.logisticFeeList.length; i++) {
if (this.logisticFeeList[i].mallId == mallId) {
flag = true
for (let j = 0; j < res.result.list.length; j++) {
this.logisticFeeList[i].billList.push({
sn: res.result.list[j].mainWayBillSn,
amount: res.result.list[j].amount,
company: null,
waight: 0.0
})
}
break
}
}
if (!flag) {
let temp = {
mallId: mallId,
billList: []
}
for (let j = 0; j < res.result.list.length; j++) {
temp.billList.push({
sn: res.result.list[j].mainWayBillSn,
amount: res.result.list[j].amount,
company: null,
weight: 0.0,
writeWeight: 0.0
})
}
this.logisticFeeList.push(temp)
}
if (pageNum * pageSize < res.result.total) {
pageNum ++
} else {
break
}
}
}
},
async getLogisticWeightDetail() {
for (let i = 0; i < this.logisticFeeList.length; i++) {
let page = 1
let weight = 0.0
let writeWeight = 0.0
while(true) {
let tempList = []
for (let j = (page-1)*20; j < this.logisticFeeList[i].billList.length; j++) {
tempList.push(this.logisticFeeList[i].billList[j].sn)
if (tempList.length % 20 == 0) {
break
}
}
if (tempList.length == 0) break
let res = await sendChromeAPIMessage({
url: `bgSongbird-api/supplier/delivery/feedback/queryWaitConfirmWeightExpressList`,
needMallId: true,
mallId: this.logisticFeeList[i].mallId,
anti: true,
data: {
pageNo: 1,
pageSize: 20,
platformExpressMainSnList: tempList,
displayStatus: 100
}})
if (res.errorCode == 1000000) {
for (let ii = 0; ii < res.result.list.length; ii++) {
for (let jj = 0; jj < this.logisticFeeList[i].billList.length; jj++) {
if (this.logisticFeeList[i].billList[jj].sn == res.result.list[ii].expressDeliverySn) {
this.logisticFeeList[i].billList[jj].company = res.result.list[ii].expressCompany
this.logisticFeeList[i].billList[jj].weight = res.result.list[ii].realExpressWeight / 1000
this.logisticFeeList[i].billList[jj].writeWeight = res.result.list[ii].predictTotalPackageWeight / 1000
this.totalFinalWeight += res.result.list[ii].realExpressWeight / 1000
this.totalWriteWeight += res.result.list[ii].predictTotalPackageWeight / 1000
writeWeight += res.result.list[ii].predictTotalPackageWeight / 1000
weight += res.result.list[ii].realExpressWeight / 1000
break
}
}
}
page++
}
}
for (let kk = 0; kk < this.tableData.length; kk++) {
if (this.tableData[kk].mallId == this.logisticFeeList[i].mallId) {
this.tableData[kk].weight = Math.round(weight * 100)/100
this.tableData[kk].writeWeight = Math.round(writeWeight * 100)/100
break
}
}
}
},
calcLogiticData() {
for (let i = 0; i < this.logisticFeeList.length; i++) {
for (let j = 0; j < this.logisticFeeList[i].billList.length; j++) {
let flag = false
for (let x = 0; x < this.logisticTableData.length; x++) {
if (this.logisticTableData[x].company == this.logisticFeeList[i].billList[j].company) {
flag = true
this.logisticTableData[x].writeWeight += this.logisticFeeList[i].billList[j].writeWeight
this.logisticTableData[x].weight += this.logisticFeeList[i].billList[j].weight
this.logisticTableData[x].amount += this.logisticFeeList[i].billList[j].amount
break
}
}
if (!flag) {
console.log(this.logisticFeeList[i].mallId, this.logisticFeeList[i].billList[j], this.logisticFeeList[i].billList[j].company)
this.logisticTableData.push({
company: this.logisticFeeList[i].billList[j].company,
writeWeight: this.logisticFeeList[i].billList[j].writeWeight,
weight: this.logisticFeeList[i].billList[j].weight,
amount: this.logisticFeeList[i].billList[j].amount,
weightPercent: 0.0,
amountPercent: 0.0
})
}
}
}
for (let j = 0; j < this.logisticTableData.length; j++) {
this.logisticTableData[j].weight = Math.round(this.logisticTableData[j].weight * 100)/100
this.logisticTableData[j].amount = Math.round(this.logisticTableData[j].amount * 100)/100
this.logisticTableData[j].company = this.logisticTableData[j].company || '退回服务费'
}
}
}
}
</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;
}
}
}
</style>

View File

@@ -189,7 +189,6 @@ import { saveAs } from 'file-saver'
}
this.getUserInfo()
this.isLoading = true
this.getList()
}
})
},
@@ -202,12 +201,13 @@ import { saveAs } from 'file-saver'
})
if (res.code == '0' && res.msg == "OK") {
this.mallId = res.info.merchantCode
this.getList([])
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
async getList () {
async getList (skcList) {
let res = await sendGeiwohuoAPIMessage({
url: `idms/goods-skc/list`,
method: 'POST',
@@ -222,6 +222,8 @@ import { saveAs } from 'file-saver'
let data = {skc: item.skc,
skcCode: item.supplierCode
}
skcList.push(item.skc)
for (let j = 0; j < item.skuList.length; j++) {
let sku = item.skuList[j]
@@ -229,7 +231,7 @@ import { saveAs } from 'file-saver'
data = {...data, sku: sku.skuCode,
skuAttr: sku.attr,
skuCode: sku.supplierSku,
price: sku.price,
price: null,
costPrice: '',
profitPercent: null,
edit: false,
@@ -242,8 +244,9 @@ import { saveAs } from 'file-saver'
if (res.info.list.length == 100 && (res.info.count > 100*this.currentPage)) {
this.currentPage++
await this.sleepSync(200)
await this.getList()
await this.getList(skcList)
} else {
await this.getPriceInfo(skcList)
this.getSkuCostList()
}
} else if (res.code == 100004 || res.code == 20302) {
@@ -251,6 +254,22 @@ import { saveAs } from 'file-saver'
this.$store.commit("setSheinAlertShow", true)
}
},
async getPriceInfo(skcList) {
let res = await sendGeiwohuoAPIMessage({
url: `idms/goods-skc/price`,
method: 'POST',
data: skcList})
if (res.code == '0') {
for (let key in res.info) {
for (let i = 0; i < this.list.length; i++) {
if (key == this.list[i].sku) {
this.list[i].price = res.info[key]
break
}
}
}
}
},
sleepSync(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
},

View File

@@ -217,10 +217,10 @@ import { saveAs } from 'file-saver'
await this.getSkuCostList()
this.isLoading = true
this.getList()
this.getList([])
},
getList () {
sendGeiwohuoAPIMessage({
async getList (skcList) {
let res = await sendGeiwohuoAPIMessage({
url: 'idms/goods-skc/list',
method: 'POST',
data: {
@@ -251,7 +251,7 @@ import { saveAs } from 'file-saver'
"labelFakeIdList": [],
"tspIdList": [],
"sortBy7dSaleCnt": 2
}}).then((res) => {
}})
if (res.code == '0' && res.msg == "OK") {
for(let i = 0;i < res.info.list.length; i++) {
let item = res.info.list[i];
@@ -262,6 +262,8 @@ import { saveAs } from 'file-saver'
data.supplierCode = item.supplierCode
data.skc = item.skc
skcList.push(item.skc)
for(let j = 0;j < item.skuList.length; j++) {
let sku = item.skuList[j]
if (sku.attr == '合计') continue
@@ -278,18 +280,18 @@ import { saveAs } from 'file-saver'
ivtNum: sku.stock,
costPrice: null,
todayProfit: null,
productTotalPrice: Math.round((sku.price * sku.stock)*100)/100,
inroadTotalPrice: Math.round((sku.price * sku.transit)*100)/100}
productTotalPrice: null,
inroadTotalPrice: null}
this.todayTotal += temp.todaySale
this.todayMoney += Math.round((temp.cost * temp.todaySale)*100)/100
this.todayMoney = Math.round(this.todayMoney * 100) / 100
// this.todayMoney += Math.round((temp.cost * temp.todaySale)*100)/100
// this.todayMoney = Math.round(this.todayMoney * 100) / 100
this.inventoryTotal += temp.ivtNum
this.inventoryMoney += Math.round((temp.cost * temp.ivtNum)*100)/100
this.inventoryMoney = Math.round(this.inventoryMoney*100)/100
// this.inventoryMoney += Math.round((temp.cost * temp.ivtNum)*100)/100
// this.inventoryMoney = Math.round(this.inventoryMoney*100)/100
this.inroadTotal += temp.onWayNum
this.inroadTotalMoney += Math.round((temp.cost * temp.onWayNum)*100)/100
this.inroadTotalMoney = Math.round(this.inroadTotalMoney*100)/100
// this.inroadTotalMoney += Math.round((temp.cost * temp.onWayNum)*100)/100
// this.inroadTotalMoney = Math.round(this.inroadTotalMoney*100)/100
this.list.push(temp);
}
@@ -297,12 +299,36 @@ import { saveAs } from 'file-saver'
if (this.pageSize == res.info.list.length) {
this.currentPage ++
setTimeout(() => {
this.getList()
this.getList(skcList)
}, 1500)
} else {
let res1 = await sendGeiwohuoAPIMessage({
url: `idms/goods-skc/price`,
method: 'POST',
data: skcList})
if (res1.code == '0') {
for (let key in res1.info) {
for (let i = 0; i < this.list.length; i++) {
if (key == this.list[i].skuCode) {
this.list[i].cost = res1.info[key]
break
}
}
}
}
for (let i = 0; i < this.list.length; i++) {
this.list[i].productTotalPrice = Math.round((this.list[i].cost * this.list[i].ivtNum)*100)/100
this.list[i].inroadTotalPrice = Math.round((this.list[i].cost * this.list[i].onWayNum)*100)/100
this.todayMoney += Math.round((this.list[i].cost * this.list[i].todaySale)*100)/100
this.todayMoney = Math.round(this.todayMoney * 100) / 100
this.inventoryMoney += Math.round((this.list[i].cost * this.list[i].ivtNum)*100)/100
this.inventoryMoney = Math.round(this.inventoryMoney*100)/100
this.inroadTotalMoney += Math.round((this.list[i].cost * this.list[i].onWayNum)*100)/100
this.inroadTotalMoney = Math.round(this.inroadTotalMoney*100)/100
for (let j = 0; j < this.costList.length; j++) {
if (this.list[i].skuCode == this.costList[j].sku) {
this.list[i].costPrice = this.costList[j].costPrice
this.list[i].todayProfit = Math.round((this.list[i].cost - this.costList[j].costPrice) * this.list[i].todaySale * 100) / 100
break
@@ -323,9 +349,6 @@ import { saveAs } from 'file-saver'
this.getList()
}, 1500)
}
}).catch(() => {
this.isLoading = false
})
},
async getSkuCostList() {
let res = await this.$http.post(`/api/skuCost/listAll`, null, {

View File

@@ -275,7 +275,7 @@ import { saveAs } from 'file-saver'
]
this.tableData.map(item => {
data.push([item.orderNo, item.skc, item.skuCode, item.imgPath, item.supplierCode, item.supplierSku, item.suffixZh, item.price, item.costPrice, item.orderQuantity, item.needQuantity, item.deliveryQuantity, item.certifiedQuantity, item.defectiveQuantity, item.addTime])
data.push([item.orderNo, item.skc, item.skuCode, item.imgPath, item.supplierCode, item.supplierSku, item.suffixZh, item.price, item.costPrice, item.orderQuantity, item.needQuantity, item.deliveryQuantity, item.groundingQuantity, item.defectiveQuantity, item.addTime])
})
// 将数据转换为工作表

View File

@@ -0,0 +1,239 @@
<template>
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
<ai-title
slot="title"
title="商品列表(ODM)"
isShowBottomBorder>
</ai-title>
<template slot="content">
<ai-search-bar>
<template #left>
<div class="search-item">
<label>可售天数小于</label>
<el-input size="small" clearable placeholder="请输入SKC ID" v-model="search.ableSaleDays"></el-input>
</div>
</template>
<template #right>
<!--<el-button type="primary" @click="toLoad">加载</el-button>-->
</template>
</ai-search-bar>
<ai-card title="商品列表" style="padding-bottom: 40px;">
<template #right>
<el-button type="primary" @click="exportToExcel">导出</el-button>
</template>
<ai-table
:isShowPagination="false"
:tableData="filteredData"
:col-configs="colConfigs"
height="600"
style="margin-top: 8px;"
@getList="() => {}">
<el-table-column slot="goodsThumb" width="120px" label="商品图片" fixed="left">
<template slot-scope="scope">
<div>
<el-image :src="scope.row.goodsThumb" style="width: 40px; height: 40px" class="image" :preview-src-list="[scope.row.goodsThumb]" />
</div>
</template>
</el-table-column>
</ai-table>
</ai-card>
</template>
</ai-list>
</template>
<script>
import {sendGeiwohuoAPIMessage} from '@/api/chromeApi'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'ProductListOdm',
data () {
return {
isLoading: false,
list: [],
mallId: '',
colConfigs: [
{ slot: 'goodsThumb', label: '商品图片', align: 'left' },
{ prop: 'skc', label: 'SKC ID', align: 'left' },
{ prop: 'supplierCode', label: 'SKC货号', align: 'left' },
{ prop: 'sku', label: 'SKU ID', align: 'left' },
{ prop: 'suffixZh', label: '属性集', align: 'left' },
{ prop: 'num', label: '建议备货数量', align: 'left', sortable: true, 'sort-method': (a, b) => Number(a.num) - Number(b.num) },
{ prop: 'warningDaysNew', label: '备货预警天数', align: 'left' },
{ prop: 'ableSaleDays', label: '可售天数', align: 'left', sortable: true, 'sort-method': (a, b) => a.ableSaleDays - b.ableSaleDays },
{ prop: 'saleInfoWeek', label: '近7天销量', align: 'left', sortable: true, 'sort-method': (a, b) => a.saleInfoWeek - b.saleInfoWeek },
{ prop: 'saleInfoMonth', label: '本月销量', align: 'left', sortable: true, 'sort-method': (a, b) => a.saleInfoMonth - b.saleInfoMonth },
{ prop: 'saleInfoPreMonth', label: '上月销量', align: 'left', sortable: true, 'sort-method': (a, b) => a.saleInfoPreMonth - b.saleInfoPreMonth }
],
search: {
unSet: false,
skc: '',
sku: '',
skcCode: ''
},
tableData: [],
currentPage: 1,
}
},
computed: {
filteredData() {
const filteredData = this.list.filter(item => {
let flag1 = true
if (this.search.ableSaleDays) {
if ('' == item.ableSaleDays) flag1 = false
else if (Number(item.ableSaleDays) > Number(this.search.ableSaleDays)) {
flag1 = false
}
}
return flag1
})
return filteredData
}
},
mounted () {
this.$http.post('/api/malluser/info').then(res => {
if (res.code == 0) {
this.$store.commit('setUserInfo', res.data)
if (res.data.flag != 1) {
Message.error('您的账号未激活或已失效,请激活后使用')
this.$store.commit('setActiveDlgShow', true)
return;
}
this.getUserInfo()
this.isLoading = true
this.getList()
}
})
},
methods: {
async getUserInfo() {
let res = await sendGeiwohuoAPIMessage({
url: 'sso-prefix/auth/getUser?uuid=' + Date.now(),
method: 'GET'
})
if (res.code == '0' && res.msg == "OK") {
this.mallId = res.info.merchantCode
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
async getList () {
let res = await sendGeiwohuoAPIMessage({
url: `gmpj/goods/goods/list`,
method: 'POST',
data: {
mallStatusList: [
1
],
page: this.currentPage,
perPage: 100
}})
if (res.code == '0') {
for(let i = 0;i < res.info.list.length; i++) {
let item = res.info.list[i];
let data = {
goodsThumb: item.goodsThumb,
skc: item.skc,
supplierCode: item.supplierCode
}
for (let j = 0; j < item.sizes.length; j++) {
let sku = item.sizes[j]
data = {...data,
sku: sku.skuCode,
suffixZh: sku.suffixZh,
ableSaleDays: sku.ableSaleDays,
saleInfoWeek: sku.saleInfoWeek,
saleInfoMonth: sku.saleInfoMonth,
warningDaysNew: item.warningDaysNew,
saleInfoPreMonth: sku.saleInfoPreMonth
}
if (item.warningDaysNew > 0) {
data.num = ((item.warningDaysNew - Number(sku.ableSaleDays)) * (sku.saleInfoWeek / 7)).toFixed(2)
if (data.num < 0) {
data.num = 0
}
}
this.list.push(data)
}
}
if (res.info.list.length == 100 && (res.info.count > 100*this.currentPage)) {
this.currentPage++
await this.sleepSync(200)
await this.getList()
} else {
this.isLoading = false
}
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
sleepSync(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
},
exportToExcel() {
// 假设你有一个表格数据的数组
const data = [
["商品图片", "SKC", "SKC货号", "SKU", "属性集", "建议备货数量", " 备货预警天数", "可售天数", "近7天销量", "本月销量", "上月销量"]
]
this.filteredData.map(item => {
data.push([item.goodsThumb, item.skc, item.supplierCode, item.sku, item.suffixZh, item.num, item.warningDaysNew, item.ableSaleDays, item.saleInfoWeek, item.saleInfoMonth, item.saleInfoPreMonth])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '商品列表.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
}
}
}
</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;
}
}
}
</style>

View File

@@ -177,7 +177,7 @@ import { saveAs } from 'file-saver'
let successList = res1.info.sucessList
for (let i = 0; i < successList.length; i++) {
for (let j = 0; j < params.length; j++) {
if (successList[i].skuCode == params[j].skuCode) {
if ((successList[i].skuCode == params[j].skuCode) && (successList[i].orderNo == params[j].orderNo)) {
successList[i].skc = params[j].skc
successList[i].printNumber = params[j].printNumber
successList[i].subSuffixZh = params[j].subSuffixZh

View File

@@ -223,7 +223,7 @@ import JsonExcel from 'vue-json-excel'
this.form.mallId = ''
})
},
toLoad() {
async toLoad() {
if (!this.form.mallId) {
Message.error("请选择店铺")
return
@@ -232,7 +232,7 @@ import JsonExcel from 'vue-json-excel'
Message.error("请选择时间")
return
}
this.getSkuCostList()
await this.getSkuCostList()
this.reqData.purchaseTimeFrom = this.form.date[0].getTime()
this.reqData.purchaseTimeTo = this.form.date[1].getTime() + 86400 * 1000
this.reqData.pageNo = 1
@@ -241,9 +241,8 @@ import JsonExcel from 'vue-json-excel'
this.sumTableData = []
this.packageNumber = 0
this.currentIndex = 0
this.costList = []
this.isLoading = true
this.load()
await this.load()
},
async load() {
let res = await sendChromeAPIMessage({
@@ -287,7 +286,7 @@ import JsonExcel from 'vue-json-excel'
}
else if (res.result.subOrderForSupplierList.length == 100) {
this.reqData.pageNo ++
this.load()
await this.load()
} else {
this.tableData.map(item => {
for (let i = 0; i < this.costList.length; i++) {
@@ -338,6 +337,9 @@ import JsonExcel from 'vue-json-excel'
})
this.isLoading = false
}
} else {
await this.$sleepSync(500)
await this.load()
}
},
async getSkuCostList() {

View File

@@ -147,6 +147,7 @@ import JsonExcel from 'vue-json-excel'
{ prop: 'extCode', label: 'SKU货号', width: '160px', align: 'left' },
{ prop: 'specName', label: 'SKU属性', width: '100px', align: 'left' },
{ prop: 'supplierPrice', label: '申报价格(CNY)', width: '180px', align: 'left' },
{ prop: 'cost', label: '成本价格(CNY)', width: '180px', align: 'left', sortable: true, 'sort-method': (a, b) => a.cost - b.cost },
{ prop: 'xiadan', label: '送货数量', width: '100px', align: 'left' },
{ prop: 'skuNum', label: '入库数量', width: '100px', align: 'left' },
{ prop: 'deliveryOrderSn', label: '发货单号', width: '140px', align: 'left' },
@@ -183,6 +184,7 @@ import JsonExcel from 'vue-json-excel'
"SKU货号": "extCode",
"SKU属性": "specName",
"申报价格(CNY)": "supplierPrice",
"成本价格(CNY)": "cost",
"下单数量": "xiadan",
"实际入库数量": "skuNum",
"发货单号": "deliveryOrderSn",
@@ -218,7 +220,7 @@ import JsonExcel from 'vue-json-excel'
this.form.mallId = ''
})
},
toLoad() {
async toLoad() {
if (!this.form.mallId) {
Message.error("请选择店铺")
return
@@ -227,103 +229,113 @@ import JsonExcel from 'vue-json-excel'
Message.error("请选择时间")
return
}
this.getSkuCostList()
await this.getSkuCostList()
this.reqData.purchaseTimeFrom = this.form.date[0].getTime()
this.reqData.purchaseTimeTo = this.form.date[1].getTime() + 86400 * 1000
this.reqData.pageNo = 1
this.reqData.statusList = this.form.status
this.tableData = []
this.costList = []
this.sumTableData = []
this.packageNumber = 0
this.currentIndex = 0
this.isLoading = true
this.load()
await this.load()
},
load() {
sendChromeAPIMessage({
async load() {
let res = await sendChromeAPIMessage({
url: 'oms/bg/venom/api/supplier/purchase/manager/querySubOrderList',
needMallId: true,
mallId: this.form.mallId,
anti: true,
data: this.reqData}).then((res) => {
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.subOrderForSupplierList.length; i++) {
let item = res.result.subOrderForSupplierList[i];
let data = {};
data.purchaseTime = timestampToTime(item.purchaseTime)
data.subPurchaseOrderSn = item.subPurchaseOrderSn
data.productName = item.productName
data.productSkcPicture = item.productSkcPicture
data.productSkcId = item.productSkcId
data.skcExtCode = item.productSn
data.status = this.options.filter(i => {return i.value == item.status})[0].label
data.deliveryOrderSn = item.deliverInfo.deliveryOrderSn
data.deliverTime = timestampToTime(item.deliverInfo.deliverTime)
data.receiveTime = timestampToTime(item.deliverInfo.receiveTime)
for(let k = 0; k < item.skuQuantityDetailList.length; k++) {
data = {...data,
productSkuId: item.skuQuantityDetailList[k].productSkuId,
specName: item.skuQuantityDetailList[k].className,
extCode: item.skuQuantityDetailList[k].extCode,
supplierPrice: item.skuQuantityDetailList[k].supplierPrice / 100,
xiadan: item.skuQuantityDetailList[k].deliverQuantity,
skuNum: item.skuQuantityDetailList[k].realReceiveAuthenticQuantity}
data: this.reqData})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.subOrderForSupplierList.length; i++) {
let item = res.result.subOrderForSupplierList[i];
let data = {};
data.purchaseTime = timestampToTime(item.purchaseTime)
data.subPurchaseOrderSn = item.subPurchaseOrderSn
data.productName = item.productName
data.productSkcPicture = item.productSkcPicture
data.productSkcId = item.productSkcId
data.skcExtCode = item.productSn
data.status = this.options.filter(i => {return i.value == item.status})[0].label
data.deliveryOrderSn = item.deliverInfo.deliveryOrderSn
data.deliverTime = timestampToTime(item.deliverInfo.deliverTime)
data.receiveTime = timestampToTime(item.deliverInfo.receiveTime)
for(let k = 0; k < item.skuQuantityDetailList.length; k++) {
data = {...data,
productSkuId: item.skuQuantityDetailList[k].productSkuId,
specName: item.skuQuantityDetailList[k].className,
extCode: item.skuQuantityDetailList[k].extCode,
supplierPrice: item.skuQuantityDetailList[k].supplierPrice / 100,
xiadan: item.skuQuantityDetailList[k].deliverQuantity,
skuNum: item.skuQuantityDetailList[k].realReceiveAuthenticQuantity,
cost: null}
this.tableData.push(data)
}
}
if (this.reqData.pageNo == 1 && res.result.subOrderForSupplierList.length == 0) {
this.isLoading = false
}
else if (res.result.subOrderForSupplierList.length == 100) {
this.reqData.pageNo ++
this.load()
} else {
this.tableData.map(item => {
let flag = false
for (let i = 0; i < this.sumTableData.length; i++) {
if (this.sumTableData[i].productSkuId == item.productSkuId) {
this.sumTableData[i].xiadan += item.xiadan
this.sumTableData[i].purchaseQuantity += item.purchaseQuantity
this.sumTableData[i].skuNum += item.skuNum
flag = true
break
}
}
if (!flag) {
this.sumTableData.push({
productName: item.productName,
productSkcPicture: item.productSkcPicture,
productSkcId: item.productSkcId,
productSkuId: item.productSkuId,
xiadan: item.xiadan,
skuNum: item.skuNum,
skcExtCode: item.skcExtCode,
extCode: item.extCode,
supplierPrice: item.supplierPrice,
specName: item.specName,
cost: null,
costAmount: null,
profit: null
})
}
})
this.sumTableData.map(item => {
for (let i = 0; i < this.costList.length; i++) {
if (this.costList[i].sku == item.productSkuId) {
item.cost = this.costList[i].costPrice
item.costAmount = Math.round(this.costList[i].costPrice * item.skuNum * 100) / 100
item.profit = Math.round((item.supplierPrice - item.cost) * item.skuNum * 100) / 100
break
}
}
})
this.isLoading = false
}
this.tableData.push(data)
}
})
}
if (this.reqData.pageNo == 1 && res.result.subOrderForSupplierList.length == 0) {
this.isLoading = false
}
else if (res.result.subOrderForSupplierList.length == 100) {
this.reqData.pageNo ++
await this.load()
} else {
this.tableData.map(item => {
for (let i = 0; i < this.costList.length; i++) {
if (this.costList[i].sku == item.productSkuId) {
item.cost = this.costList[i].costPrice
break
}
}
let flag = false
for (let i = 0; i < this.sumTableData.length; i++) {
if (this.sumTableData[i].productSkuId == item.productSkuId) {
this.sumTableData[i].xiadan += item.xiadan
this.sumTableData[i].purchaseQuantity += item.purchaseQuantity
this.sumTableData[i].skuNum += item.skuNum
flag = true
break
}
}
if (!flag) {
this.sumTableData.push({
productName: item.productName,
productSkcPicture: item.productSkcPicture,
productSkcId: item.productSkcId,
productSkuId: item.productSkuId,
xiadan: item.xiadan,
skuNum: item.skuNum,
skcExtCode: item.skcExtCode,
extCode: item.extCode,
supplierPrice: item.supplierPrice,
specName: item.specName,
cost: null,
costAmount: null,
profit: null
})
}
})
this.sumTableData.map(item => {
for (let i = 0; i < this.costList.length; i++) {
if (this.costList[i].sku == item.productSkuId) {
item.cost = this.costList[i].costPrice
item.costAmount = Math.round(this.costList[i].costPrice * item.skuNum * 100) / 100
item.profit = Math.round((item.supplierPrice - item.cost) * item.skuNum * 100) / 100
break
}
}
})
this.isLoading = false
}
} else {
await this.$sleepSync(500)
await this.load()
}
},
async getSkuCostList() {
let res = await this.$http.post(`/api/skuCost/listAll`, null, {

View File

@@ -286,6 +286,17 @@
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
<el-tooltip class="item" effect="dark" content="非服饰类且非定制品,请选择“否”" placement="top">
<el-form-item
prop="isCombinPackage"
label="是否合并包裹:"
:rules="[{ required: true, message: '请选择是否合并包裹', trigger: 'blur' }]">
<el-radio-group :disabled="!robForm.isCreateDeliveryBill" v-model="robForm.isCombinPackage" size="medium">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
</el-tooltip>
</el-form>
<span slot="footer" class="dialog-footer">
@@ -366,7 +377,8 @@
step: "500",
randomValue: 500,
isCreateDeliveryBill: false,
isModifyMaxNum: false
isModifyMaxNum: false,
isCombinPackage: false
},
loadMallIndex: 0,
loadMode: 0, // 加载模式0表示单个店铺加载1表示一键加载
@@ -666,7 +678,7 @@
data: {
"subPurchaseOrderSn": sn
}}).then((res) => {
if (res.errorCode == 1000000 && res.result.isSuccess) {
if (res?.errorCode == 1000000 && res?.result.isSuccess) {
for (let j = 0; j < this.choosedList.length; j++) {
if (this.choosedList[j].subPurchaseOrderSn == sn) {
this.successList.push(this.choosedList[j])
@@ -777,23 +789,43 @@
}
})
let packageInfos = []
data.orderDetailVOList.map(item => {
if (!this.robForm.isCombinPackage) {
data.orderDetailVOList.map(item => {
let packageDetailSaveInfos = []
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos})
})
} else {
let packageDetailSaveInfos = []
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
data.orderDetailVOList.map(item => {
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
})
packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos})
})
}
let addressInfo = this.addressList.filter(k => {
return k.mallId == mallId
})

View File

@@ -33,6 +33,10 @@
<label>结束页</label>
<el-input size="small" placeholder="请输入起始页" type="number" v-model="endPage"></el-input>
</div>
<div class="search-item">
<label>SKC</label>
<el-input size="small" placeholder="请输入SKC多个用逗号隔开" v-model="skcs"></el-input>
</div>
</template>
<template #right>
<el-button type="primary" @click="toLoad">加载</el-button>
@@ -40,7 +44,8 @@
</ai-search-bar>
<ai-card title="数据明细" style="padding-bottom: 40px;">
<template #right>
<el-button type="primary" :disabled="tableData.length == 0" @click="exportWaitUploadToExcel">导出</el-button>
<el-button type="primary" :disabled="tableData.length == 0" @click="exportWaitUploadToExcel">导出当前</el-button>
<el-button type="primary" @click="exportAllToExcel">导出所有店铺</el-button>
</template>
<ai-table
:isShowPagination="false"
@@ -69,7 +74,6 @@
<script>
import { Message } from 'element-ui'
import {sendChromeAPIMessage} from '@/api/chromeApi'
import {timestampToTime} from '@/utils/date'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
@@ -83,6 +87,7 @@ import { saveAs } from 'file-saver'
},
startPage: 1,
endPage: 10,
skcs: null,
reqData: {
page: 1,
pageSize: 100
@@ -130,6 +135,9 @@ import { saveAs } from 'file-saver'
Message.error("起始页不能大于结束页")
return
}
if (this.skcs) {
this.reqData.productSkcIdList = this.skcs.split(',')
}
this.$userCheck(this.form.mallId).then(() => {
this.reqData.page = this.startPage
this.tableData = []
@@ -182,6 +190,91 @@ import { saveAs } from 'file-saver'
}
})
},
async exportAllToExcel() {
this.isLoading = true
let list = []
for (let j = 0; j < this.$store.state.mallList.length; j++) {
let page = 1
while(true) {
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/labelcode/pageQuery',
needMallId: true,
mallId: this.$store.state.mallList[j].mallId,
anti: true,
data: {
page: page,
pageSize: 100
}})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.pageItems.length; i++) {
let item = res.result.pageItems[i];
let data = {};
data.productName = item.productName
data.mainImageUrl = item.displayImage
data.productSkcId = item.labelCodeVO.productSkcId
data.productSkuId = item.labelCodeVO.productSkuId
data.labelCode = item.labelCodeVO.labelCode
data.extCode = item.labelCodeVO.skcExtCode
data.skuExtCode = item.labelCodeVO.skuExtCode
data.category = item.leafCat.catName
data.displayImage = item.displayImage
data.mallName = this.$store.state.mallList[j].mallName
let temp = item.productSkcSpecList.map(item2 => {
return item2.specName
})
data.skcSpecName = temp.join(',')
temp = item.productSkuSpecList.map(item2 => {
return item2.specName
})
data.skuSpecName = temp.join(',')
list.push(data)
}
if (res.result.pageItems.length == 100) {
page ++
} else {
break
}
}
await this.$sleepSync(200)
}
}
// 假设你有一个表格数据的数组
const data = [
["商品名称", "分类", "条码编码", "SKC","SKU", "SKC货号", "SKU货号", "主销售属性", "次销售属性", "模板名称", "店铺名称", "图片"]
]
list.map(item => {
data.push([item.productName, item.category, item.labelCode, item.productSkcId, item.productSkuId, item.extCode, item.skuExtCode, item.skcSpecName, item.skuSpecName, "", item.mallName, item.displayImage])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '商品条码列表.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
this.isLoading = false
},
exportWaitUploadToExcel() {
// 假设你有一个表格数据的数组
const data = [

View File

@@ -167,7 +167,17 @@
</el-radio-group>
</el-form-item>
</el-form>
<el-tooltip class="item" effect="dark" content="非服饰类且非定制品,请选择“否”" placement="top">
<el-form-item
prop="isCombinPackage"
label="是否合并包裹:"
:rules="[{ required: true, message: '请选择是否合并包裹', trigger: 'blur' }]">
<el-radio-group :disabled="!robForm.isCreateDeliveryBill" v-model="robForm.isCombinPackage" size="medium">
<el-radio :label="false"></el-radio>
<el-radio :label="true"></el-radio>
</el-radio-group>
</el-form-item>
</el-tooltip>
<span slot="footer" class="dialog-footer">
<el-button @click="createDlgShow = false"> </el-button>
<el-button type="primary" @click="beforeBegin"> </el-button>
@@ -216,7 +226,8 @@
pageSize: 100,
currentPage: 1,
robForm: {
isModifyMaxNum: false
isModifyMaxNum: false,
isCombinPackage: false
},
loadMallIndex: 0,
loadMode: 0, // 加载模式0表示单个店铺加载1表示一键加载
@@ -299,15 +310,12 @@
Message.error("请选择备货单")
return
}
console.log(this.arr)
this.arr.map(item => {
let temp = this.choosedList.filter(i => {
return i.subPurchaseOrderBasicVO?.subPurchaseOrderSn == item.subPurchaseOrderBasicVO.subPurchaseOrderSn
})
console.log(temp)
if (temp.length == 0) {
this.choosedList.push(item)
console.log(this.choosedList)
}
})
Message.success("添加成功,可继续添加")
@@ -423,22 +431,41 @@
}
})
let packageInfos = []
data.orderDetailVOList.map(item => {
if (!this.robForm.isCombinPackage) {
data.orderDetailVOList.map(item => {
let packageDetailSaveInfos = []
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos})
})
} else {
let packageDetailSaveInfos = []
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
data.orderDetailVOList.map(item => {
if (this.robForm.isModifyMaxNum) {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.skuDeliveryQuantityMaxLimit
})
} else {
packageDetailSaveInfos.push({
productSkuId: item.productSkuId,
skuNum: item.productSkuPurchaseQuantity
})
}
})
packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos})
})
}
let addressInfo = this.addressList.filter(k => {
return k.mallId == data.mallId

View File

@@ -124,7 +124,7 @@
</div>
</div>
<div class="order-manage_contentInfo__1Cjd6">
<div>属性集{{ item.color + ' ' + item.size}}</div>
<div>SKU货号{{ item.extCode}}</div>
<div>待发货数{{ item.purchaseQuantity }}</div>
<div>SKU ID {{ item.productSkuId }}</div>
</div>
@@ -231,7 +231,6 @@
})
if (temp.length == 0) {
this.choosedList.push(item)
console.log(this.choosedList)
}
})
Message.success("添加成功,可继续添加")
@@ -266,8 +265,8 @@
}
this.beginCreate()
},
getList (data, mallId, mallName, currentPage) {
sendChromeAPIMessage({
async getList (data, mallId, mallName, currentPage) {
let res = await sendChromeAPIMessage({
url: 'oms/bg/venom/api/supplier/purchase/manager/querySubOrderList',
needMallId: true,
anti: true,
@@ -284,34 +283,34 @@
"firstOrderByParam": "expectLatestDeliverTime",
"firstOrderByDesc": 0
}
}}).then((res) => {
if (res.errorCode == 1000000) {
res.result.subOrderForSupplierList.map((item) => {
data.push({...item, mallId: mallId, mallName: mallName})
})
}})
if (res.errorCode == 1000000) {
res.result.subOrderForSupplierList.map((item) => {
data.push({...item, 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 {
this.isLoading = false
this.isDlgLoading = false
Message.success("所有店铺待创建备货单已加载完成")
}
if (this.pageSize == length) {
currentPage ++
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 {
this.getList(data, mallId, mallName, currentPage)
}
})
} else {
this.getList(data, mallId, mallName, currentPage)
}
},
remove(sn) {
for (let i = 0; i < this.choosedList.length; i++) {

View File

@@ -31,6 +31,7 @@
worksheet="待装箱发货单明细">
<el-button type="primary">导出数据</el-button>
</json-excel>
<!--<el-button type="primary" @click="downloadLabelData">导出带标签数据</el-button>-->
</template>
<ai-table
:isShowPagination="false"
@@ -243,6 +244,76 @@ import { Message } from 'element-ui'
}
}
})
},
async downloadLabelData() {
let skuList = []
this.list.map(item => {
skuList.push(item.productSkuId)
})
let temp = []
for (let x = 0; x < skuList.length; x++) {
temp.push(skuList[x])
if (temp.length == 100) {
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/labelcode/pageQuery',
needMallId: true,
mallId: this.mallId,
anti: true,
data: {
"page": 1,
"pageSize": 100,
"productSkuIdList": temp
}})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.pageItems.length; i++) {
let item = res.result.pageItems[i];
for(let j = 0; j < this.list.length; j++) {
if (this.list[j].productSkuId == item.labelCodeVO.productSkuId) {
this.list[j].labelCode = item.labelCodeVO.labelCode
this.list[j].skuExtCode = item.labelCodeVO.skuExtCode
let temp = item.productSkuSpecList.map(item2 => {
return item2.specName
})
this.list[j].skuSpecName = temp.join(',')
}
}
}
}
temp = []
}
}
// 假设你有一个表格数据的数组
const data = [
["备货单号", "商品名称", "货号", "SKC ID","SKU ID", "商品属性", "发货件数", "物流公司", "物流单号", "发货单号", "收货仓库", "发货时间", "预约取货时间", "条码编码", "SKU货号", "次销售属性"]
]
this.list.map(item => {
data.push([item.subPurchaseOrderSn, item.productName, item.skcExtCode, item.productSkcId, item.productSkuId, item.specName, item.skuNum, item.expressCompany, item.expressDeliverySn, item.deliveryOrderSn, item.subWarehouseName, item.deliverTime,
item.expectPickUpGoodsTime, item.labelCode, item.skuExtCode, item.skuSpecName])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '待收货发货单带标签数据.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
}
}
}

View File

@@ -31,6 +31,7 @@
worksheet="待收货发货单明细">
<el-button type="primary">导出数据</el-button>
</json-excel>
<!--<el-button type="primary" @click="downloadLabelData">导出带标签数据</el-button>-->
</template>
<ai-table
:isShowPagination="false"
@@ -51,6 +52,8 @@ import {sendChromeAPIMessage} from '@/api/chromeApi'
import JsonExcel from 'vue-json-excel'
import {timestampToTime} from '@/utils/date'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'WaitShippingList',
@@ -125,8 +128,8 @@ import { Message } from 'element-ui'
this.isLoading = false
})
},
getList () {
sendChromeAPIMessage({
async getList () {
let res = await sendChromeAPIMessage({
url: 'bgSongbird-api/supplier/deliverGoods/management/pageQueryDeliveryBatch',
needMallId: true,
mallId: this.mallId,
@@ -134,90 +137,80 @@ import { Message } from 'element-ui'
"pageNo": this.currentPage,
"pageSize": 100,
"status": 1
}}).then((res) => {
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.list.length; i++) {
let item = res.result.list[i];
let data = {};
data.expressCompany = item.expressCompany
data.expressDeliverySn = item.expressDeliverySn
data.subWarehouseName = item.subWarehouseName
data.expectPickUpGoodsTime = timestampToTime(item.expectPickUpGoodsTime)
}})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.list.length; i++) {
let item = res.result.list[i];
let data = {};
data.expressCompany = item.expressCompany
data.expressDeliverySn = item.expressDeliverySn
data.subWarehouseName = item.subWarehouseName
data.expectPickUpGoodsTime = timestampToTime(item.expectPickUpGoodsTime)
for(let j = 0;j < item.deliveryOrderList.length; j++) {
let item1 = item.deliveryOrderList[j]
data = {...data,
subPurchaseOrderSn: item1.subPurchaseOrderSn,
deliveryOrderSn: item1.deliveryOrderSn,
productName: item1.subPurchaseOrderBasicVO.productName,
skcExtCode: item1.subPurchaseOrderBasicVO.skcExtCode,
deliverTime: timestampToTime(item1.deliverTime),
productSkcId: item1.productSkcId}
for(let j = 0;j < item.deliveryOrderList.length; j++) {
let item1 = item.deliveryOrderList[j]
data = {...data,
subPurchaseOrderSn: item1.subPurchaseOrderSn,
deliveryOrderSn: item1.deliveryOrderSn,
productName: item1.subPurchaseOrderBasicVO.productName,
skcExtCode: item1.subPurchaseOrderBasicVO.skcExtCode,
deliverTime: timestampToTime(item1.deliverTime),
productSkcId: item1.productSkcId}
for(let k = 0; k < item1.packageDetailList.length; k++) {
data = {...data,
productSkuId: item1.packageDetailList[k].productSkuId,
specName: '',
skuNum: item1.packageDetailList[k].skuNum}
for(let k = 0; k < item1.packageDetailList.length; k++) {
data = {...data,
productSkuId: item1.packageDetailList[k].productSkuId,
specName: '',
skuNum: item1.packageDetailList[k].skuNum}
this.list.push(data)
}
this.packageNumber = this.packageNumber + item.receivePackageNum
setTimeout(() => {
this.getSkuDetailList(item1.deliveryOrderSn)
}, 200 * i)
this.list.push(data)
}
// this.packageNumber = this.packageNumber + item.receivePackageNum
await this.getSkuDetailList(item1.deliveryOrderSn)
}
if (100 == res.result.list.length) {
this.currentPage ++
setTimeout(() => {
this.getList()
}, 1500)
} else {
this.isLoading = false
}
} else {
setTimeout(() => {
this.getList()
}, 1500)
// Message.error("【拼多多】" + res.errorMsg + ", 请重新尝试加载")
}
}).catch(() => {
this.isLoading = false
})
if (100 == res.result.list.length) {
this.currentPage ++
await this.$sleepSync(1000)
await this.getList()
} else {
this.isLoading = false
}
} else {
await this.$sleepSync(200)
await this.getList()
// Message.error("【拼多多】" + res.errorMsg + ", 请重新尝试加载")
}
},
getSkuDetailList(sn) {
sendChromeAPIMessage({
async getSkuDetailList(sn) {
let res = await sendChromeAPIMessage({
url: 'bgSongbird-api/supplier/deliverGoods/management/queryDeliveryOrderPackageDetailInfo',
needMallId: true,
mallId: this.mallId,
anti: true,
data: {deliveryOrderSn: sn}}).then((res) => {
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.deliveryOrderDetails.length; i++) {
let item = res.result.deliveryOrderDetails[i]
data: {deliveryOrderSn: sn}})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.deliveryOrderDetails.length; i++) {
let item = res.result.deliveryOrderDetails[i]
let specArr = item.secondarySpecVOList.map(item => {
return item.specName
})
let spec = specArr.join(',')
let specArr = item.secondarySpecVOList.map(item => {
return item.specName
})
let spec = specArr.join(',')
for(let j = 0; j < this.list.length; j++) {
if (this.list[j].productSkuId == item.productSkuId) {
this.list[j].specName = spec
}
for(let j = 0; j < this.list.length; j++) {
if (this.list[j].productSkuId == item.productSkuId) {
this.list[j].specName = spec
}
}
this.packageNumber = this.packageNumber - res.result.deliveryOrderDetails.length
if (this.packageNumber < 5) this.isLoading = false
} else {
setTimeout(() => {
this.getSkuDetailList(sn)
}, 200)
}
})
// this.packageNumber = this.packageNumber - res.result.deliveryOrderDetails.length
// if (this.packageNumber < 5) this.isLoading = false
} else {
await this.getSkuDetailList(sn)
}
},
startDownload() {
this.$http.post('/api/malluser/info').then(res => {
@@ -230,6 +223,75 @@ import { Message } from 'element-ui'
}
}
})
},
async downloadLabelData() {
let skuList = []
this.list.map(item => {
skuList.push(item.productSkuId)
})
let temp = []
for (let x = 0; x < skuList.length; x++) {
temp.push(skuList[x])
if (temp.length == 100) {
let res = await sendChromeAPIMessage({
url: 'bg-visage-mms/labelcode/pageQuery',
needMallId: true,
mallId: this.mallId,
anti: true,
data: {
"page": 1,
"pageSize": 100,
"productSkuIdList": temp
}})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.pageItems.length; i++) {
let item = res.result.pageItems[i];
for(let j = 0; j < this.list.length; j++) {
if (this.list[j].productSkuId == item.labelCodeVO.productSkuId) {
this.list[j].labelCode = item.labelCodeVO.labelCode
this.list[j].skuExtCode = item.labelCodeVO.skuExtCode
let temp = item.productSkuSpecList.map(item2 => {
return item2.specName
})
this.list[j].skuSpecName = temp.join(',')
}
}
}
}
temp = []
}
}
// 假设你有一个表格数据的数组
const data = [
["备货单号", "商品名称", "货号", "SKC ID","SKU ID", "商品属性", "发货件数", "物流公司", "物流单号", "发货单号", "收货仓库", "发货时间", "预约取货时间", "条码编码", "SKU货号", "次销售属性"]
]
this.list.map(item => {
data.push([item.subPurchaseOrderSn, item.productName, item.skcExtCode, item.productSkcId, item.productSkuId, item.specName, item.skuNum, item.expressCompany, item.expressDeliverySn, item.deliveryOrderSn, item.subWarehouseName, item.deliverTime,
item.expectPickUpGoodsTime, item.labelCode, item.skuExtCode, item.skuSpecName])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '待收货发货单带标签数据.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
}
}
}

View File

@@ -84,14 +84,12 @@ import { Message } from 'element-ui'
{ prop: 'contactName', label: '退货子仓联系人',width: '160px', align: 'left' },
{ prop: 'contactPhone', label: '手机号', width: '160px',align: 'left' },
{ prop: 'packageStatusDesc', label: '状态',width: '100px', },
{ prop: 'returnSupplierReasonDesc', label: '退货原因', width: '120px'},
{ prop: 'reason', label: '退货原因备注', width: '120px'},
{ prop: 'returnSupplierQuantity', label: '退货数量(件)', width: '120px'},
{ prop: 'returnHandOverTypeDesc', label: '退货方式', width: '100px'},
{ prop: 'payMethodDesc', label: '快递支付方式', width: '120px'},
{ prop: 'logisticsTypeDesc', label: '物流商', width: '100px'},
{ prop: 'packageFinishTime', label: '打包完成时间', width: '160px'},
{ prop: 'latestSelfTakeTime', label: '最晚自提时间', width: '160px'},
{ prop: 'latestSelfTakeTime', label: '最晚可创建自提时间', width: '160px'},
{ prop: 'outboundTime', label: '出库时间', width: '160px'}
],
jsonFields: {
@@ -102,14 +100,12 @@ import { Message } from 'element-ui'
"退货子仓联系人": "contactName",
"手机号": "contactPhone",
"状态": "packageStatusDesc",
"退货原因": "returnSupplierReasonDesc",
"退货原因备注": "reason",
"退货数量(件)": "returnSupplierQuantity",
"退货方式": "returnHandOverTypeDesc",
"快递支付方式": "payMethodDesc",
"物流商": "logisticsTypeDesc",
"打包完成时间": "packageFinishTime",
"最晚自提时间": "latestSelfTakeTime",
"最晚可创建自提时间": "latestSelfTakeTime",
"出库时间": "outboundTime"
},
form: {
@@ -177,6 +173,7 @@ import { Message } from 'element-ui'
}}).then((res) => {
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.items.length; i++) {
console.log(i)
let item = res.result.items[i];
let data = {};
data.returnSupplierPackageNo = item.returnSupplierPackageNo
@@ -186,8 +183,6 @@ import { Message } from 'element-ui'
data.contactName = item.contactName
data.contactPhone = item.contactPhone
data.packageStatusDesc = item.packageStatusDesc
data.returnSupplierReasonDesc = JSON.parse(item.returnSupplierReasonDesc).join('')
data.reason = item.reason
data.returnSupplierQuantity = item.returnSupplierQuantity
data.returnHandOverTypeDesc = item.returnHandOverTypeDesc
data.payMethodDesc = item.payMethodDesc