调整
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"dependencies": {
|
||||
"@antv/g2plot": "^2.4.25",
|
||||
"axios": "^1.4.0",
|
||||
"bi-vue-mindmap": "^0.6.12",
|
||||
"core-js": "^3.8.3",
|
||||
"crypto-js": "^4.0.0",
|
||||
"dayjs": "^1.11.9",
|
||||
|
||||
274
public/js/temuSeller.js
Normal file
274
public/js/temuSeller.js
Normal file
@@ -0,0 +1,274 @@
|
||||
function matchTemuDomain(url) {
|
||||
const urlPattern = /https:\/\/([\da-z\.-]+)\.kuajingmaihuo\.com\//
|
||||
return urlPattern.test(url);
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (matchTemuDomain(window.location.href)) {
|
||||
let j = 0
|
||||
let timer = setInterval(() => {
|
||||
let models = document.querySelectorAll('div[class^="MDL_header"]')
|
||||
let flag = false
|
||||
for (let i = 0; i < models.length; i++) {
|
||||
if (models[i].textContent.includes("商品降价提醒") || models[i].textContent.includes("降价,提升竞争力,避免限制备货")) {
|
||||
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]
|
||||
}
|
||||
models[i].appendChild(popup)
|
||||
popup.addEventListener('click', async () => {
|
||||
let tbodyObj = models[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")) {
|
||||
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 models2 = document.querySelectorAll('div[class^="price-adjust-confirm-system_contentWrp"]')
|
||||
for (let i = 0; i < models2.length; i++) {
|
||||
let tipsObj = models2[i].querySelector('div[class^="price-adjust-confirm-system_tips"]')
|
||||
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].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")) {
|
||||
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')
|
||||
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 = models3[i].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")) {
|
||||
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 models4 = document.querySelectorAll('div[class^="price-adjust-confirm-system-old_contentWrp"]')
|
||||
for (let i = 0; i < models4.length; i++) {
|
||||
let tipsObj = models4[i].querySelector('div[class^="price-adjust-confirm-system-old_tips"]')
|
||||
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 = models4[i].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")) {
|
||||
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 models5 = document.querySelectorAll('div[class^="new-price-adjust-confirm_content"]')
|
||||
for (let i = 0; i < models5.length; i++) {
|
||||
let tipsObj = models5[i].querySelector('div[class^="new-price-adjust-confirm_tips"]')
|
||||
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 = models5[i].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")) {
|
||||
let labelObj = tdObj.querySelector('div label:nth-child(2)')
|
||||
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
|
||||
// await sleepSync(50)
|
||||
radioObj.click()
|
||||
}
|
||||
}
|
||||
})
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
clearInterval(timer)
|
||||
} else {
|
||||
j++
|
||||
if (j == 10) {
|
||||
clearInterval(timer)
|
||||
}
|
||||
}
|
||||
}, 3000)
|
||||
|
||||
// document.body.appendChild(popup)
|
||||
}
|
||||
}
|
||||
/*
|
||||
function createElement() {
|
||||
const popup = document.createElement("div")
|
||||
popup.innerText = "拒绝调价"
|
||||
const styles = {
|
||||
position: "fixed",
|
||||
right: '10px',
|
||||
top: '60px',
|
||||
zIndex: 999999,
|
||||
padding: "8px",
|
||||
background: "#409EFF",
|
||||
color: "#fff",
|
||||
borderRadius: "8px",
|
||||
cursor: "pointer"
|
||||
}
|
||||
for (const e in styles) {
|
||||
popup.style[e] = styles[e]
|
||||
}
|
||||
popup.addEventListener('click', async () => {
|
||||
let divObj1 = document.querySelector('div[class^="price-adjust-confirm-system_contentWrp"]')
|
||||
if (divObj1) {
|
||||
let tbodyObj = divObj1.querySelector('tbody')
|
||||
let trList = tbodyObj.querySelectorAll('tr')
|
||||
for (let i = 0; i < trList.length; i++) {
|
||||
let tdObj = trList[i].querySelector('td:last-child')
|
||||
let labelObj = tdObj.querySelector('div label:last-child')
|
||||
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
|
||||
// await sleepSync(50)
|
||||
radioObj.click()
|
||||
}
|
||||
}
|
||||
let divObj2 = document.querySelector('div[class^="price-adjust-confirm_header"]')
|
||||
if (divObj2) {
|
||||
let divObj = divObj2.nextElementSibling
|
||||
let tbodyObj = divObj.querySelector('tbody')
|
||||
let trList = tbodyObj.querySelectorAll('tr')
|
||||
for (let i = 0; i < trList.length; i++) {
|
||||
let tdObj = trList[i].querySelector('td:last-child')
|
||||
let labelObj = tdObj.querySelector('div label:last-child')
|
||||
//let radioObj = labelObj.querySelector("[type='radio']")
|
||||
// await sleepSync(50)
|
||||
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
|
||||
radioObj.click()
|
||||
}
|
||||
}
|
||||
let divObj3 = document.querySelector('div[class^="price-adjust-confirm-new_banner"]')
|
||||
if (divObj3) {
|
||||
let divObj = divObj3.nextElementSibling
|
||||
let tbodyObj = divObj.querySelector('tbody')
|
||||
let trList = tbodyObj.querySelectorAll('tr')
|
||||
for (let i = 0; i < trList.length; i++) {
|
||||
let tdObj = trList[i].querySelector('td:last-child')
|
||||
let labelObj = tdObj.querySelector('div label:last-child')
|
||||
//let radioObj = labelObj.querySelector("[type='radio']")
|
||||
// await sleepSync(50)
|
||||
let radioObj = labelObj.querySelector('div[class^="RD_radioWrapper"]')
|
||||
radioObj.click()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return popup
|
||||
}
|
||||
*/
|
||||
init()
|
||||
8
public/js/temuSellerContent.js
Normal file
8
public/js/temuSellerContent.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function injectScript(file, node) {
|
||||
var th = document.getElementsByTagName(node)[0];
|
||||
var s = document.createElement('script');
|
||||
s.setAttribute('type', 'text/javascript');
|
||||
s.setAttribute('src', file);
|
||||
th.appendChild(s);
|
||||
}
|
||||
injectScript( chrome.runtime.getURL('/js/temuSeller.js'), 'body');
|
||||
@@ -426,13 +426,14 @@ export default {
|
||||
content['cat' + (i+1) + 'Id'] = this.form.targetCatId[i]
|
||||
}
|
||||
}
|
||||
if (content['cat'+(i+1)+'Id'] != reqData.catId) {
|
||||
if (content['cat'+(i)+'Id'] != reqData.catId) {
|
||||
content['cat'+(++i)+'Id'] = reqData.catId
|
||||
}
|
||||
for (; i < 10; i++) {
|
||||
content['cat' + (i+1) + 'Id'] = ''
|
||||
}
|
||||
|
||||
content.personalizationSwitch = 0
|
||||
content.productDraftId = draftId
|
||||
|
||||
this.createProduct(content)
|
||||
|
||||
@@ -8,3 +8,4 @@ function injectScript(file, node) {
|
||||
injectScript( chrome.runtime.getURL('/js/jszip.min.js'), 'body');
|
||||
injectScript( chrome.runtime.getURL('/js/FileSaver.js'), 'body');
|
||||
injectScript( chrome.runtime.getURL('/js/download.js'), 'body');
|
||||
injectScript( chrome.runtime.getURL('/js/temuSeller.js'), 'body');
|
||||
|
||||
@@ -76,12 +76,24 @@
|
||||
"js": [
|
||||
"/content.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"*://*.kuajingmaihuo.com/*"
|
||||
],
|
||||
"js": [
|
||||
"/js/temuSellerContent.js"
|
||||
]
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ],
|
||||
"matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*", "*://*.shein.com/*" ]
|
||||
},
|
||||
{
|
||||
"resources": [ "js/temuSeller.js" ],
|
||||
"matches": [ "*://*.kuajingmaihuo.com/*" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 3,
|
||||
"name": "TEMU助手",
|
||||
"description": "TEMU助手 - 自动化提高生产效率",
|
||||
"version": "3.2.3",
|
||||
"version": "3.2.8",
|
||||
"background": {
|
||||
"service_worker": "/background.js"
|
||||
},
|
||||
@@ -80,12 +80,24 @@
|
||||
"js": [
|
||||
"/content.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"*://*.kuajingmaihuo.com/*"
|
||||
],
|
||||
"js": [
|
||||
"/js/temuSellerContent.js"
|
||||
]
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ],
|
||||
"matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*", "*://*.shein.com/*" ]
|
||||
},
|
||||
{
|
||||
"resources": [ "js/temuSeller.js" ],
|
||||
"matches": [ "*://*.kuajingmaihuo.com/*" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ const router = new VueRouter({
|
||||
name: 'myUrgencyOrder',
|
||||
component: () => import('../view/shipping/MyUrgencyOrder.vue')
|
||||
},
|
||||
{
|
||||
path: 'productLabel',
|
||||
name: 'productLabel',
|
||||
component: () => import('../view/shipping/ProductLabel.vue')
|
||||
},
|
||||
{
|
||||
path: 'returnPackage',
|
||||
name: 'returnPackage',
|
||||
@@ -202,6 +207,11 @@ const router = new VueRouter({
|
||||
name: 'afterSaleDeductStat',
|
||||
component: () => import('../view/sale/AfterSaleDeductStat.vue')
|
||||
},
|
||||
{
|
||||
path: 'saleStatTemu',
|
||||
name: 'saleStatTemu',
|
||||
component: () => import('../view/sale/ExportSaleStatTemu.vue')
|
||||
},
|
||||
{
|
||||
path: 'costManageShein',
|
||||
name: 'costManageShein',
|
||||
|
||||
@@ -135,6 +135,7 @@ export function transform(leftData) {
|
||||
countryShortName: leftData.productWhExtAttr.productOrigin ? leftData.productWhExtAttr.productOrigin.countryShortName: 'CN'
|
||||
}
|
||||
};
|
||||
rightData.personalizationSwitch = leftData.productWhExtAttr.personalizationSwitch || "0"
|
||||
rightData.productCarouseVideoReqList = leftData.carouseVideoVOList;
|
||||
rightData.goodsAdvantageLabelTypes = leftData.goodsAdvantageLabelVOList;
|
||||
rightData.productDetailVideoReqList = leftData.detailVideoVOList;
|
||||
@@ -297,6 +298,7 @@ export function transformSubmitForHalf(leftData, config, draftId) {
|
||||
countryShortName: leftData.productWhExtAttr.productOrigin ? leftData.productWhExtAttr.productOrigin.countryShortName: 'CN'
|
||||
}
|
||||
};
|
||||
rightData.personalizationSwitch = leftData.productWhExtAttr.personalizationSwitch || 0
|
||||
rightData.productCarouseVideoReqList = leftData.carouseVideoVOList;
|
||||
rightData.goodsAdvantageLabelTypes = leftData.goodsAdvantageLabelVOList;
|
||||
rightData.productDetailVideoReqList = leftData.detailVideoVOList;
|
||||
@@ -323,14 +325,20 @@ export function transformSubmitForHalf(leftData, config, draftId) {
|
||||
freightTemplateId: config.freightTemplateId,
|
||||
shipmentLimitSecond: config.sendGoodsSecond
|
||||
}
|
||||
let bindSiteIds = []
|
||||
if (leftData.productSaleExtAttr?.productSemiManaged?.bindSites) {
|
||||
leftData.productSaleExtAttr?.productSemiManaged?.bindSites.map(ii => {
|
||||
bindSiteIds.push(ii.siteId)
|
||||
})
|
||||
}
|
||||
rightData.productSemiManagedReq = {
|
||||
bindSiteIds: config.siteList
|
||||
bindSiteIds: bindSiteIds
|
||||
}
|
||||
let targetRouteList = []
|
||||
for (let m = 0; m < config.wareHouseList.length; m++) {
|
||||
targetRouteList.push({
|
||||
warehouseId: config.wareHouseList[m],
|
||||
siteIdList: config.siteList
|
||||
siteIdList: bindSiteIds
|
||||
})
|
||||
}
|
||||
rightData.productWarehouseRouteReq = {
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<el-menu-item index="/shippingList">已收货发货单</el-menu-item>
|
||||
<el-menu-item index="/myNormalOrder">普通备货单</el-menu-item>
|
||||
<el-menu-item index="/myUrgencyOrder">紧急备货单</el-menu-item>
|
||||
<el-menu-item index="/productLabel">商品条码管理</el-menu-item>
|
||||
</el-submenu>
|
||||
|
||||
<el-submenu index="/copyProduct">
|
||||
@@ -131,6 +132,7 @@
|
||||
</template>
|
||||
<el-menu-item index="/costManageTemu">成本管理</el-menu-item>
|
||||
<el-menu-item index="/saleData">销售管理</el-menu-item>
|
||||
<el-menu-item index="/saleStatTemu">销售统计</el-menu-item>
|
||||
<el-menu-item index="/saleOut">售罄看板</el-menu-item>
|
||||
<el-menu-item index="/afterSaleStat">售后统计</el-menu-item>
|
||||
<el-menu-item index="/afterSaleDeductStat">售后赔付统计</el-menu-item>
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
productName: item.productName,
|
||||
skcId: item.skcId,
|
||||
popUpType: 1,
|
||||
createTime: res.result.createTime,
|
||||
versionId: res.result.popUpAutoPass12.versionId,
|
||||
newSupplyPrice: item.newSupplyPrice / 100,
|
||||
}
|
||||
@@ -119,6 +120,7 @@
|
||||
productName: item.productName,
|
||||
skcId: item.skcId,
|
||||
popUpType: 2,
|
||||
createTime: res.result.createTime,
|
||||
versionId: res.result.popUpAutoPass24.versionId,
|
||||
newSupplyPrice: item.newSupplyPrice / 100,
|
||||
}
|
||||
@@ -132,6 +134,7 @@
|
||||
productName: item.productName,
|
||||
skcId: item.skcId,
|
||||
popUpType: 3,
|
||||
createTime: res.result.createTime,
|
||||
versionId: res.result.popUpOthers.versionId,
|
||||
newSupplyPrice: item.newSupplyPrice / 100,
|
||||
}
|
||||
@@ -166,10 +169,12 @@
|
||||
let popUpType1VersionId = ''
|
||||
let popUpType2VersionId = ''
|
||||
let popUpType3VersionId = ''
|
||||
let createTime = null
|
||||
let ids = []
|
||||
this.priceList.map(item => {
|
||||
if (item.popUpType == 1) {
|
||||
popUpType1VersionId = item.versionId
|
||||
createTime = item.createTime
|
||||
ids.push(item.id)
|
||||
}
|
||||
})
|
||||
@@ -183,12 +188,13 @@
|
||||
"rejectOrderIdList": ids,
|
||||
"maxOrderId": popUpType1VersionId,
|
||||
"popUpType": 1,
|
||||
"createTime": new Date().getTime()
|
||||
"createTime": createTime
|
||||
}})
|
||||
}
|
||||
ids = []
|
||||
this.priceList.map(item => {
|
||||
if (item.popUpType == 2) {
|
||||
createTime = item.createTime
|
||||
popUpType2VersionId = item.versionId
|
||||
ids.push(item.id)
|
||||
}
|
||||
@@ -202,12 +208,13 @@
|
||||
"rejectOrderIdList": ids,
|
||||
"maxOrderId": popUpType2VersionId,
|
||||
"popUpType": 2,
|
||||
"createTime": new Date().getTime()
|
||||
"createTime": createTime
|
||||
}})
|
||||
}
|
||||
ids = []
|
||||
this.priceList.map(item => {
|
||||
if (item.popUpType == 3) {
|
||||
createTime = item.createTime
|
||||
popUpType3VersionId = item.versionId
|
||||
ids.push(item.id)
|
||||
}
|
||||
@@ -221,7 +228,7 @@
|
||||
"rejectOrderIdList": ids,
|
||||
"maxOrderId": popUpType3VersionId,
|
||||
"popUpType": 3,
|
||||
"createTime": new Date().getTime()
|
||||
"createTime": createTime
|
||||
}})
|
||||
}
|
||||
if (res.success && res.errorCode == 1000000) {
|
||||
|
||||
@@ -32,9 +32,12 @@
|
||||
</div>
|
||||
</ai-card>
|
||||
</div>
|
||||
<ai-card title="常用工具" v-if="false">
|
||||
<div class="">
|
||||
dsad
|
||||
<ai-card title="TEMU助手功能概览">
|
||||
<template #right>
|
||||
<a href="https://www.yuque.com/liushiwei-f582m/kb/bmqqls0o5ybd6c8p?singleDoc" style="color: blue; font-size: 18px; text-decoration: underline;" target="_blank">在线帮助手册</a>
|
||||
</template>
|
||||
<div style="height: 1000px">
|
||||
<BiVueMindmap ref="bi-vue-mindmap" :isReadonly="true" :flatNodes="mindmapNodes" />
|
||||
</div>
|
||||
</ai-card>
|
||||
<AiDialog
|
||||
@@ -58,9 +61,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BiVueMindmap from "bi-vue-mindmap";
|
||||
|
||||
export default {
|
||||
name: 'AdminHome',
|
||||
components: {
|
||||
BiVueMindmap,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
noticeList: [],
|
||||
@@ -70,7 +77,258 @@
|
||||
changeLogList: [],
|
||||
isImportant: false,
|
||||
version: '',
|
||||
isShowDownload: false
|
||||
isShowDownload: false,
|
||||
mindmapNodes: [
|
||||
{
|
||||
id: "01",
|
||||
parentId: null,
|
||||
title: "TEMU助手"
|
||||
},
|
||||
{
|
||||
id: "0101",
|
||||
parentId: "01",
|
||||
title: "TEMU"
|
||||
},
|
||||
{
|
||||
id: "010101",
|
||||
parentId: "0101",
|
||||
title: "辅助运营"
|
||||
},
|
||||
{
|
||||
id: "01010101",
|
||||
parentId: "010101",
|
||||
title: "备货单管理",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101010101",
|
||||
parentId: "01010101",
|
||||
title: "创建备货单:批量领取系统下的备货单"
|
||||
},
|
||||
{
|
||||
id: "0101010102",
|
||||
parentId: "01010101",
|
||||
title: "抢仓发货:同时操作多个店铺自动抢仓并创建发货单",
|
||||
resources: [{
|
||||
type: "VIDEO",
|
||||
url: "http://temu.jjcp52.com/dist/qiangcang.mp4"
|
||||
}]
|
||||
},
|
||||
{
|
||||
id: "0101010103",
|
||||
parentId: "01010101",
|
||||
title: "发货台管理:批量从“发货台”创建发货单"
|
||||
},
|
||||
{
|
||||
id: "0101010104",
|
||||
parentId: "01010101",
|
||||
title: "待装箱发货单:对应“备货单管理”->“发货单列表”,“待装箱发货”列表,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010105",
|
||||
parentId: "01010101",
|
||||
title: "待收货发货单:对应“备货单管理”->“发货单列表”,“待仓库收货”列表,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010106",
|
||||
parentId: "01010101",
|
||||
title: "已收货发货单:对应“备货单管理”->“发货单列表”,“已收货”列表,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010107",
|
||||
parentId: "01010101",
|
||||
title: "普通备货单:对应“备货单管理”->“我的备货单”,“普通备货单”列表,支持导出、成本统计"
|
||||
},
|
||||
{
|
||||
id: "0101010108",
|
||||
parentId: "01010101",
|
||||
title: "紧急备货单:对应“备货单管理”->“我的备货单”,“紧急备货单”列表,支持导出、成本统计"
|
||||
},
|
||||
{
|
||||
id: "0101010109",
|
||||
parentId: "01010101",
|
||||
title: "商品条码管理:对应“备货单管理”->“商品条码管理”,支持导出,可用于自定义生成标签,提高贴标效率"
|
||||
},
|
||||
{
|
||||
id: "01010102",
|
||||
parentId: "010101",
|
||||
title: "商品管理",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101010201",
|
||||
parentId: "01010102",
|
||||
title: "商品管理:对应“商品管理”->“商品列表”,支持导出,支持半托管"
|
||||
},
|
||||
{
|
||||
id: "0101010202",
|
||||
parentId: "01010102",
|
||||
title: "商品复制:店铺之间快速商品拷贝"
|
||||
},
|
||||
{
|
||||
id: "0101010203",
|
||||
parentId: "01010102",
|
||||
title: "查找买手:根据SKC查询买手名字"
|
||||
},
|
||||
{
|
||||
id: "0101010204",
|
||||
parentId: "01010102",
|
||||
title: "上新生命周期:对应“商品管理”->“上新生命周期管理”,支持导出未发布到站点、已下架的数据"
|
||||
},
|
||||
{
|
||||
id: "01010103",
|
||||
parentId: "010101",
|
||||
title: "库存管理",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101010301",
|
||||
parentId: "01010103",
|
||||
title: "退货包裹管理:对应“库存管理”->“退货包裹管理”,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010302",
|
||||
parentId: "01010103",
|
||||
title: "退货明细:对应“库存管理”->“退货明细”,支持导出"
|
||||
},
|
||||
{
|
||||
id: "01010104",
|
||||
parentId: "010101",
|
||||
title: "销售管理",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101010401",
|
||||
parentId: "01010104",
|
||||
title: "成本管理:维护SKU的成本价格,用于成本、利润的计算和统计"
|
||||
},
|
||||
{
|
||||
id: "0101010402",
|
||||
parentId: "01010104",
|
||||
title: "销售管理:对应“销售管理”->“销售管理”,统计今日销量/销售额、今日利润/利润率、库存/在途库存,支持数据导出"
|
||||
},
|
||||
{
|
||||
id: "0101010403",
|
||||
parentId: "01010104",
|
||||
title: "销售统计:统计过去一段时间内,总体销售额/单量/成本/利润/利润率的统计,以及SKC/SKU维度的销售额/利润/单量的统计,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010404",
|
||||
parentId: "01010104",
|
||||
title: "售罄看板:对应“销售管理”->“售罄看板”,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010405",
|
||||
parentId: "01010104",
|
||||
title: "售后统计:对应“结算管理”->“售后管理”,计算预计扣款,白卖件数,支持导出"
|
||||
},
|
||||
{
|
||||
id: "0101010406",
|
||||
parentId: "01010104",
|
||||
title: "售后赔付统计:对应“结算管理”->“对账中心”->“扣款详情”,统计过去一段时间内店铺的扣款总金额/次数,支持导出"
|
||||
},
|
||||
{
|
||||
id: "01010105",
|
||||
parentId: "010101",
|
||||
title: "其他",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101010501",
|
||||
parentId: "01010105",
|
||||
title: "弹窗消息:支持一键已读所有店铺的弹窗消息"
|
||||
},
|
||||
{
|
||||
id: "0101010502",
|
||||
parentId: "01010105",
|
||||
title: "拒绝调价:辅助批量点击“我不接受”按钮,减轻工作量,避免遗漏",
|
||||
resources: [{
|
||||
type: "PIC",
|
||||
url: "http://temu.jjcp52.com/dist/refuse-price.png"
|
||||
}]
|
||||
},
|
||||
{
|
||||
id: "010102",
|
||||
parentId: "0101",
|
||||
title: "选品采集"
|
||||
},
|
||||
{
|
||||
id: "01010201",
|
||||
parentId: "010102",
|
||||
title: "商品采集:根据TEMU前端地址,采集商品信息到店铺草稿箱,减轻上品工作量",
|
||||
resources: [{
|
||||
type: "VIDEO",
|
||||
url: "http://temu.jjcp52.com/dist/xuanpin.mp4"
|
||||
}]
|
||||
},
|
||||
{
|
||||
id: "01010202",
|
||||
parentId: "010102",
|
||||
title: "速卖通采集:根据“速卖通”前端地址,采集商品信息到店铺草稿箱,减轻上品工作量"
|
||||
},
|
||||
{
|
||||
id: "01010203",
|
||||
parentId: "010102",
|
||||
title: "选品跟踪",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "0101020301",
|
||||
parentId: "01010203",
|
||||
title: "店铺跟踪:跟踪指定店铺的销售趋势、价格趋势,采集跟卖。(暂时不可用)"
|
||||
},
|
||||
{
|
||||
id: "0101020302",
|
||||
parentId: "01010203",
|
||||
title: "关键字跟踪:根据筛选关键字,跟踪该关键字在TEMU前端搜索结果的销售趋势、价格趋势,采集跟卖"
|
||||
},
|
||||
{
|
||||
id: "0101020303",
|
||||
parentId: "01010203",
|
||||
title: "新品跟踪:跟踪TEMU前端“Best Sellers”->“Within last 7 days”的新品,采集跟卖"
|
||||
},
|
||||
{
|
||||
id: "0101020304",
|
||||
parentId: "01010203",
|
||||
title: "单品跟踪:根据TEMU前端地址,采集销售趋势、价格趋势"
|
||||
},
|
||||
{
|
||||
id: "0102",
|
||||
parentId: "01",
|
||||
title: "SHEIN(希音)"
|
||||
},
|
||||
{
|
||||
id: "010201",
|
||||
parentId: "0102",
|
||||
title: "辅助运营",
|
||||
isFolded: true
|
||||
},
|
||||
{
|
||||
id: "01020101",
|
||||
parentId: "010201",
|
||||
title: "成本管理:维护SKU的成本价格,用于成本、利润的计算和统计"
|
||||
},
|
||||
{
|
||||
id: "01020102",
|
||||
parentId: "010201",
|
||||
title: "销售管理:对应SHEIN商家后台“商品管理”->“备货信息”,统计当天的销售额、销量、库存等信息,计算成本和利润"
|
||||
},
|
||||
{
|
||||
id: "01020103",
|
||||
parentId: "010201",
|
||||
title: "证书中心:对应SHEIN商家后台“商品管理”->“证书中心”,导出已驳回和待补充的证书列表,线下跟踪"
|
||||
},
|
||||
{
|
||||
id: "01020104",
|
||||
parentId: "010201",
|
||||
title: "商品复制:希音店铺间商品进行快速复制,节省上品时间"
|
||||
},
|
||||
{
|
||||
id: "01020105",
|
||||
parentId: "010201",
|
||||
title: "商家账单统计:对应SHEIN商家后台“财务管理”->“商家账单”,统计一段时期内销售额、单量、成本、利润、利润率,SKC/SKU维度统计排名,支持导出"
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -93,9 +93,12 @@ import CryptoJS from 'crypto-js'
|
||||
this.$message.success('两次密码输入不一致');
|
||||
return;
|
||||
}
|
||||
const devVersion = require('../../manifest.development.json').version
|
||||
const prodVersion = require('../../manifest.production.json').version
|
||||
this.btnLoading = true
|
||||
this.$http.post(`/api/malluser/reg`, {
|
||||
...this.form
|
||||
...this.form,
|
||||
version: process.env.NODE_ENV === 'production' ? prodVersion : devVersion
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: 'Basic cGM6cGM='
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
style="margin-top: 8px;"
|
||||
:current.sync="search.current" :size.sync="search.size"
|
||||
@selection-change="handleSelectionChange"
|
||||
height="700"
|
||||
@getList="getList">
|
||||
</ai-table>
|
||||
</div>
|
||||
@@ -545,6 +546,7 @@ import AiLazyCascader from "@/components/AiLazyCascader.vue"
|
||||
bindSiteIds: this.form.siteId
|
||||
}
|
||||
}
|
||||
content.personalizationSwitch = content.personalizationSwitch || 0
|
||||
setTimeout(() => {
|
||||
sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/product/draft/add',
|
||||
|
||||
@@ -323,7 +323,8 @@ import JsonExcel from 'vue-json-excel'
|
||||
supplierPrice: item.productSkuSummaries[k].supplierPrice / 100,
|
||||
specName: temp.join(","),
|
||||
skuStockQuantity,
|
||||
todaySalesVolume: item.productSkuSummaries[k].todaySalesVolume}
|
||||
todaySalesVolume: item.productSkuSummaries[k].todaySalesVolume
|
||||
}
|
||||
|
||||
this.tableData.push(data)
|
||||
}
|
||||
|
||||
@@ -226,25 +226,6 @@ import JsonExcel from 'vue-json-excel'
|
||||
}
|
||||
}
|
||||
},
|
||||
async getSkuCostList() {
|
||||
this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.mallId
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.costList = res.data
|
||||
this.tableData.map(item => {
|
||||
for (let i = 0; i < this.costList.length; i++) {
|
||||
if (item.productSkuId == this.costList[i].sku) {
|
||||
item.cost = this.costList[i].costPrice
|
||||
item.profitTimes = Math.round((item.supplierPrice * item.punishRatio + item.cost * item.times) / (item.supplierPrice - item.cost) * 100) / 100
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="售后统计"
|
||||
tips="请事先在“成本管理”维护好成本,否则部分计算不准确"
|
||||
isShowBottomBorder>
|
||||
<template #rightBtn>
|
||||
<div class="title-right">
|
||||
@@ -172,8 +173,7 @@ import JsonExcel from 'vue-json-excel'
|
||||
this.reqData.pageNo = 1
|
||||
|
||||
await this.getProductList({page: this.reqData.pageNo,
|
||||
pageSize: this.reqData.pageSize,
|
||||
productSkuIds: skuIds})
|
||||
pageSize: this.reqData.pageSize}, skuIds)
|
||||
|
||||
this.costList = []
|
||||
await this.getSkuCostList()
|
||||
@@ -227,13 +227,24 @@ import JsonExcel from 'vue-json-excel'
|
||||
this.$store.commit("setTemuAlertShow", true)
|
||||
}
|
||||
},
|
||||
async getProductList(params) {
|
||||
async getProductList(params, skuIds) {
|
||||
let productSkuIds = []
|
||||
let i = (params.page - 1) * params.pageSize
|
||||
let j = 0
|
||||
for (; i < skuIds.length; i++) {
|
||||
productSkuIds.push(skuIds[i])
|
||||
j ++
|
||||
if (j == params.pageSize) break
|
||||
}
|
||||
if (productSkuIds.length == 0) return
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/product/skc/pageQuery',
|
||||
needMallId: true,
|
||||
mallId: this.mallId,
|
||||
data: {
|
||||
...params
|
||||
page: 1,
|
||||
pageSize: params.pageSize,
|
||||
productSkuIds
|
||||
}})
|
||||
if (res.errorCode == 1000000) {
|
||||
res.result.pageItems.map((item) => {
|
||||
@@ -251,10 +262,8 @@ import JsonExcel from 'vue-json-excel'
|
||||
})
|
||||
})
|
||||
|
||||
if ((params.page * params.pageSize) < res.result.total) {
|
||||
params.page ++
|
||||
await this.getProductList(params)
|
||||
}
|
||||
params.page ++
|
||||
await this.getProductList(params, skuIds)
|
||||
}
|
||||
},
|
||||
async getSkuCostList() {
|
||||
|
||||
@@ -206,6 +206,7 @@ import { saveAs } from 'file-saver'
|
||||
this.isLoading = true
|
||||
this.getList()
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="销售数据"
|
||||
tips="请事先在“成本管理”维护好成本,否则部分计算不准确"
|
||||
isShowBottomBorder>
|
||||
<template #rightBtn>
|
||||
<div class="title-right">
|
||||
@@ -133,7 +134,7 @@
|
||||
ref="table0"
|
||||
:isShowPagination="false"
|
||||
:tableData="filteredData"
|
||||
height="500"
|
||||
height="700"
|
||||
:col-configs="colConfigs"
|
||||
:total="filteredData.length"
|
||||
style="margin-top: 8px;"
|
||||
@@ -706,6 +707,7 @@ import { Message } from 'element-ui'
|
||||
this.getSkuCostList()
|
||||
this.getList()
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
console.log(err)
|
||||
this.isLoading = false
|
||||
})
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
:tableData="tableData"
|
||||
:col-configs="colConfigs"
|
||||
:total="tableData.length"
|
||||
height="500"
|
||||
height="700"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
@@ -150,6 +150,7 @@ import { Message } from 'element-ui'
|
||||
this.getList(2)
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
888
src/view/sale/ExportSaleStatTemu.vue
Normal file
888
src/view/sale/ExportSaleStatTemu.vue
Normal file
@@ -0,0 +1,888 @@
|
||||
<template>
|
||||
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="销售统计"
|
||||
tips="最多只能统计近60天的销售数据"
|
||||
isShowBottomBorder>
|
||||
<template #rightBtn>
|
||||
<div class="title-right">
|
||||
<div>
|
||||
<label style="width:90px">时间范围:</label>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div>
|
||||
<label style="width:90px">店铺:</label>
|
||||
<el-select v-model="mallId" placeholder="请选择" size="small">
|
||||
<el-option
|
||||
v-for="item in $store.state.mallList"
|
||||
:key="item.mallId"
|
||||
:label="item.mallName"
|
||||
:value="item.mallId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="toBeginStat">开始统计</el-button>
|
||||
<el-button type="primary" icon="el-icon-download" @click="downloadPicture">下载图片</el-button>
|
||||
<json-excel
|
||||
:data="skcList"
|
||||
:fields="skcJsonFields"
|
||||
name="SKC销售统计.xls"
|
||||
worksheet="SKC销售统计">
|
||||
<el-button type="primary" icon="el-icon-download">下载SKC统计</el-button>
|
||||
</json-excel>
|
||||
<json-excel
|
||||
:data="skuList"
|
||||
:fields="skuJsonFields"
|
||||
name="SKU销售统计.xls"
|
||||
worksheet="SKU销售统计">
|
||||
<el-button type="primary" icon="el-icon-download">下载SKU统计</el-button>
|
||||
</json-excel>
|
||||
</div>
|
||||
</template>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<div id="app-content">
|
||||
<ai-card title="数据概览" style="padding-bottom: 40px;">
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="5">
|
||||
<div>
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="saleAmount"
|
||||
title="销售额"
|
||||
>
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<div>
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:value="saleCount"
|
||||
title="单量"
|
||||
>
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<div>
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="costAmount"
|
||||
title="成本"
|
||||
></el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<div>
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="profitAmount"
|
||||
title="利润"
|
||||
></el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="profitPercent"
|
||||
title="利润率"
|
||||
>
|
||||
<template slot="suffix">%</template>
|
||||
</el-statistic>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</ai-card>
|
||||
<ai-card title="趋势分析" style="padding-bottom: 40px;">
|
||||
<div>
|
||||
<div id="chart1"></div>
|
||||
</div>
|
||||
</ai-card>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKC销售额TOP10排行">
|
||||
<ai-table
|
||||
ref="table0"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleAmountSkcList"
|
||||
:col-configs="skcColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKC利润TOP10排行">
|
||||
<ai-table
|
||||
ref="table1"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleProfitSkcList"
|
||||
:col-configs="skcColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKC单量TOP10排行">
|
||||
<ai-table
|
||||
ref="table2"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleCountSkcList"
|
||||
:col-configs="skcColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKU销售额TOP10排行">
|
||||
<ai-table
|
||||
ref="table3"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleAmountSkuList"
|
||||
:col-configs="skuColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="skuExtCode" label="SKC属性/SKU属性" width="250px" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.skcExtCode + '/' + scope.row.skuExtCode }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKU利润TOP10排行">
|
||||
<ai-table
|
||||
ref="table4"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleProfitSkuList"
|
||||
:col-configs="skuColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="skuExtCode" label="SKC属性/SKU属性" width="250px" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.skcExtCode + '/' + scope.row.skuExtCode }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ai-card title="SKU单量TOP10排行">
|
||||
<ai-table
|
||||
ref="table5"
|
||||
:isShowPagination="false"
|
||||
:tableData="topSaleCountSkuList"
|
||||
:col-configs="skuColConfigs"
|
||||
style="margin-top: 8px;">
|
||||
<el-table-column slot="skuExtCode" label="SKC属性/SKU属性" width="250px" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.skcExtCode + '/' + scope.row.skuExtCode }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleAmount" label="销售额">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.saleAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="profitAmount" label="利润">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.profitAmount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="saleCount" label="单量">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">{{ scope.row.saleCount }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
</ai-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {sendChromeAPIMessage } from '@/api/chromeApi'
|
||||
import JsonExcel from 'vue-json-excel'
|
||||
import { Message } from 'element-ui'
|
||||
import {formatDate} from '@/utils/date'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { DualAxes } from '@antv/g2plot'
|
||||
|
||||
export default {
|
||||
name: 'ExportSaleStatTemu',
|
||||
|
||||
data () {
|
||||
return {
|
||||
mallId: null,
|
||||
storeCode: '',
|
||||
|
||||
dateRange: null,
|
||||
|
||||
currentPage: 1,
|
||||
pageSize: 100,
|
||||
productList: [],
|
||||
productCostList: [],
|
||||
saleAmount: 0.0,
|
||||
saleCount: 0,
|
||||
costAmount: 0.0,
|
||||
profitAmount: 0.0,
|
||||
profitPercent: 0.0,
|
||||
deductionAmount: 0.0,
|
||||
skcList: [],
|
||||
skuList: [],
|
||||
|
||||
leftChartData: [],
|
||||
rightChartData: [],
|
||||
|
||||
isLoading: false,
|
||||
|
||||
skcColConfigs: [
|
||||
{ prop: 'skcExtCode', label: 'SKC货号', width: '250px' },
|
||||
{ slot: 'saleAmount', label: '销售额', align: 'center' },
|
||||
{ slot: 'saleCount', label: '单量', align: 'center' },
|
||||
{ prop: 'costAmount', label: '成本', align: 'center'},
|
||||
{ slot: 'profitAmount', label: '利润', align: 'center' }
|
||||
],
|
||||
skcJsonFields: {
|
||||
"SKC": "productSkcId",
|
||||
"SKC货号": "skcExtCode",
|
||||
"销售额": "saleAmount",
|
||||
"单量": "saleCount",
|
||||
"成本": "costAmount",
|
||||
"利润": "profitAmount"
|
||||
},
|
||||
skuColConfigs: [
|
||||
{ slot: 'skuExtCode', label: 'SKC货号/SKU货号' },
|
||||
{ slot: 'saleAmount', label: '销售额', align: 'center' },
|
||||
{ slot: 'saleCount', label: '单量', align: 'center' },
|
||||
{ prop: 'costAmount', label: '成本', align: 'center'},
|
||||
{ slot: 'profitAmount', label: '利润', align: 'center' }
|
||||
],
|
||||
skuJsonFields: {
|
||||
"SKC": "productSkcId",
|
||||
"SKU": "productSkuId",
|
||||
"SKC货号": "skcExtCode",
|
||||
"SKU货号": "skuExtCode",
|
||||
"销售额": "saleAmount",
|
||||
"单量": "saleCount",
|
||||
"成本": "costAmount",
|
||||
"利润": "profitAmount"
|
||||
},
|
||||
|
||||
chartObj: null
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
topSaleAmountSkcList() {
|
||||
const list = Object.assign([], this.skcList)
|
||||
list.sort((a, b) => b.amount - a.amount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleProfitSkcList() {
|
||||
const list = Object.assign([], this.skcList)
|
||||
list.sort((a, b) => b.profitAmount - a.profitAmount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleCountSkcList() {
|
||||
const list = Object.assign([], this.skcList)
|
||||
list.sort((a, b) => b.saleCount - a.saleCount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleAmountSkuList() {
|
||||
const list = Object.assign([], this.skuList)
|
||||
list.sort((a, b) => b.saleAmount - a.saleAmount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleProfitSkuList() {
|
||||
const list = Object.assign([], this.skuList)
|
||||
list.sort((a, b) => b.profitAmount - a.profitAmount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleCountSkuList() {
|
||||
const list = Object.assign([], this.skuList)
|
||||
list.sort((a, b) => b.saleCount - a.saleCount)
|
||||
return list.slice(0, 10)
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
JsonExcel
|
||||
},
|
||||
mounted () {
|
||||
this.initChart1()
|
||||
},
|
||||
methods: {
|
||||
initChart1 () {
|
||||
this.chartObj = new DualAxes('chart1', {
|
||||
data: [this.leftChartData, this.rightChartData],
|
||||
xField: 'day',
|
||||
yField: ['value', 'value1'],
|
||||
yAxis: {
|
||||
value: {
|
||||
title: {
|
||||
text: '金额'
|
||||
},
|
||||
label: {
|
||||
formatter: (value) => {
|
||||
return `${value}元`;
|
||||
}
|
||||
}
|
||||
},
|
||||
value1: {
|
||||
max: 100,
|
||||
title: {
|
||||
text: '利润率'
|
||||
},
|
||||
label: {
|
||||
formatter: (value) => {
|
||||
return `${value}%`;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
geometryOptions: [
|
||||
{
|
||||
geometry: 'line',
|
||||
color: ['#FF9A49', '#7A8AA1', '#1EEB73', '#C947AE' ],
|
||||
isGroup: true,
|
||||
smooth: true, // 是否平滑
|
||||
seriesField: 'type'
|
||||
},
|
||||
{
|
||||
geometry: 'line',
|
||||
color: ['red' ],
|
||||
lineStyle: {
|
||||
fill: 'red',
|
||||
fillOpacity: 0.5,
|
||||
stroke: 'red',
|
||||
lineWidth: 4,
|
||||
strokeOpacity: 0.7,
|
||||
shadowColor: 'black',
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 5,
|
||||
shadowOffsetY: 5,
|
||||
cursor: 'pointer'
|
||||
},
|
||||
isStack: true,
|
||||
smooth: true, // 是否平滑
|
||||
seriesField: 'type', // 指定使用第二个Y轴字段
|
||||
}],
|
||||
});
|
||||
|
||||
this.chartObj.render();
|
||||
},
|
||||
toBeginStat() {
|
||||
if (!this.dateRange) {
|
||||
Message.error("请选择统计时间范围")
|
||||
return
|
||||
}
|
||||
if (!this.mallId) {
|
||||
Message.error("请选择店铺")
|
||||
return
|
||||
}
|
||||
this.$userCheck(this.mallId).then(() => {
|
||||
this.beginStat()
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
async beginStat() {
|
||||
this.currentPage = 1
|
||||
this.isLoading = true
|
||||
this.saleAmount = 0.0
|
||||
this.saleCount = 0
|
||||
this.costAmount = 0.0
|
||||
this.profitAmount = 0.0
|
||||
this.profitPercent = 0.0
|
||||
this.productList = []
|
||||
this.productCostList = []
|
||||
this.skcList = []
|
||||
this.skuList = []
|
||||
this.leftChartData = []
|
||||
this.rightChartData = []
|
||||
this.chartObj.changeData([this.leftChartData, this.rightChartData])
|
||||
await this.getProductList()
|
||||
await this.getSkuCostList()
|
||||
await this.getSkuSaleNumber(0)
|
||||
this.leftChartData.sort((a, b) => {
|
||||
let leftDate = new Date(a.day)
|
||||
let rightDate = new Date(b.day)
|
||||
return leftDate.getTime() - rightDate.getTime()
|
||||
})
|
||||
this.leftChartData.map(item => {
|
||||
if (item.type == '销售额' || item.type == '成本' || item.type == '利润') {
|
||||
item.value = Math.round(item.value * 100) / 100
|
||||
}
|
||||
|
||||
if (item.type == '销售额') {
|
||||
this.leftChartData.map(item1 => {
|
||||
if (item1.type == '成本' && item1.day == item.day) {
|
||||
this.rightChartData.push({
|
||||
day: item1.day,
|
||||
value1: Math.round((item.value - item1.value) / item.value * 10000) / 100,
|
||||
type: '利润率'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
this.rightChartData.sort((a, b) => {
|
||||
let leftDate = new Date(a.day)
|
||||
let rightDate = new Date(b.day)
|
||||
return leftDate.getTime() - rightDate.getTime()
|
||||
})
|
||||
this.skuList = this.skuList.filter(item => {
|
||||
return item.saleCount > 0
|
||||
})
|
||||
|
||||
this.skuList.map(item => {
|
||||
item.saleAmount = Math.round(item.saleAmount * 100) / 100
|
||||
item.costAmount = Math.round(item.costAmount * 100) / 100
|
||||
item.profitAmount = Math.round(item.profitAmount * 100) / 100
|
||||
})
|
||||
this.skuList.map(item => {
|
||||
let flag = false
|
||||
for (let i = 0; i < this.skcList.length; i++) {
|
||||
if (item.productSkcId == this.skcList[i].productSkcId) {
|
||||
this.skcList[i].saleAmount = this.skcList[i].saleAmount + item.saleAmount
|
||||
this.skcList[i].costAmount = this.skcList[i].costAmount + item.costAmount
|
||||
this.skcList[i].profitAmount = this.skcList[i].profitAmount + item.profitAmount
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.skcList.push({
|
||||
productSkcId: item.productSkcId,
|
||||
skcExtCode: item.skcExtCode,
|
||||
saleAmount: item.saleAmount,
|
||||
saleCount: item.saleCount,
|
||||
costAmount: item.costAmount,
|
||||
profitAmount: item.profitAmount,
|
||||
profitPercent: item.profitPercent
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.skcList.map(item => {
|
||||
item.saleAmount = Math.round(item.saleAmount * 100) / 100
|
||||
item.costAmount = Math.round(item.costAmount * 100) / 100
|
||||
item.profitAmount = Math.round(item.profitAmount * 100) / 100
|
||||
})
|
||||
this.leftChartData.map(item => {
|
||||
if (item.type == '销售额') {
|
||||
this.saleAmount = this.saleAmount + item.value
|
||||
}
|
||||
if (item.type == '成本') {
|
||||
this.costAmount = this.costAmount + item.value
|
||||
}
|
||||
if (item.type == '利润') {
|
||||
this.profitAmount = this.profitAmount + item.value
|
||||
}
|
||||
if (item.type == '单量') {
|
||||
this.saleCount = this.saleCount + item.value
|
||||
}
|
||||
})
|
||||
this.saleAmount = Math.round(this.saleAmount * 100) / 100
|
||||
this.costAmount = Math.round(this.costAmount * 100) / 100
|
||||
this.profitAmount = Math.round(this.profitAmount * 100) / 100
|
||||
this.profitPercent = Math.round((this.saleAmount - this.costAmount) / this.saleAmount * 10000) / 100
|
||||
this.chartObj.changeData([this.leftChartData, this.rightChartData])
|
||||
this.isLoading = false
|
||||
},
|
||||
getPorductList() {
|
||||
this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.storeCode
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.productList = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
async getProductList() {
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'marvel-mms/cn/api/kiana/venom/sales/management/listWarehouse',
|
||||
needMallId: true,
|
||||
mallId: this.mallId,
|
||||
data: {
|
||||
pageNo: this.currentPage,
|
||||
pageSize: this.pageSize,
|
||||
isLack: 0,
|
||||
priceAdjustRecentDays: 7
|
||||
}})
|
||||
|
||||
if (res.errorCode == 1000000) {
|
||||
for(let i = 0;i < res.result.subOrderList.length; i++) {
|
||||
let item = res.result.subOrderList[i]
|
||||
let data = {}
|
||||
data.productName = item.productName
|
||||
data.productId = item.productId
|
||||
data.productSkcId = item.productSkcId
|
||||
data.skcExtCode = item.skcExtCode
|
||||
for(let j = 0;j < item.skuQuantityDetailList.length; j++) {
|
||||
data = {...data,
|
||||
skuExtCode: item.skuQuantityDetailList[j].skuExtCode,
|
||||
supplierPrice: item.skuQuantityDetailList[j].supplierPrice / 100,
|
||||
productSkuId: item.skuQuantityDetailList[j].productSkuId,
|
||||
className: item.skuQuantityDetailList[j].className
|
||||
}
|
||||
this.productList.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
if ((this.currentPage * this.pageSize) < res.result.total) {
|
||||
this.currentPage ++
|
||||
await this.getProductList()
|
||||
}
|
||||
} else {
|
||||
await this.getProductList()
|
||||
}
|
||||
},
|
||||
async getSkuSaleNumber (page) {
|
||||
let tempSkuId = []
|
||||
let i = page * 500
|
||||
let j = 0
|
||||
for (; i < this.productList.length; i++) {
|
||||
tempSkuId.push(this.productList[i].productSkuId)
|
||||
j ++
|
||||
if (j == 500) break
|
||||
}
|
||||
if (tempSkuId.length == 0) return
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'oms/bg/venom/api/supplier/sales/management/querySkuSalesNumber',
|
||||
needMallId: true,
|
||||
mallId: this.mallId,
|
||||
data: {
|
||||
productSkuIds: tempSkuId,
|
||||
startDate: this.dateRange[0],
|
||||
endDate: this.dateRange[1]
|
||||
}})
|
||||
if (res.errorCode == 1000000) {
|
||||
for (let i = 0; i < res.result.length; i++) {
|
||||
let cost = this.getCost(res.result[i].prodSkuId)
|
||||
|
||||
let flag = false
|
||||
// 计算每日销售额
|
||||
let skuObj = 0
|
||||
for (let k = 0; k < this.productList.length; k++) {
|
||||
if (this.productList[k].productSkuId == res.result[i].prodSkuId) {
|
||||
skuObj = this.productList[k]
|
||||
break
|
||||
}
|
||||
}
|
||||
for (let j = 0; j < this.leftChartData.length; j++) {
|
||||
if (this.leftChartData[j].type == '销售额' && this.leftChartData[j].day == res.result[i].date) {
|
||||
this.leftChartData[j].value = this.leftChartData[j].value + skuObj.supplierPrice * res.result[i].salesNumber
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.leftChartData.push({
|
||||
type: '销售额',
|
||||
value: skuObj.supplierPrice * res.result[i].salesNumber,
|
||||
day: res.result[i].date
|
||||
})
|
||||
}
|
||||
|
||||
// 计算每日销量
|
||||
flag = false
|
||||
for (let j = 0; j < this.leftChartData.length; j++) {
|
||||
if (this.leftChartData[j].type == '单量' && this.leftChartData[j].day == res.result[i].date) {
|
||||
this.leftChartData[j].value = this.leftChartData[j].value + res.result[i].salesNumber
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.leftChartData.push({
|
||||
type: '单量',
|
||||
value: res.result[i].salesNumber,
|
||||
day: res.result[i].date
|
||||
})
|
||||
}
|
||||
|
||||
// 计算每日成本
|
||||
flag = false
|
||||
for (let j = 0; j < this.leftChartData.length; j++) {
|
||||
if (this.leftChartData[j].type == '成本' && this.leftChartData[j].day == res.result[i].date) {
|
||||
this.leftChartData[j].value = this.leftChartData[j].value + cost * res.result[i].salesNumber
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.leftChartData.push({
|
||||
type: '成本',
|
||||
value: cost * res.result[i].salesNumber,
|
||||
day: res.result[i].date
|
||||
})
|
||||
}
|
||||
|
||||
// 计算每日利润
|
||||
flag = false
|
||||
for (let j = 0; j < this.leftChartData.length; j++) {
|
||||
if (this.leftChartData[j].type == '利润' && this.leftChartData[j].day == res.result[i].date) {
|
||||
this.leftChartData[j].value = this.leftChartData[j].value + (skuObj.supplierPrice - cost) * res.result[i].salesNumber
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.leftChartData.push({
|
||||
type: '利润',
|
||||
value: (skuObj.supplierPrice - cost) * res.result[i].salesNumber,
|
||||
day: res.result[i].date
|
||||
})
|
||||
}
|
||||
|
||||
// 计算SKU维度销售额
|
||||
flag = false
|
||||
for (let j = 0; j < this.skuList.length; j++) {
|
||||
if (this.skuList[j].productSkuId == res.result[i].prodSkuId) {
|
||||
this.skuList[j].saleAmount = this.skuList[j].saleAmount + skuObj.supplierPrice * res.result[i].salesNumber
|
||||
this.skuList[j].costAmount = this.skuList[j].costAmount + cost * res.result[i].salesNumber
|
||||
this.skuList[j].saleCount = this.skuList[j].saleCount + res.result[i].salesNumber
|
||||
this.skuList[j].profitAmount = this.skuList[j].profitAmount + (skuObj.supplierPrice - cost) * res.result[i].salesNumber
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.skuList.push({
|
||||
productSkcId: skuObj.productSkcId,
|
||||
productSkuId: skuObj.productSkuId,
|
||||
skcExtCode: skuObj.skcExtCode,
|
||||
skuExtCode: skuObj.skuExtCode,
|
||||
saleAmount: skuObj.supplierPrice * res.result[i].salesNumber,
|
||||
costAmount: cost * res.result[i].salesNumber,
|
||||
profitAmount: (skuObj.supplierPrice - cost) * res.result[i].salesNumber,
|
||||
saleCount: res.result[i].salesNumber,
|
||||
profitPercent: Math.round((skuObj.supplierPrice - cost) / skuObj.supplierPrice * 10000) / 100
|
||||
})
|
||||
}
|
||||
}
|
||||
await this.getSkuSaleNumber(page + 1)
|
||||
} else {
|
||||
await this.getSkuSaleNumber(page)
|
||||
}
|
||||
},
|
||||
async getSkuCostList() {
|
||||
let res = await this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.mallId
|
||||
}
|
||||
})
|
||||
if (res.code == 0) {
|
||||
this.productCostList = res.data
|
||||
}
|
||||
},
|
||||
getCost(sku) {
|
||||
for (let i = 0; i < this.productCostList.length; i++) {
|
||||
if (sku == this.productCostList[i].sku) {
|
||||
return this.productCostList[i].costPrice
|
||||
}
|
||||
}
|
||||
return 0
|
||||
},
|
||||
sleepSync(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
},
|
||||
async downloadPicture() {
|
||||
try {
|
||||
const element = document.getElementById('app-content');
|
||||
const canvas = await html2canvas(element);
|
||||
// 创建一个图片元素
|
||||
const img = new Image();
|
||||
img.src = canvas.toDataURL('image/png');
|
||||
// 添加到body中以便下载
|
||||
document.body.appendChild(img);
|
||||
// 触发下载
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none'
|
||||
a.href = img.src;
|
||||
a.download = '近60天销售统计.png';
|
||||
a.click();
|
||||
document.body.removeChild(img);
|
||||
} catch (error) {
|
||||
console.error('Error saving image:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
margin-right: 20px;
|
||||
padding: 16px 24px;
|
||||
background: #FFF;
|
||||
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
|
||||
border-radius: 4px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:nth-of-type(1) {
|
||||
color: #2266ff;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
color: #f8b426;
|
||||
}
|
||||
&:nth-of-type(3) {
|
||||
color: #21aa99;
|
||||
}
|
||||
&:nth-of-type(4) {
|
||||
color: #F46;
|
||||
}
|
||||
&:nth-of-type(5) {
|
||||
color: #11A265;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 30px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
p {
|
||||
font-weight: 600;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.like {
|
||||
cursor: pointer;
|
||||
font-size: 25px;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
@@ -6,15 +6,50 @@
|
||||
isShowBottomBorder>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<ai-card title="待补充证书列表" style="padding-bottom: 40px;">
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<el-radio-group v-model="certStatus" @change="getList">
|
||||
<el-radio-button label="refused">已驳回</el-radio-button>
|
||||
<el-radio-button label="waitUpload">待补充</el-radio-button>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template #right>
|
||||
<el-button type="primary" @click="exportToExcel">导出</el-button>
|
||||
</template>
|
||||
</ai-search-bar>
|
||||
<ai-card v-if="certStatus == 'refused'" title="已驳回证书列表" style="padding-bottom: 40px;">
|
||||
<template #right>
|
||||
<el-button type="primary" @click="exportRefusedToExcel">导出</el-button>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="list"
|
||||
:col-configs="colConfigs"
|
||||
height="600"
|
||||
:tableData="refusedList"
|
||||
:col-configs="refusedColConfigs"
|
||||
height="700"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
<el-table-column slot="auditStatus" width="120px" label="状态" align="left">
|
||||
<template slot-scope="scope">
|
||||
<div style="color: red">
|
||||
审批失败
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column slot="certName" label="证书名称" align="left">
|
||||
<template slot-scope="scope">
|
||||
<a v-for="item in scope.row.certName" :href="item.certificate_url" target="_blank">{{ item.certificate_url_name }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
<ai-card v-if="certStatus == 'waitUpload'" title="待补充证书列表" style="padding-bottom: 40px;">
|
||||
<template #right>
|
||||
<el-button type="primary" @click="exportWaitUploadToExcel">导出</el-button>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="waitUploadList"
|
||||
:col-configs="waitUploadColConfigs"
|
||||
height="700"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
@@ -36,9 +71,10 @@ import { saveAs } from 'file-saver'
|
||||
data () {
|
||||
return {
|
||||
isLoading: false,
|
||||
list: [],
|
||||
mallId: '',
|
||||
colConfigs: [
|
||||
certStatus: 'refused',
|
||||
waitUploadList: [],
|
||||
waitUploadColConfigs: [
|
||||
{ prop: 'spu', label: 'SPU', align: 'left' },
|
||||
{ prop: 'productName', label: '商品标题', align: 'left' },
|
||||
{ prop: 'skc', label: 'SKC ID', align: 'left' },
|
||||
@@ -46,7 +82,20 @@ import { saveAs } from 'file-saver'
|
||||
{ prop: 'certificateTypeName', label: '证书类型', align: 'left' },
|
||||
{ prop: 'mergeSiteName', label: '管控地区', align: 'left' },
|
||||
{ prop: 'subSite', label: '管控子站点', align: 'left' },
|
||||
{ slot: 'uploadEndTime', label: '上传截止时间', align: 'left' }
|
||||
{ prop: 'uploadEndTime', label: '上传截止时间', align: 'left' }
|
||||
],
|
||||
refusedList: [],
|
||||
refusedColConfigs: [
|
||||
{ prop: 'spu', label: 'SPU', align: 'left' },
|
||||
{ prop: 'productName', label: '商品标题', align: 'left' },
|
||||
{ prop: 'skc', label: 'SKC ID', align: 'left' },
|
||||
{ prop: 'mainAttrName', label: '主规格', align: 'left' },
|
||||
{ slot: 'auditStatus', label: '状态' },
|
||||
{ prop: 'certificateTypeName', label: '证书类型', align: 'left' },
|
||||
{ slot: 'certName', label: '证书名称' },
|
||||
{ prop: 'refusedReason', label: '审核备注', align: 'left' },
|
||||
{ prop: 'mergeSiteName', label: '管控地区', align: 'left' },
|
||||
{ prop: 'subSite', label: '管控子站点', align: 'left' }
|
||||
],
|
||||
|
||||
tableData: [],
|
||||
@@ -55,12 +104,33 @@ import { saveAs } from 'file-saver'
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.isLoading = true
|
||||
this.getList()
|
||||
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.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
async getList () {
|
||||
this.isLoading = true
|
||||
this.currentPage = 1
|
||||
if (this.certStatus == 'refused') {
|
||||
this.refusedList = []
|
||||
await this.getRefusedList()
|
||||
} else {
|
||||
this.waitUploadList = []
|
||||
await this.getWaitUploadList()
|
||||
}
|
||||
this.isLoading = false
|
||||
},
|
||||
async getWaitUploadList() {
|
||||
let res = await sendGeiwohuoAPIMessage({
|
||||
url: `spmp-api-prefix/spmp/certificate/get_skc_certificate_miss_list?page_num=${this.currentPage}&page_size=200`,
|
||||
method: 'POST',
|
||||
@@ -84,30 +154,95 @@ import { saveAs } from 'file-saver'
|
||||
subSite: subSite.join(',')
|
||||
}
|
||||
|
||||
this.list.push(data)
|
||||
this.waitUploadList.push(data)
|
||||
}
|
||||
if (res.info.data.length == 200 && (res.info.meta.count > 200*this.currentPage)) {
|
||||
this.currentPage++
|
||||
await this.sleepSync(200)
|
||||
await this.getList()
|
||||
} else {
|
||||
this.isLoading = false
|
||||
await this.getWaitUploadList()
|
||||
}
|
||||
} else if (res.code == 100004 || res.code == 20302) {
|
||||
this.isLoading = false
|
||||
this.$store.commit("setSheinAlertShow", true)
|
||||
}
|
||||
},
|
||||
async getRefusedList() {
|
||||
let res = await sendGeiwohuoAPIMessage({
|
||||
url: `spmp-api-prefix/spmp/certificate/get_skc_certificate_list?page_num=${this.currentPage}&page_size=200`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
audit_status: 3
|
||||
}})
|
||||
if (res.code == '0') {
|
||||
for(let i = 0;i < res.info.data.length; i++) {
|
||||
let item = res.info.data[i];
|
||||
let mainSite = []
|
||||
let subSite = []
|
||||
item.merge_site_info_list.map(e => {
|
||||
mainSite.push(e.merge_site_name)
|
||||
subSite = subSite.concat(e.sub_site_list)
|
||||
})
|
||||
let data = {
|
||||
pqmsCertificateSn: item.pqms_certificate_sn,
|
||||
auditStatus: item.audit_status,
|
||||
spu: item.spu_name,
|
||||
productName: item.skc_name_cn,
|
||||
skc: item.skc_name,
|
||||
mainAttrName: item.main_attribute_name,
|
||||
mergeSiteName: mainSite.join(','),
|
||||
certificateTypeName: item.certificate_type_name,
|
||||
certName: item.cert_file_list,
|
||||
refusedReason: null,
|
||||
subSite: subSite.join(',')
|
||||
}
|
||||
|
||||
this.refusedList.push(data)
|
||||
}
|
||||
if (res.info.data.length == 200 && (res.info.meta.count > 200*this.currentPage)) {
|
||||
this.currentPage++
|
||||
await this.sleepSync(200)
|
||||
await this.getRefusedList()
|
||||
} else {
|
||||
await this.getAuditInfo()
|
||||
}
|
||||
} else if (res.code == 100004 || res.code == 20302) {
|
||||
this.$store.commit("setSheinAlertShow", true)
|
||||
}
|
||||
},
|
||||
async getAuditInfo() {
|
||||
let pqmsList = []
|
||||
this.refusedList.map(item => {
|
||||
pqmsList.push(item.pqmsCertificateSn)
|
||||
})
|
||||
|
||||
let res = await sendGeiwohuoAPIMessage({
|
||||
url: `spmp-api-prefix/spmp/certificate/get_cert_audit_fail_reason`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
pqms_certificate_sn_list: pqmsList
|
||||
}})
|
||||
if (res.code == '0') {
|
||||
res.info.data.map(item => {
|
||||
for (let i = 0; i < this.refusedList.length; i++) {
|
||||
if (this.refusedList[i].pqmsCertificateSn == item.certificate_sn) {
|
||||
this.refusedList[i].refusedReason = item.fail_reason
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (res.code == 100004 || res.code == 20302) {
|
||||
this.$store.commit("setSheinAlertShow", true)
|
||||
}
|
||||
},
|
||||
sleepSync(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
},
|
||||
exportToExcel() {
|
||||
exportWaitUploadToExcel() {
|
||||
// 假设你有一个表格数据的数组
|
||||
const data = [
|
||||
["SPU", "商品标题", "SKC ID", "主规格", "证书类型", "管控地区", "管控子站点", "上传截止时间"]
|
||||
]
|
||||
|
||||
this.list.map(item => {
|
||||
this.waitUploadList.map(item => {
|
||||
data.push([item.spu, item.productName, item.skc, item.mainAttrName, item.certificateTypeName, item.mergeSiteName, item.subSite, item.uploadEndTime])
|
||||
})
|
||||
|
||||
@@ -128,6 +263,41 @@ import { saveAs } from 'file-saver'
|
||||
// 使用saveAs下载文件
|
||||
saveAs(dataBlob, '待补充证书列表.xlsx');
|
||||
|
||||
// 清理
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
},
|
||||
exportRefusedToExcel() {
|
||||
// 假设你有一个表格数据的数组
|
||||
const data = [
|
||||
["SPU", "商品标题", "SKC ID", "主规格", "证书类型","证书名称", "证书地址", "审核备注", "管控地区", "管控子站点"]
|
||||
]
|
||||
|
||||
this.refusedList.map(item => {
|
||||
let certName = [], certUrl = []
|
||||
item.certName.map(item1 => {
|
||||
certName.push(item1.certificate_url_name)
|
||||
certUrl.push(item1.certificate_url)
|
||||
})
|
||||
data.push([item.spu, item.productName, item.skc, item.mainAttrName, item.certificateTypeName, certName.join(','), certUrl.join(','), item.refusedReason, item.mergeSiteName, item.subSite])
|
||||
})
|
||||
|
||||
// 将数据转换为工作表
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
style="margin-top: 8px;"
|
||||
:current.sync="search.current" :size.sync="search.size"
|
||||
@selection-change="handleSelectionChange"
|
||||
height="700"
|
||||
@getList="getList">
|
||||
</ai-table>
|
||||
</div>
|
||||
@@ -140,7 +141,17 @@ import { Message } from 'element-ui'
|
||||
},
|
||||
|
||||
created () {
|
||||
this.getList()
|
||||
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.getList()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
@@ -179,9 +179,19 @@ import { saveAs } from 'file-saver'
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.getUserInfo()
|
||||
this.isLoading = true
|
||||
this.getList()
|
||||
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: {
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
ref="table0"
|
||||
:isShowPagination="false"
|
||||
:tableData="filteredData"
|
||||
height="500"
|
||||
height="700"
|
||||
:col-configs="colConfigs"
|
||||
:total="filteredData.length"
|
||||
style="margin-top: 8px;"
|
||||
@@ -134,7 +134,9 @@ import { Message } from 'element-ui'
|
||||
{prop: 'ableSaleDays',label: '可售天数',align: 'center'},
|
||||
{prop: 'cost',label: '价格',width: '120px',align: 'center'},
|
||||
{prop: 'costPrice',label: '成本',width: '120px',align: 'center'},
|
||||
{prop: 'todaySale',label: '今日销量',width: '120px',align: 'center'},
|
||||
{prop: 'todaySale',label: '今日销量',width: '120px',align: 'center',sortable: true,'sort-method': (a, b) => {
|
||||
return a.todaySale - b.todaySale
|
||||
}},
|
||||
{prop: 'todayProfit',label: '利润',width: '120px',align: 'center',sortable: true,'sort-method': (a, b) => {
|
||||
return a.todayProfit - b.todayProfit
|
||||
}},
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
<json-excel
|
||||
:data="skuList"
|
||||
:fields="skuJsonFields"
|
||||
name="SKC账单数据.xls"
|
||||
worksheet="SKC账单数据">
|
||||
name="SKU账单数据.xls"
|
||||
worksheet="SKU账单数据">
|
||||
<el-button type="primary" icon="el-icon-download">下载SKU统计</el-button>
|
||||
</json-excel>
|
||||
</div>
|
||||
@@ -310,7 +310,7 @@ import { DualAxes } from '@antv/g2plot'
|
||||
isLoading: false,
|
||||
|
||||
skcColConfigs: [
|
||||
{ prop: 'skcCode', label: '货号', width: '180px' },
|
||||
{ prop: 'skcCode', label: '货号', width: '250px' },
|
||||
{ slot: 'amount', label: '销售额', align: 'center' },
|
||||
{ prop: 'quantity', label: '单数', align: 'center' },
|
||||
{ prop: 'cost', label: '成本', align: 'center'},
|
||||
@@ -327,7 +327,7 @@ import { DualAxes } from '@antv/g2plot'
|
||||
"利润率": "profitPercent",
|
||||
},
|
||||
skuColConfigs: [
|
||||
{ prop: 'skuCode', label: '属性集', width: '220px' },
|
||||
{ prop: 'skuCode', label: '属性集', width: '250px' },
|
||||
{ slot: 'amount', label: '销售额', align: 'center' },
|
||||
{ prop: 'quantity', label: '单数', align: 'center' },
|
||||
{ prop: 'cost', label: '成本', align: 'center'},
|
||||
@@ -602,7 +602,6 @@ import { DualAxes } from '@antv/g2plot'
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(this.leftChartData)
|
||||
this.chartObj.changeData([this.leftChartData, this.rightChartData])
|
||||
this.isLoading = false
|
||||
}
|
||||
@@ -665,6 +664,9 @@ import { DualAxes } from '@antv/g2plot'
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else if (res2.code == 100004 || res2.code == 20302) {
|
||||
this.isLoading = false
|
||||
this.$store.commit("setSheinAlertShow", true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,36 @@
|
||||
</template>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<div class="search-item">
|
||||
<label>状态:</label>
|
||||
<el-select v-model="form.status" multiple placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label style="width:120px">备货单创建时间:</label>
|
||||
<el-date-picker
|
||||
v-model="form.date"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
</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>
|
||||
<label style="width:80px">状态:</label>
|
||||
<el-select v-model="form.status" multiple placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<label style="width:120px">备货单创建时间:</label>
|
||||
<el-date-picker
|
||||
v-model="form.date"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
<el-button type="primary" @click="toLoad">加载</el-button>
|
||||
<json-excel
|
||||
:data="tableData"
|
||||
:fields="jsonFields"
|
||||
@@ -59,6 +69,26 @@
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
<ai-card title="数据统计" style="padding-bottom: 40px;">
|
||||
<template #right>
|
||||
<json-excel
|
||||
:data="sumTableData"
|
||||
:fields="sumJsonFields"
|
||||
name="普通备货单统计.xls"
|
||||
worksheet="普通备货单统计">
|
||||
<el-button type="primary" :disabled="sumTableData.length == 0">下载数据</el-button>
|
||||
</json-excel>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="sumTableData"
|
||||
:col-configs="sumColConfigs"
|
||||
:total="sumTableData.length"
|
||||
height="500"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
@@ -116,6 +146,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' },
|
||||
{ prop: 'purchaseQuantity', label: '备货件数', width: '100px', align: 'left' },
|
||||
{ prop: 'xiadan', label: '送货数量', width: '100px', align: 'left' },
|
||||
{ prop: 'skuNum', label: '入库数量', width: '100px', align: 'left' },
|
||||
@@ -123,8 +154,25 @@ import JsonExcel from 'vue-json-excel'
|
||||
{ prop: 'deliverTime', label: '发货时间', width: '160px', align: 'left' },
|
||||
{ prop: 'receiveTime', label: '收货时间', width: '160px', align: 'left' }
|
||||
],
|
||||
sumTableData: [],
|
||||
sumColConfigs: [
|
||||
{ prop: 'productName', label: '商品名称', width: '240px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'productSkcId', label: 'SKC ID', width: '120px', align: 'left' },
|
||||
{ prop: 'skcExtCode', label: 'SKC货号', width: '100px', align: 'left' },
|
||||
{ prop: 'productSkuId', label: 'SKU ID', width: '120px', align: 'left' },
|
||||
{ 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: 'purchaseQuantity', label: '备货总件数', width: '100px', align: 'left', sortable: true, 'sort-method': (a, b) => a.purchaseQuantity - b.purchaseQuantity },
|
||||
{ prop: 'xiadan', label: '送货总数量', width: '100px', align: 'left', sortable: true, 'sort-method': (a, b) => a.xiadan - b.xiadan },
|
||||
{ prop: 'skuNum', label: '实际入库总数量', width: '100px', align: 'left', sortable: true, 'sort-method': (a, b) => a.skuNum - b.skuNum },
|
||||
{ prop: 'costAmount', label: '成本总额', width: '140px', align: 'left', sortable: true, 'sort-method': (a, b) => a.costAmount - b.costAmount },
|
||||
{ prop: 'profit', label: '预计利润总额', width: '160px', align: 'left', sortable: true, 'sort-method': (a, b) => a.profit - b.profit },
|
||||
],
|
||||
isLoading: false,
|
||||
tableData: [],
|
||||
costList: [],
|
||||
jsonFields: {
|
||||
"备货单创建时间": "purchaseTime",
|
||||
"备货单号": "subPurchaseOrderSn",
|
||||
@@ -137,6 +185,7 @@ import JsonExcel from 'vue-json-excel'
|
||||
"SKU货号": "extCode",
|
||||
"SKU属性": "specName",
|
||||
"申报价格(CNY)": "supplierPrice",
|
||||
"成本价格(CNY)": "cost",
|
||||
"备货件数": "purchaseQuantity",
|
||||
"下单数量": "xiadan",
|
||||
"实际入库数量": "skuNum",
|
||||
@@ -144,7 +193,22 @@ import JsonExcel from 'vue-json-excel'
|
||||
"发货时间": "deliverTime",
|
||||
"收货时间": "receiveTime"
|
||||
},
|
||||
snList: [],
|
||||
sumJsonFields: {
|
||||
"商品名称": "productName",
|
||||
"商品图片": "productSkcPicture",
|
||||
"SKC ID": "productSkcId",
|
||||
"SKC货号": "skcExtCode",
|
||||
"SKU ID": "productSkuId",
|
||||
"SKU货号": "extCode",
|
||||
"SKU属性": "specName",
|
||||
"申报价格(CNY)": "supplierPrice",
|
||||
"成本价格(CNY)": "cost",
|
||||
"备货总件数": "purchaseQuantity",
|
||||
"送货总数量": "xiadan",
|
||||
"实际入库总数量": "skuNum",
|
||||
"成本总额": "costAmount",
|
||||
"预计利润总额": "profit"
|
||||
},
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
@@ -168,64 +232,123 @@ import JsonExcel from 'vue-json-excel'
|
||||
Message.error("请选择时间")
|
||||
return
|
||||
}
|
||||
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.sumTableData = []
|
||||
this.packageNumber = 0
|
||||
this.snList = []
|
||||
this.currentIndex = 0
|
||||
this.costList = []
|
||||
this.isLoading = true
|
||||
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,
|
||||
purchaseQuantity: item.skuQuantityDetailList[k].purchaseQuantity,
|
||||
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,
|
||||
purchaseQuantity: item.skuQuantityDetailList[k].purchaseQuantity,
|
||||
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.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 ++
|
||||
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,
|
||||
purchaseQuantity: item.purchaseQuantity,
|
||||
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
|
||||
}
|
||||
}
|
||||
},
|
||||
async getSkuCostList() {
|
||||
let res = await this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.form.mallId
|
||||
}
|
||||
})
|
||||
if (res.code == 0) {
|
||||
this.costList = res.data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,36 @@
|
||||
</template>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<div class="search-item">
|
||||
<label>状态:</label>
|
||||
<el-select v-model="form.status" multiple placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label style="width:120px">备货单创建时间:</label>
|
||||
<el-date-picker
|
||||
v-model="form.date"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
</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>
|
||||
<label style="width:80px">状态:</label>
|
||||
<el-select v-model="form.status" multiple placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<label style="width:120px">备货单创建时间:</label>
|
||||
<el-date-picker
|
||||
v-model="form.date"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
<el-button type="primary" @click="toLoad">加载</el-button>
|
||||
<json-excel
|
||||
:data="tableData"
|
||||
:fields="jsonFields"
|
||||
@@ -59,6 +69,26 @@
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
<ai-card title="数据统计" style="padding-bottom: 40px;">
|
||||
<template #right>
|
||||
<json-excel
|
||||
:data="sumTableData"
|
||||
:fields="sumJsonFields"
|
||||
name="紧急备货单统计.xls"
|
||||
worksheet="紧急备货单统计">
|
||||
<el-button type="primary" :disabled="sumTableData.length == 0">下载数据</el-button>
|
||||
</json-excel>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="sumTableData"
|
||||
:col-configs="sumColConfigs"
|
||||
:total="sumTableData.length"
|
||||
height="500"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
@@ -123,8 +153,24 @@ import JsonExcel from 'vue-json-excel'
|
||||
{ prop: 'deliverTime', label: '发货时间', width: '160px', align: 'left' },
|
||||
{ prop: 'receiveTime', label: '收货时间', width: '160px', align: 'left' }
|
||||
],
|
||||
sumTableData: [],
|
||||
sumColConfigs: [
|
||||
{ prop: 'productName', label: '商品名称', width: '240px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'productSkcId', label: 'SKC ID', width: '120px', align: 'left' },
|
||||
{ prop: 'skcExtCode', label: 'SKC货号', width: '100px', align: 'left' },
|
||||
{ prop: 'productSkuId', label: 'SKU ID', width: '120px', align: 'left' },
|
||||
{ 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', sortable: true, 'sort-method': (a, b) => a.xiadan - b.xiadan },
|
||||
{ prop: 'skuNum', label: '实际入库总数量', width: '100px', align: 'left', sortable: true, 'sort-method': (a, b) => a.skuNum - b.skuNum },
|
||||
{ prop: 'costAmount', label: '成本总额', width: '140px', align: 'left', sortable: true, 'sort-method': (a, b) => a.costAmount - b.costAmount },
|
||||
{ prop: 'profit', label: '预计利润总额', width: '160px', align: 'left', sortable: true, 'sort-method': (a, b) => a.profit - b.profit },
|
||||
],
|
||||
isLoading: false,
|
||||
tableData: [],
|
||||
costList: [],
|
||||
jsonFields: {
|
||||
"备货单创建时间": "purchaseTime",
|
||||
"备货单号": "subPurchaseOrderSn",
|
||||
@@ -143,7 +189,21 @@ import JsonExcel from 'vue-json-excel'
|
||||
"发货时间": "deliverTime",
|
||||
"收货时间": "receiveTime"
|
||||
},
|
||||
snList: [],
|
||||
sumJsonFields: {
|
||||
"商品名称": "productName",
|
||||
"商品图片": "productSkcPicture",
|
||||
"SKC ID": "productSkcId",
|
||||
"SKC货号": "skcExtCode",
|
||||
"SKU ID": "productSkuId",
|
||||
"SKU货号": "extCode",
|
||||
"SKU属性": "specName",
|
||||
"申报价格(CNY)": "supplierPrice",
|
||||
"成本价格(CNY)": "cost",
|
||||
"送货总数量": "xiadan",
|
||||
"实际入库总数量": "skuNum",
|
||||
"成本总额": "costAmount",
|
||||
"预计利润总额": "profit"
|
||||
},
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
@@ -167,13 +227,14 @@ import JsonExcel from 'vue-json-excel'
|
||||
Message.error("请选择时间")
|
||||
return
|
||||
}
|
||||
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.packageNumber = 0
|
||||
this.snList = []
|
||||
this.currentIndex = 0
|
||||
this.isLoading = true
|
||||
this.load()
|
||||
@@ -220,10 +281,59 @@ import JsonExcel from 'vue-json-excel'
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
async getSkuCostList() {
|
||||
let res = await this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.form.mallId
|
||||
}
|
||||
})
|
||||
if (res.code == 0) {
|
||||
this.costList = res.data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
this.isDlgLoading = true
|
||||
this.getList(this.tableData, this.mallId, this.mallName, 1)
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
@@ -688,11 +689,19 @@
|
||||
this.createDeliveryBill(sn, mallId)
|
||||
}
|
||||
} else {
|
||||
this.choosedSnMallList.push(obj)
|
||||
for (let j = 0; j < this.choosedList.length; j++) {
|
||||
if (this.choosedList[j].subPurchaseOrderSn == sn) {
|
||||
this.choosedList[j].robTotal ++;
|
||||
break;
|
||||
if (res.result?.errorInfoList[0] && res.result?.errorInfoList[0].errorCode == 60002) {
|
||||
for (let j = 0; j < this.choosedList.length; j++) {
|
||||
if (this.choosedList[j].subPurchaseOrderSn == sn) {
|
||||
this.choosedList.splice(j, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.choosedSnMallList.push(obj)
|
||||
for (let j = 0; j < this.choosedList.length; j++) {
|
||||
if (this.choosedList[j].subPurchaseOrderSn == sn) {
|
||||
this.choosedList[j].robTotal ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
237
src/view/shipping/ProductLabel.vue
Normal file
237
src/view/shipping/ProductLabel.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="商品条码管理"
|
||||
tips="每页为100条商品数据"
|
||||
isShowBottomBorder>
|
||||
<template #rightBtn>
|
||||
<div class="title-right">
|
||||
<div>
|
||||
<label style="width:90px">店铺:</label>
|
||||
<el-select v-model="form.mallId" placeholder="请选择" size="small">
|
||||
<el-option
|
||||
v-for="item in $store.state.mallList"
|
||||
:key="item.mallId"
|
||||
:label="item.mallName"
|
||||
:value="item.mallId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<div class="content">
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<div class="search-item">
|
||||
<label>起始页:</label>
|
||||
<el-input size="small" placeholder="请输入起始页" type="number" v-model="startPage"></el-input>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>结束页:</label>
|
||||
<el-input size="small" placeholder="请输入起始页" type="number" v-model="endPage"></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" :disabled="tableData.length == 0" @click="exportWaitUploadToExcel">导出</el-button>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="tableData"
|
||||
:col-configs="colConfigs"
|
||||
:total="tableData.length"
|
||||
height="700"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
|
||||
<el-table-column slot="productName" width="300px" :show-overflow-tooltip='true' label="商品名称" fixed="left">
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
<el-image :src="scope.row.mainImageUrl" style="width: 40px; height: 40px" class="image" :preview-src-list="[scope.row.mainImageUrl]" />
|
||||
{{ scope.row.productName }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</div>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
|
||||
<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'
|
||||
|
||||
export default {
|
||||
name: 'ProductLabel',
|
||||
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
mallId: ''
|
||||
},
|
||||
startPage: 1,
|
||||
endPage: 10,
|
||||
reqData: {
|
||||
page: 1,
|
||||
pageSize: 100
|
||||
},
|
||||
colConfigs: [
|
||||
{ slot: 'productName', label: '商品名称', width: '300px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'category', label: '分类', width: '140px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'labelCode', label: '条码编码', align: 'left' },
|
||||
{ prop: 'productSkcId', label: 'SKC', align: 'left' },
|
||||
{ prop: 'productSkuId', label: 'SKU', align: 'left' },
|
||||
{ prop: 'extCode', label: 'SKC货号', align: 'left' },
|
||||
{ prop: 'skuExtCode', label: 'SKU货号', align: 'left' },
|
||||
{ prop: 'skcSpecName', label: '主销售属性', align: 'left' },
|
||||
{ prop: 'skuSpecName', label: '次销售属性', width: '100px', align: 'left' }
|
||||
],
|
||||
isLoading: false,
|
||||
tableData: [],
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
beforeGetList() {
|
||||
this.$userCheck(this.form.mallId).then(() => {
|
||||
this.toLoad()
|
||||
}).catch((err) => {
|
||||
this.form.mallId = ''
|
||||
})
|
||||
},
|
||||
toLoad() {
|
||||
if (!this.form.mallId) {
|
||||
Message.error("请选择店铺")
|
||||
return
|
||||
}
|
||||
if (!this.startPage || (this.startPage < 1)) {
|
||||
Message.error("起始页不能为空,且不能小于1")
|
||||
return
|
||||
}
|
||||
if (!this.endPage || (this.startPage < 1)) {
|
||||
Message.error("结束页不能为空")
|
||||
return
|
||||
}
|
||||
if (this.startPage > this.endPage) {
|
||||
Message.error("起始页不能大于结束页")
|
||||
return
|
||||
}
|
||||
this.$userCheck(this.form.mallId).then(() => {
|
||||
this.reqData.page = this.startPage
|
||||
this.tableData = []
|
||||
this.currentIndex = 0
|
||||
this.isLoading = true
|
||||
this.load()
|
||||
}).catch((err) => {
|
||||
this.form.mallId = ''
|
||||
})
|
||||
},
|
||||
load() {
|
||||
sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/labelcode/pageQuery',
|
||||
needMallId: true,
|
||||
mallId: this.form.mallId,
|
||||
anti: true,
|
||||
data: this.reqData}).then((res) => {
|
||||
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
|
||||
|
||||
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(',')
|
||||
|
||||
this.tableData.push(data)
|
||||
|
||||
}
|
||||
if (res.result.pageItems.length == this.reqData.pageSize && this.reqData.page < this.endPage) {
|
||||
this.reqData.page ++
|
||||
this.load()
|
||||
} else {
|
||||
this.isLoading = false
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
exportWaitUploadToExcel() {
|
||||
// 假设你有一个表格数据的数组
|
||||
const data = [
|
||||
["商品名称", "分类", "条码编码", "SKC","SKU", "SKC货号", "SKU货号", "主销售属性", "次销售属性"]
|
||||
]
|
||||
|
||||
this.tableData.map(item => {
|
||||
data.push([item.productName, item.category, item.labelCode, item.productSkcId, item.productSkuId, item.extCode, item.skuExtCode, item.skcSpecName, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
@@ -256,6 +256,7 @@
|
||||
this.isDlgLoading = true
|
||||
this.getList(this.tableData, this.mallId, this.mallName, 1)
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
this.isDlgLoading = true
|
||||
this.getList(this.tableData, this.mallId, this.mallName, 1)
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -123,6 +123,7 @@ import { Message } from 'element-ui'
|
||||
this.skcIds = []
|
||||
this.getList()
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -121,6 +121,7 @@ import { Message } from 'element-ui'
|
||||
this.isLoading = true
|
||||
this.getList()
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
</json-excel>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="tableData"
|
||||
:col-configs="colConfigs"
|
||||
:total="total"
|
||||
@@ -70,6 +71,26 @@
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
<ai-card title="数据统计" style="padding-bottom: 40px;">
|
||||
<template #right>
|
||||
<json-excel
|
||||
:data="sumTableData"
|
||||
:fields="sumJsonFields"
|
||||
name="退货统计.xls"
|
||||
worksheet="退货统计">
|
||||
<el-button type="primary" :disabled="sumTableData.length == 0">下载数据</el-button>
|
||||
</json-excel>
|
||||
</template>
|
||||
<ai-table
|
||||
:isShowPagination="false"
|
||||
:tableData="sumTableData"
|
||||
:col-configs="sumColConfigs"
|
||||
:total="sumTableData.length"
|
||||
height="500"
|
||||
style="margin-top: 8px;"
|
||||
@getList="() => {}">
|
||||
</ai-table>
|
||||
</ai-card>
|
||||
</div>
|
||||
</template>
|
||||
</ai-list>
|
||||
@@ -98,8 +119,18 @@ import { Message } from 'element-ui'
|
||||
{ prop: 'orderTypeDesc', label: '退货原因',width: '220px', align: 'left' },
|
||||
{ prop: 'packageSn', label: '退货包裹号', width: '200px',align: 'left' },
|
||||
{ prop: 'quantity', label: 'SKU件数',width: '100px', },
|
||||
{ prop: 'cost', label: '成本单价' },
|
||||
{ prop: 'outboundTime', label: '出库时间', width: '160px'}
|
||||
],
|
||||
sumColConfigs: [
|
||||
{ prop: 'productSkcId', label: 'SKC', align: 'left', fixed: 'left' },
|
||||
{ prop: 'productSkuId', label: 'SKU', align: 'left', fixed: 'left' },
|
||||
{ prop: 'skuExtCode', label: 'SKU属性', align: 'left', fixed: 'left' },
|
||||
{ prop: 'secondarySaleSpec', label: '属性集', align: 'left', fixed: 'left' },
|
||||
{ prop: 'quantity', label: 'SKU总件数', sortable: true, 'sort-method': (a, b) => a.quantity - b.quantity },
|
||||
{ prop: 'costPrice', label: '成本价', sortable: true, 'sort-method': (a, b) => a.costPrice - b.costPrice},
|
||||
{ prop: 'costAmount', label: '成本总额', sortable: true, 'sort-method': (a, b) => a.costAmount - b.costAmount}
|
||||
],
|
||||
jsonFields: {
|
||||
"SPU": "productSpuId",
|
||||
"SKC": "productSkcId",
|
||||
@@ -112,8 +143,19 @@ import { Message } from 'element-ui'
|
||||
"退货原因": "orderTypeDesc",
|
||||
"退货包裹号": "packageSn",
|
||||
"SKU件数": "quantity",
|
||||
"成本单价": "cost",
|
||||
"出库时间": "outboundTime"
|
||||
},
|
||||
sumJsonFields: {
|
||||
"SKC": "productSkcId",
|
||||
"SKU": "productSkuId",
|
||||
"SKU属性": "skuExtCode",
|
||||
"图片地址": "thumbUrl",
|
||||
"属性集": "secondarySaleSpec",
|
||||
"SKU总件数": "quantity",
|
||||
"成本价": "costPrice",
|
||||
"成本总额": "costAmount"
|
||||
},
|
||||
form: {
|
||||
mallId: '',
|
||||
date: ''
|
||||
@@ -122,6 +164,8 @@ import { Message } from 'element-ui'
|
||||
pageSize: 100,
|
||||
|
||||
tableData: [],
|
||||
sumTableData: [],
|
||||
costList: [],
|
||||
total: 0,
|
||||
search: {
|
||||
current: 1,
|
||||
@@ -163,6 +207,7 @@ import { Message } from 'element-ui'
|
||||
}
|
||||
this.currentPage = 1
|
||||
this.tableData = []
|
||||
this.sumTableData = []
|
||||
|
||||
let startTime = this.form.date[1].getTime() - 30 * 24 * 60 * 60 * 1000
|
||||
if (startTime < this.form.date[0].getTime()) {
|
||||
@@ -196,6 +241,7 @@ import { Message } from 'element-ui'
|
||||
data.packageSn = item.packageSn
|
||||
data.quantity = item.quantity
|
||||
data.outboundTime = timestampToTime(item.outboundTime)
|
||||
data.cost = null
|
||||
|
||||
this.tableData.push(data)
|
||||
}
|
||||
@@ -215,7 +261,8 @@ import { Message } from 'element-ui'
|
||||
this.getList(startTimeTemp, endTimeTemp)
|
||||
} else {
|
||||
this.getDeliverySn(1)
|
||||
this.getSkuExtCode(1)
|
||||
|
||||
this.getSkuCostList()
|
||||
this.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -288,6 +335,58 @@ import { Message } from 'element-ui'
|
||||
await getSkuExtCode(pageNo + 1)
|
||||
}
|
||||
},
|
||||
calcAmount() {
|
||||
this.tableData.map(item => {
|
||||
for (let i = 0; i < this.costList.length; i++) {
|
||||
if (item.productSkuId == this.costList[i].sku) {
|
||||
item.cost = this.costList[i].costPrice
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let flag = false
|
||||
for (let i = 0; i < this.sumTableData.length; i++) {
|
||||
if (item.productSkuId == this.sumTableData[i].productSkuId) {
|
||||
this.sumTableData[i].quantity += item.quantity
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
this.sumTableData.push({
|
||||
productSkcId: item.productSkcId,
|
||||
productSkuId: item.productSkuId,
|
||||
skuExtCode: item.skuExtCode,
|
||||
secondarySaleSpec: item.secondarySaleSpec,
|
||||
thumbUrl: item.thumbUrl,
|
||||
quantity: item.quantity,
|
||||
costPrice: null,
|
||||
costAmount: null
|
||||
})
|
||||
}
|
||||
})
|
||||
this.sumTableData.map(item => {
|
||||
for (let i = 0; i < this.costList.length; i++) {
|
||||
if (this.costList[i].sku == item.productSkuId) {
|
||||
item.costPrice = this.costList[i].costPrice
|
||||
item.costAmount = Math.round(this.costList[i].costPrice * item.quantity * 100) / 100
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
async getSkuCostList() {
|
||||
await this.getSkuExtCode(1)
|
||||
let res = await this.$http.post(`/api/skuCost/listAll`, null, {
|
||||
params: {
|
||||
mallId: this.form.mallId
|
||||
}
|
||||
})
|
||||
if (res.code == 0) {
|
||||
this.costList = res.data
|
||||
this.calcAmount()
|
||||
}
|
||||
},
|
||||
startDownload() {
|
||||
this.$http.post('/api/malluser/info').then(res => {
|
||||
if (res.code == 0) {
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
:tableData="tableData"
|
||||
:col-configs="colConfigs"
|
||||
:total="total"
|
||||
height="500"
|
||||
height="700"
|
||||
style="margin-top: 8px;"
|
||||
@getList="getList">
|
||||
</ai-table>
|
||||
|
||||
39
yarn.lock
39
yarn.lock
@@ -492,6 +492,11 @@
|
||||
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.22.10.tgz"
|
||||
integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==
|
||||
|
||||
"@babel/parser@^7.23.5":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f"
|
||||
integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz"
|
||||
@@ -1848,6 +1853,17 @@
|
||||
postcss "^8.4.14"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-sfc@2.7.16":
|
||||
version "2.7.16"
|
||||
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz#ff81711a0fac9c68683d8bb00b63f857de77dc83"
|
||||
integrity sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.23.5"
|
||||
postcss "^8.4.14"
|
||||
source-map "^0.6.1"
|
||||
optionalDependencies:
|
||||
prettier "^1.18.2 || ^2.0.0"
|
||||
|
||||
"@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.npmmirror.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz"
|
||||
@@ -2378,6 +2394,16 @@ batch@0.6.1:
|
||||
resolved "https://registry.npmmirror.com/batch/-/batch-0.6.1.tgz"
|
||||
integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
|
||||
|
||||
bi-vue-mindmap@^0.6.12:
|
||||
version "0.6.12"
|
||||
resolved "https://registry.npmmirror.com/bi-vue-mindmap/-/bi-vue-mindmap-0.6.12.tgz#092202bd224ed49dd133a1c6490fe7330848a280"
|
||||
integrity sha512-cKfKB5rm3L+391iV9RPkfC8lIKx9xAhW6shpGnXHPwZcboIpW+ZjPpq2vaJ0qlXH96i4VMW2Xk6StBMVRQ2GDw==
|
||||
dependencies:
|
||||
core-js "^3.6.5"
|
||||
vue "^2.6.11"
|
||||
vue-router "^3.2.0"
|
||||
vuex "^3.4.0"
|
||||
|
||||
big.js@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz"
|
||||
@@ -2955,6 +2981,11 @@ core-js@^2.4.0:
|
||||
resolved "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.6.5:
|
||||
version "3.37.1"
|
||||
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9"
|
||||
integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==
|
||||
|
||||
core-js@^3.8.3:
|
||||
version "3.32.0"
|
||||
resolved "https://registry.npmmirror.com/core-js/-/core-js-3.32.0.tgz"
|
||||
@@ -7536,6 +7567,14 @@ vue-template-es2015-compiler@^1.9.0:
|
||||
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz"
|
||||
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
||||
|
||||
vue@^2.6.11:
|
||||
version "2.7.16"
|
||||
resolved "https://registry.npmmirror.com/vue/-/vue-2.7.16.tgz#98c60de9def99c0e3da8dae59b304ead43b967c9"
|
||||
integrity sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==
|
||||
dependencies:
|
||||
"@vue/compiler-sfc" "2.7.16"
|
||||
csstype "^3.1.0"
|
||||
|
||||
vue@^2.6.14:
|
||||
version "2.7.14"
|
||||
resolved "https://registry.npmmirror.com/vue/-/vue-2.7.14.tgz"
|
||||
|
||||
Reference in New Issue
Block a user