diff --git a/package.json b/package.json index 6848310..dc30477 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "crypto-js": "^4.0.0", "dayjs": "^1.11.9", "element-ui": "^2.15.13", + "file-saver": "^2.0.5", + "html2canvas": "^1.4.1", "query-string": "^9.0.0", "spark-md5": "^3.0.2", "v-viewer": "^1.6.4", @@ -22,7 +24,8 @@ "vue-qr": "^4.0.9", "vue-router": "^3.2.0", "vuex": "^3.4.0", - "vuex-persistedstate": "^4.1.0" + "vuex-persistedstate": "^4.1.0", + "xlsx": "^0.18.5" }, "devDependencies": { "@babel/core": "^7.12.16", diff --git a/public/js/download.js b/public/js/download.js index 0453bee..142dc60 100644 --- a/public/js/download.js +++ b/public/js/download.js @@ -1,3 +1,8 @@ +function matchSheinDomain(url) { + const urlPattern = /https:\/\/([\da-z\.-]+)\.shein\.com\/([\S.-]+)-p-([\S.-]+)/ + return urlPattern.test(url); +} + function init() { if (window.location.href.startsWith('https://www.aliexpress.com/item/')) { const popup = document.createElement("div") @@ -187,6 +192,111 @@ function init() { }) document.body.appendChild(popup) } + } else if (matchSheinDomain(window.location.href)) { + const popup = document.createElement("div") + popup.innerText = "下载图片" + const styles = { + position: "fixed", + right: '10px', + top: '60px', + zIndex: 9999, + padding: "8px", + background: "#409EFF", + color: "#fff", + borderRadius: "8px", + cursor: "pointer" + } + for (const e in styles) { + popup.style[e] = styles[e] + } + + popup.addEventListener('click', async () => { + var baseList = []; + var downloadList = [] + + let bannerIdx = 1, detailIdx = 1 + baseList.push({type: 0, index: bannerIdx++, src: window.gbRawData.productIntroData.goods_imgs.main_image.origin_image}) + var detailImages = window.gbRawData.productIntroData.goods_imgs.detail_image + + for (var i = 0; i < detailImages.length; i++) { + if (!(detailImages[i].isMoreDetail)) { + baseList.push({type: 0, index: bannerIdx++, src: detailImages[i].origin_image}) + } else { + baseList.push({type: 1, index: detailIdx++, src: detailImages[i].origin_image}) + } + } + + var video = document.querySelector('video') + if (window.gbRawData.productIntroData.goods_imgs.video_url) { + baseList.push({type: 2, index: 1, src: window.gbRawData.productIntroData.goods_imgs.video_url}) + } + + var zip = new JSZip(); + var imgsBanner = zip.folder("轮播图"); + var imgsDetail = zip.folder("详情图"); + var videos = zip.folder("视频"); + + for (var k = 0; k < baseList.length; k++) { + let type = baseList[k].type + let index = baseList[k].index + if (type == 2) { + let x = new XMLHttpRequest() + x.open('GET', baseList[k].src, true) + x.responseType = 'blob' + x.onload = (e) => { + downloadList.push({type: type, index: index, data: x.response}); + if (downloadList.length === baseList.length && downloadList.length > 0) { + for (let l = 0; l < downloadList.length; l++) { + if (downloadList[l].type == '0') { + imgsDetail.file(`详情图${downloadList[l].index}.png`, downloadList[l].data, { base64: true }); + } else if (downloadList[l].type == '1') { + imgsBanner.file(`轮播图${downloadList[l].index}.png`, downloadList[l].data, { base64: true }); + } else if (downloadList[l].type == '2') { + videos.file(`视频.mp4`, downloadList[l].data, { Blob: true }); + } + } + zip.generateAsync({ type: "blob" }).then(function (content) { + // see FileSaver.js + saveAs(content, "shein_" + id + ".zip"); + }); + } + } + x.send() + } else { + let image = new Image(); + // 解决跨域 Canvas 污染问题 + image.setAttribute("crossOrigin", "anonymous"); + image.onload = function () { + let canvas = document.createElement("canvas"); + canvas.width = image.width; + canvas.height = image.height; + let context = canvas.getContext("2d"); + context.drawImage(image, 0, 0, image.width, image.height); + let url = canvas.toDataURL(); // 得到图片的base64编码数据 + canvas.toDataURL("image/png"); + downloadList.push({type: type, index: index, data: url.substring(22)}); // 去掉base64编码前的 data:image/png;base64, + if (downloadList.length === baseList.length && downloadList.length > 0) { + for (let l = 0; l < downloadList.length; l++) { + if (downloadList[l].type == '0') { + imgsDetail.file(`详情图${downloadList[l].index}.png`, downloadList[l].data, { base64: true }); + } else if (downloadList[l].type == '1') { + imgsBanner.file(`轮播图${downloadList[l].index}.png`, downloadList[l].data, { base64: true }); + } else if (downloadList[l].type == '2') { + videos.file(`视频.mp4`, downloadList[l].data, { Blob: true }); + } + } + zip.generateAsync({ type: "blob" }).then(function (content) { + // see FileSaver.js + saveAs(content, "shein_" + id + ".zip"); + }); + } + }; + image.src = baseList[k].src; + } + } + }) + document.body.appendChild(popup) + } } diff --git a/public/rules_7.json b/public/rules_7.json new file mode 100644 index 0000000..b4c61d0 --- /dev/null +++ b/public/rules_7.json @@ -0,0 +1,29 @@ +[ + { + "id": 18, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "Origin", + "operation": "set", + "value": "https://img.ltwebstatic.com" + }, + { + "header": "Referer", + "operation": "set", + "value": "https://img.ltwebstatic.com" + }, + { + "header": "Sec-Fetch-Mode", + "operation": "set", + "value": "no-cors" + } + ] + }, + "condition": { + "urlFilter": "||img.ltwebstatic.com" + } + } +] \ No newline at end of file diff --git a/public/rules_8.json b/public/rules_8.json new file mode 100644 index 0000000..1efbc83 --- /dev/null +++ b/public/rules_8.json @@ -0,0 +1,24 @@ +[ + { + "id": 19, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "Origin", + "operation": "set", + "value": "https://www.geiwohuo.com/" + }, + { + "header": "Referer", + "operation": "set", + "value": "https://www.geiwohuo.com/" + } + ] + }, + "condition": { + "urlFilter": "||www.geiwohuo.com" + } + } +] \ No newline at end of file diff --git a/public/rules_9.json b/public/rules_9.json new file mode 100644 index 0000000..c78d649 --- /dev/null +++ b/public/rules_9.json @@ -0,0 +1,24 @@ +[ + { + "id": 20, + "priority": 1, + "action": { + "type": "modifyHeaders", + "requestHeaders": [ + { + "header": "Origin", + "operation": "set", + "value": "https://agentseller.temu.com/" + }, + { + "header": "Referer", + "operation": "set", + "value": "https://agentseller.temu.com/" + } + ] + }, + "condition": { + "urlFilter": "||agentseller.temu.com" + } + } +] \ No newline at end of file diff --git a/src/api/chromeApi.js b/src/api/chromeApi.js index c37d080..36368b0 100644 --- a/src/api/chromeApi.js +++ b/src/api/chromeApi.js @@ -26,6 +26,32 @@ export async function sendChromeAPIMessage(message) { }) } + +/** + * 向Chrome发送消息 + * @param message 消息 + */ +export async function sendTemuSellerAgentMessage(message) { + message.type = 'api' + if (!message.url.startsWith('http')) { + message.url = "https://agentseller.temu.com/" + message.url; + } + message.anti = message.anti || false + if (message.needMallId) { + // 如果参数中没有携带MallId,则从state中获取 + if (!message.mallId) { + message.mallId = store.state.mallId; + } + } + if (message.anti) { + message.anti = await genAnti.a() + } + return new Promise((resolve) => { + // @ts-ignore + chrome.runtime.sendMessage(message, resolve) + }) +} + /** * 向Chrome发送消息 * @param message 消息 @@ -74,7 +100,11 @@ export async function sendSheinAPIMessage(message) { */ export async function sendGeiwohuoAPIMessage(message) { message.type = 'geiwohuoApi' - message.url = "https://sso.geiwohuo.com/" + message.url; + if (message.isWWW) { + message.url = "https://www.geiwohuo.com/" + message.url; + } else { + message.url = "https://sso.geiwohuo.com/" + message.url; + } return new Promise((resolve) => { // @ts-ignore chrome.runtime.sendMessage(message, resolve) diff --git a/src/components/AiCopyFromTemu.vue b/src/components/AiCopyFromTemu.vue index 50a16a3..cdba9a2 100644 --- a/src/components/AiCopyFromTemu.vue +++ b/src/components/AiCopyFromTemu.vue @@ -368,13 +368,17 @@ export default { let content = data let i = 0 if (this.form.isSameCategory) { - let res2 = await this.$http.post('/api/innerCategory/fullById',null , { + /*let res2 = await this.$http.post('/api/innerCategory/fullById',null , { params: { id: reqData.catId } - }) - for (; i < res2.data.length; i++) { - content['cat' + (i+1) + 'Id'] = res2.data[i] + })*/ + for (; i < 10; i++) { + if (content['cat' + (i+1) + 'Id']) { + continue + }else { + break + } } let res3 = await sendChromeAPIMessage({ @@ -422,6 +426,9 @@ export default { content['cat' + (i+1) + 'Id'] = this.form.targetCatId[i] } } + if (content['cat'+(i+1)+'Id'] != reqData.catId) { + content['cat'+(++i)+'Id'] = reqData.catId + } for (; i < 10; i++) { content['cat' + (i+1) + 'Id'] = '' } diff --git a/src/manifest.development.json b/src/manifest.development.json index f946080..9788813 100644 --- a/src/manifest.development.json +++ b/src/manifest.development.json @@ -21,7 +21,8 @@ "*://*.alicdn.com/", "*://*.amazon.com/", "*://*.shein.com/", - "*://*.geiwohuo.com/" + "*://*.geiwohuo.com/", + "*://*.ltwebstatic.com/" ], "permissions": [ "cookies", @@ -51,13 +52,26 @@ "id": "6", "enabled": true, "path": "rules_6.json" + },{ + "id": "7", + "enabled": true, + "path": "rules_7.json" + },{ + "id": "8", + "enabled": true, + "path": "rules_8.json" + },{ + "id": "9", + "enabled": true, + "path": "rules_9.json" }] }, "content_scripts": [ { "matches": [ "*://*.aliexpress.com/item/*", - "*://*.amazon.com/*" + "*://*.amazon.com/*", + "*://*.shein.com/*" ], "js": [ "/content.js" @@ -67,7 +81,7 @@ "web_accessible_resources": [ { "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], - "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*" ] + "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*", "*://*.shein.com/*" ] } ] } diff --git a/src/manifest.production.json b/src/manifest.production.json index b33a91e..7299469 100644 --- a/src/manifest.production.json +++ b/src/manifest.production.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "TEMU助手", "description": "TEMU助手 - 自动化提高生产效率", - "version": "3.2.1", + "version": "3.2.3", "background": { "service_worker": "/background.js" }, @@ -21,7 +21,8 @@ "*://*.alicdn.com/", "*://*.amazon.com/", "*://*.shein.com/", - "*://*.geiwohuo.com/" + "*://*.geiwohuo.com/", + "*://*.ltwebstatic.com/" ], "permissions": [ "cookies", @@ -55,13 +56,26 @@ "id": "6", "enabled": true, "path": "rules_6.json" + },{ + "id": "7", + "enabled": true, + "path": "rules_7.json" + },{ + "id": "8", + "enabled": true, + "path": "rules_8.json" + },{ + "id": "9", + "enabled": true, + "path": "rules_9.json" }] }, "content_scripts": [ { "matches": [ "*://*.aliexpress.com/item/*", - "*://*.amazon.com/*" + "*://*.amazon.com/*", + "*://*.shein.com/*" ], "js": [ "/content.js" @@ -71,7 +85,7 @@ "web_accessible_resources": [ { "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], - "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*" ] + "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*", "*://*.shein.com/*" ] } ] } diff --git a/src/router/index.js b/src/router/index.js index 129195e..c4accf1 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -85,15 +85,20 @@ const router = new VueRouter({ name: 'copyProduct', component: () => import('../view/product/CopyProduct.vue') }, + { + path: 'sellerSelect', + name: 'sellerSelect', + component: () => import('../view/product/SellerSelect.vue') + }, { path: 'draft', name: 'draft', component: () => import('../view/product/Draft.vue') }, { - path: 'copyProductShein', - name: 'copyProductShein', - component: () => import('../view/product/CopyProductShein.vue') + path: 'findSeller', + name: 'findSeller', + component: () => import('../view/product/FindSeller.vue') }, { path: 'copyProductAliExpress', @@ -172,21 +177,56 @@ const router = new VueRouter({ component: () => import('../view/CoinFlow.vue') }, + { + path: 'costManageTemu', + name: 'costManageTemu', + component: () => import('../view/sale/CostManageTemu.vue') + }, { path: 'saleData', name: 'saleData', component: () => import('../view/sale/ExportSaleData.vue') }, - { - path: 'saleDataShein', - name: 'saleDataShein', - component: () => import('../view/sale/ExportSaleDataShein.vue') - }, { path: 'saleOut', name: 'saleOut', component: () => import('../view/sale/ExportSaleOutData.vue') }, + { + path: 'afterSaleStat', + name: 'afterSaleStat', + component: () => import('../view/sale/AfterSaleStat.vue') + }, + { + path: 'afterSaleDeductStat', + name: 'afterSaleDeductStat', + component: () => import('../view/sale/AfterSaleDeductStat.vue') + }, + { + path: 'costManageShein', + name: 'costManageShein', + component: () => import('../view/shein/CostManageShein.vue') + }, + { + path: 'certCenterShein', + name: 'certCenterShein', + component: () => import('../view/shein/CertCenterShein.vue') + }, + { + path: 'saleDataShein', + name: 'saleDataShein', + component: () => import('../view/shein/ExportSaleDataShein.vue') + }, + { + path: 'saleStatShein', + name: 'saleStatShein', + component: () => import('../view/shein/ExportSaleStatShein.vue') + }, + { + path: 'copyProductShein', + name: 'copyProductShein', + component: () => import('../view/shein/CopyProductShein.vue') + }, // { // path: 'statistics', diff --git a/src/store/index.js b/src/store/index.js index ab9578a..62b4aed 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -13,6 +13,8 @@ export default new Vuex.Store({ mallName: '', mallList: [], activeDlgShow: false, + showSheinAlert: false, + showTemuAlert: false, userInfo: {} }, @@ -46,6 +48,12 @@ export default new Vuex.Store({ }, setActiveDlgShow(state, flag) { state.activeDlgShow = flag + }, + setSheinAlertShow(state, flag) { + state.showSheinAlert = flag + }, + setTemuAlertShow(state, flag) { + state.showTemuAlert = flag } }, diff --git a/src/utils/product.js b/src/utils/product.js index c2f19b1..9a2e6f6 100644 --- a/src/utils/product.js +++ b/src/utils/product.js @@ -18,8 +18,9 @@ export function transform(leftData) { rightData.materialMultiLanguages = leftData.productLocalExtAttr.materialMultiLanguages; rightData.productI18nReqs = leftData.productI18nList; rightData.productPropertyReqs = []; + let flag = false for (let i = 0; i < leftData.productPropertyList.length; i++) { - rightData.productPropertyReqs.push({ + let val = { valueUnit: leftData.productPropertyList[i].valueUnit, propValue: leftData.productPropertyList[i].propValue, propName: leftData.productPropertyList[i].propName, @@ -29,9 +30,31 @@ export function transform(leftData) { pid: leftData.productPropertyList[i].pid, templatePid: leftData.productPropertyList[i].templatePid, valueExtendInfo: leftData.productPropertyList[i].valueExtendInfo - }); + } + /*if (leftData.productPropertyList[i].vid == 41500) { + if (config.brandId) { + flag = true + val.pid = 41500 + val.propName = config.brandName + } + }*/ + rightData.productPropertyReqs.push(val); } + /*if (config.brandId && !flag) { + rightData.productPropertyReqs.push({ + "valueUnit": "", + "propValue": config.brandName, + "propName": "品牌名", + "refPid": 1960, + "vid": 41500, + "controlType": 1, + "pid": config.brandId, + "templatePid": 1151553, + "valueExtendInfo": "" + }) + }*/ + // SKC let rightSkc = []; let leftSkc = leftData.productSkcList; @@ -159,6 +182,7 @@ export function transformSubmitForHalf(leftData, config, draftId) { rightData.materialMultiLanguages = leftData.productLocalExtAttr.materialMultiLanguages; rightData.productI18nReqs = leftData.productI18nList; rightData.productPropertyReqs = []; + if (!leftData.productPropertyList) return rightData for (let i = 0; i < leftData.productPropertyList.length; i++) { rightData.productPropertyReqs.push({ valueUnit: leftData.productPropertyList[i].valueUnit, @@ -240,6 +264,7 @@ export function transformSubmitForHalf(leftData, config, draftId) { } rightSkuItem.productSkuStockQuantityReq = productSkuStockQuantityReq rightSkuItem.currencyType = leftSkuItem.currencyType; + rightSkuItem.supplierPrice = leftSkuItem.supplierPrice + config.upMoney * 100; rightSkcItem.productSkuReqs.push(rightSkuItem); } @@ -255,6 +280,14 @@ export function transformSubmitForHalf(leftData, config, draftId) { rightData.carouselImageI18nReqs = leftData.carouselImageI18nVOList; rightData.materialImgUrl = leftData.materialImgUrl; rightData.goodsLayerDecorationReqs = leftData.goodsLayerDecorationVOList; + rightData.goodsLayerDecorationReqs.map(item => { + if (item.type == 'image') { + item.contentList.map(item1 => { + delete item1.text + delete item1.textModuleDetails + }) + } + }) rightData.sizeTemplateIds = !leftData.sizeTemplateIds ? []: leftData.sizeTemplateIds; rightData.showSizeTemplateIds = !leftData.showSizeTemplateIds ? []: leftData.showSizeTemplateIds; rightData.goodsModelReqs = !leftData.goodsModelList ? []: leftData.goodsModelList; diff --git a/src/view/Home.vue b/src/view/Home.vue index 6d6e1eb..fb6d18a 100644 --- a/src/view/Home.vue +++ b/src/view/Home.vue @@ -70,8 +70,11 @@ 商品列表 商品复制 - 草稿箱管理 - 商品复制(希音) + 查找买手 + + 草稿箱管理 + + 上新生命周期管理 @@ -126,18 +129,31 @@ 销售管理 - 销售管理(TEMU) - 销售数据(SHEIN) + 成本管理 + 销售管理 售罄看板 + 售后统计 + 售后赔付统计 + + + + + SHEIN希音 + + 成本管理 + 销售数据 + 证书中心 + 商品复制 + 商家账单统计 弹窗消息 - + 新手园地 @@ -164,6 +180,27 @@ :before-close="handleClose"> + + 1、检查“SHEIN商家后台”是否登录,如没登录,请先登录,之后再刷新助手 + 2、如果SHEIN商家后台已经登录,仍然弹出当前窗口,则需要SHEIN进行二次授权,二次授权可在菜单“商品管理->商品列表”,任意选择一个商品,在“价格”一栏,点击修改,在新打开的页面中可看到“正在鉴权”的字样,即可完成二次授权 + + 关 闭 + + + + 请先打开卖家中心“结算数据->售后管理”页面进行二次授权,去打开 + + 关 闭 + + @@ -174,7 +211,7 @@ diff --git a/src/view/product/FindSeller.vue b/src/view/product/FindSeller.vue new file mode 100644 index 0000000..e6cd1ce --- /dev/null +++ b/src/view/product/FindSeller.vue @@ -0,0 +1,118 @@ + + + + + + + + + 店铺: + + + + + SKC ID: + + 查找 + + + + + + + + + + \ No newline at end of file diff --git a/src/view/product/ProductList.vue b/src/view/product/ProductList.vue index a732e8d..9b9203a 100644 --- a/src/view/product/ProductList.vue +++ b/src/view/product/ProductList.vue @@ -3,12 +3,13 @@ 店铺: - + - - - 是否在售: - - - - - 商品名称: - - 加载 - - 下载数据 - - - {}"> + + + + + 起始页: + + + + 结束页: + + + + 是否在售: + + + + + + + 站点: + + + + + + + 合规下架风险: + + + + + + + 资质上传状态: + + + + + + + 商品名称: + + + + 库存起始值: + + + + 库存结束值: + + + + + 加载 + + + + + + 下载数据 + + + {}"> - - - - - {{ scope.row.productName }} - - - - - + + + + + {{ scope.row.productName }} + + + + + + @@ -80,11 +142,20 @@ import JsonExcel from 'vue-json-excel' form: { mallId: '' }, + startPage: 1, + endPage: 10, reqData: { productName: '', page: 1, pageSize: 100, - skcSiteStatus: '' + skcSiteStatus: '', + bindSiteId: '', + certPunishTypes: [], + productCertAuditStatuses: [], + jitStockQuantitySection: { + leftValue: '', + rightValue: '' + } }, options: [ {label: '是', value: 1}, @@ -100,6 +171,9 @@ import JsonExcel from 'vue-json-excel' { prop: 'extCode', label: 'SKC货号', width: '100px', align: 'left' }, { prop: 'skuExtCode', label: 'SKU货号', width: '160px', align: 'left' }, { prop: 'specName', label: 'SKU属性', width: '100px', align: 'left' }, + { prop: 'skuStockQuantity', label: '库存', width: '100px', align: 'left' }, + { prop: 'productCertAuditStatus', label: '资质上传状态', width: '120px', align: 'left' }, + { prop: 'certPunishType', label: '合规下架风险', width: '120px', align: 'left' }, { prop: 'supplierPrice', label: '申报价格(CNY)', width: '180px', align: 'left' }, { prop: 'todaySalesVolume', label: '今日销量', width: '100px', align: 'left' }, { prop: 'createdAt', label: '上架时间', width: '160px', align: 'left' } @@ -117,17 +191,47 @@ import JsonExcel from 'vue-json-excel' "SKC货号": "extCode", "SKU货号": "skuExtCode", "SKU属性": "specName", + "库存": "skuStockQuantity", + "资质上传状态": "productCertAuditStatus", + "合规下架风险": "certPunishType", "申报价格(CNY)": "supplierPrice", "今日销量": "todaySalesVolume", "上架时间": "createdAt" }, - currentIndex: 0 + certPunishTypes: [ + {id: 1, name: '已经处罚'}, + {id: 2, name: '即将下架'}, + {id: 3, name: '下架风险预警'}, + ], + productCertAuditStatusList: [ + {id: 1, name: '待上传'}, + {id: 2, name: '上传中'}, + {id: 3, name: '上传失败'}, + {id: 4, name: '上传成功'}, + ], + currentIndex: 0, + siteList: [] } }, components: { JsonExcel }, + created () { + this.getSiteList() + }, methods: { + async getSiteList() { + let res = await sendChromeAPIMessage({ + url: 'bg-visage-mms/config/common/site/query', + needMallId: true, + mallId: this.$store.state.mallList[0].mallId, + data: {}}) + if (res.success && res.errorCode == 1000000) { + this.siteList = res.result.siteBaseList.filter(item => { + return item.matchSemiManaged + }) + } + }, beforeGetList() { this.$userCheck(this.form.mallId).then(() => { this.toLoad() @@ -140,7 +244,19 @@ import JsonExcel from 'vue-json-excel' Message.error("请选择店铺") return } - this.reqData.page = 1 + 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.reqData.page = this.startPage this.tableData = [] this.currentIndex = 0 this.isLoading = true @@ -164,6 +280,24 @@ import JsonExcel from 'vue-json-excel' data.skcSiteStatus = item.skcSiteStatus == '1'? '在售': '' data.createdAt = timestampToTime(item.createdAt) data.extCode = item.extCode + data.productCertAuditStatus = '-' + if (item.productCertAuditStatus == 1) { + data.productCertAuditStatus = '待上传' + } else if (item.productCertAuditStatus == 2) { + data.productCertAuditStatus = '上传中' + } else if (item.productCertAuditStatus == 3) { + data.productCertAuditStatus = '上传失败' + } else if (item.productCertAuditStatus == 4) { + data.productCertAuditStatus = '上传成功' + } + data.certPunishType = '-' + if (item.productCertPunish?.certPunishType == 1) { + data.certPunishType = '已经处罚' + } else if (item.productCertPunish?.certPunishType == 2) { + data.certPunishType = '即将下架' + } else if (item.productCertPunish?.certPunishType == 3) { + data.certPunishType = '下架风险预警' + } data.category = '' for (let i = 1; i < 11; i++) { @@ -179,21 +313,23 @@ import JsonExcel from 'vue-json-excel' let temp = item.productSkuSummaries[k].productSkuSpecList.map(item2 => { return item2.parentSpecName + ":" + item2.specName }) + let skuStockQuantity = '-' + if (item.productSkuSummaries[k].productSkuSemiManagedStock) { + skuStockQuantity = item.productSkuSummaries[k].productSkuSemiManagedStock.skuStockQuantity + } data = {...data, productSkuId: item.productSkuSummaries[k].productSkuId, skuExtCode: item.productSkuSummaries[k].extCode, supplierPrice: item.productSkuSummaries[k].supplierPrice / 100, specName: temp.join(","), + skuStockQuantity, todaySalesVolume: item.productSkuSummaries[k].todaySalesVolume} this.tableData.push(data) } } - if (this.reqData.page == 1 && res.result.pageItems.length == 0) { - this.isLoading = false - } - else if (res.result.pageItems.length == 100) { + if (res.result.pageItems.length == this.reqData.pageSize && this.reqData.page < this.endPage) { this.reqData.page ++ this.load() } else { diff --git a/src/view/product/SellerSelect.vue b/src/view/product/SellerSelect.vue new file mode 100644 index 0000000..28569d7 --- /dev/null +++ b/src/view/product/SellerSelect.vue @@ -0,0 +1,272 @@ + + + + + + + 店铺: + + + + + + + + + + + + + + 起始页: + + + + 结束页: + + + + 状态: + + + + + + + 是否合规待办: + + + + + + + + 加载 + + + + + + 下载数据 + + + {}"> + + + + + + {{ scope.row.productName }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/view/sale/AfterSaleDeductStat.vue b/src/view/sale/AfterSaleDeductStat.vue new file mode 100644 index 0000000..cb6aa75 --- /dev/null +++ b/src/view/sale/AfterSaleDeductStat.vue @@ -0,0 +1,270 @@ + + + + + + + 店铺: + + + + + + + + + + + + + + 账务时间: + + + + + + 加载 + + + + + + 下载数据 + + + {}"> + + + + + {{ scope.row.productName }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/view/sale/AfterSaleStat.vue b/src/view/sale/AfterSaleStat.vue new file mode 100644 index 0000000..6469b2e --- /dev/null +++ b/src/view/sale/AfterSaleStat.vue @@ -0,0 +1,301 @@ + + + + + + + 店铺: + + + + + + + + + + + + + + 售后申请年份: + + + + + 扣罚倍数: + + + + + + + + 加载 + + + + + + 下载数据 + + + {}"> + + + + + {{ scope.row.productName }} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/view/sale/CostManageTemu.vue b/src/view/sale/CostManageTemu.vue new file mode 100644 index 0000000..a085499 --- /dev/null +++ b/src/view/sale/CostManageTemu.vue @@ -0,0 +1,361 @@ + + + + + + + 店铺: + + + + + + + + + + + + + + + + + 只显示未填写 + + + SKC ID: + + + + SKU ID: + + + + SKC货号: + + + + + + + + + + 导出 + 导入 + + {}"> + + + + {{ row.costPrice }} + + + + + + + + + + + + + + + + + 选择文件 + + 最多上传1个文件,单个文件最大10MB,仅支持Excel格式 + + + + + 关 闭 + 确 定 + + + + + + + + + diff --git a/src/view/sale/ExportSaleData.vue b/src/view/sale/ExportSaleData.vue index 739331b..4b60f38 100644 --- a/src/view/sale/ExportSaleData.vue +++ b/src/view/sale/ExportSaleData.vue @@ -68,12 +68,12 @@ - 今日销量 - {{ todayTotal }} + 今日销量/销售额 + {{ todayTotal }}/{{ todayMoney }} - 今日销售额 - {{ todayMoney }} + 今日利润/利润率 + {{ profitMoney }}/{{ profitPercent }} 可用库存总量(件) @@ -103,17 +103,12 @@ {{ inroadTotalMoney }} - - 已收货总量(件) - {{ deliveryTotal }} - - - 已收货总货值 - {{ deliveryMoney }} - + + 只显示今日有销量 + {}"> @@ -224,13 +219,13 @@ import { Message } from 'element-ui' currentPage: 1, todayTotal: 0, todayMoney: 0.0, + profitMoney: 0.0, + profitPercent: 0, inventoryTotal: 0, inventoryMoney: 0.0, inroadTotal: 0, inroadTotalMoney: 0.0, - deliveryTotal: 0, - deliveryMoney: 0.0, - allProductList: [], + costList: [], startDate: '', endDate: '', skuIds: [], @@ -264,6 +259,9 @@ import { Message } from 'element-ui' "用户累计加购数量": "inCardNumber", "已订阅待提醒到货": "nomsgSubsCntCntSth", "销售数据 - 今日": "todaySaleVolume", + "销售数据 - 今日销售额": "saleMoney", + "销售数据 - 利润": "profitMoney", + "销售数据 - 利润率": "profitPercent", "销售数据 - 近7日": "lastSevenDaysSaleVolume", "销售数据 - 近30天": "lastThirtyDaysSaleVolume", "库存数据 - 仓内可用库存": "inventoryNumInfo.warehouseInventoryNum", @@ -296,11 +294,22 @@ import { Message } from 'element-ui' skuDownloadForm: { date: '' }, + showTodaySale: false } }, computed: { ...mapState(['mallList']), + filteredData() { + const filteredData = this.list.filter(item => { + if (this.showTodaySale) { + return item.todaySaleVolume > 0 + } + return true + }) + + return filteredData + }, colConfigs () { return [ { @@ -362,6 +371,38 @@ import { Message } from 'element-ui' width: '120px', align: 'center' }, + { + prop: 'todaySaleVolume', + label: '今日销量', + width: '120px', + align: 'center', + sortable: true, + 'sort-method': (a, b) => { + return a.todaySaleVolume - b.todaySaleVolume + } + }, + { + prop: 'saleMoney', + label: '销售额', + width: '120px', + align: 'center' + }, + { + prop: 'profitMoney', + label: '利润', + width: '120px', + align: 'center', + sortable: true, + 'sort-method': (a, b) => { + return a.profitMoney - b.profitMoney + } + }, + { + prop: 'profitPercent', + label: '利润率(%)', + width: '120px', + align: 'center' + }, { prop: 'onSalesDurationOffline', label: '加入站点时长', @@ -388,7 +429,6 @@ import { Message } from 'element-ui' label: '仓内可用库存', width: '160px', align: 'center', - fixed: "right", sortable: true, 'sort-method': (a, b) => { return a.warehouseInventoryNum - b.warehouseInventoryNum @@ -550,6 +590,13 @@ import { Message } from 'element-ui' align: 'center', fixed: 'left' }, + { + prop: 'supplierPrice', + label: '申报价格', + width: '120px', + align: 'center', + fixed: 'left' + }, { prop: 'productSkuId', label: 'SKU ID', @@ -599,6 +646,7 @@ import { Message } from 'element-ui' "SKC货号": "skcExtCode", "SKU ID": "productSkuId", "SKU货号": "skuExtCode", + "申报价格": "supplierPrice", "图片链接": "productSkcPicture" } @@ -637,15 +685,13 @@ import { Message } from 'element-ui' this.currentPage = 1 this.todayMoney = 0.0 this.todayTotal = 0 + this.profitMoney = 0.0 + this.profitPercent = 0 this.inventoryMoney = 0.0 this.inventoryTotal = 0 this.inroadTotalMoney = 0.0 this.inroadTotal = 0 - this.deliveryTotal = 0 - this.deliveryMoney = 0.0 - this.allProductList = [] if (!this.mallId) { - Message.error("请先选择店铺") return } @@ -657,33 +703,27 @@ import { Message } from 'element-ui' this.isLoading = true this.$userCheck(this.mallId).then(() => { this.last30DaySkcList = [] - this.getAllProductList() + this.getSkuCostList() this.getList() }).catch((err) => { console.log(err) this.isLoading = false }) }, - getAllProductList() { - this.$http.post('/api/deliveryOrder/totalDelivery',null, { - params: {mallId: this.mallId} - }).then(res => { - if (res.code === 0) { - this.deliveryTotal = res.data + getSkuCostList() { + this.$http.post(`/api/skuCost/listAll`, null, { + params: { + mallId: this.mallId } - }) - - this.$http.post('/api/deliveryOrder/getAllProductList', null, { - params: {mallId: this.mallId} }).then(res => { if (res.code == 0) { - this.allProductList = res.data + this.costList = res.data } }) }, getList () { sendChromeAPIMessage({ - url: 'marvel-mms/cn/api/kiana/venom/sales/management/list', + url: 'marvel-mms/cn/api/kiana/venom/sales/management/listWarehouse', needMallId: true, mallId: this.mallId, data: { @@ -724,32 +764,30 @@ import { Message } from 'element-ui' for(let j = 0;j < item.skuQuantityDetailList.length; j++) { + let costPrice = this.getCostPrice(item.skuQuantityDetailList[j].productSkuId) + let saleMoney = Math.round(item.skuQuantityDetailList[j].todaySaleVolume * item.skuQuantityDetailList[j].supplierPrice) /100 + let profitMoney = Math.round(item.skuQuantityDetailList[j].todaySaleVolume * (item.skuQuantityDetailList[j].supplierPrice / 100 - costPrice) * 100) /100 + let profitPercent = Math.round(profitMoney / saleMoney * 10000) /100 data = {...data, ...item.skuQuantityDetailList[j], + saleMoney: saleMoney, + profitMoney: profitMoney, + profitPercent: profitPercent, productTotalPrice: ((item.skuQuantityDetailList[j].supplierPrice / 100) * item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum).toFixed(2), inroadTotalPrice: ((item.skuQuantityDetailList[j].supplierPrice / 100) * (item.skuQuantityDetailList[j].inventoryNumInfo.waitOnShelfNum + item.skuQuantityDetailList[j].inventoryNumInfo.waitReceiveNum)).toFixed(2), warehouseInventoryNum: item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum} - - this.todayTotal += item.skuQuantityDetailList[j].todaySaleVolume - this.todayMoney += new Number(((item.skuQuantityDetailList[j].supplierPrice / 100) * item.skuQuantityDetailList[j].todaySaleVolume).toFixed(2)) - this.todayMoney = new Number(this.todayMoney.toFixed(2)) - this.inventoryTotal += item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum - this.inventoryMoney += new Number(((item.skuQuantityDetailList[j].supplierPrice / 100) * item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum).toFixed(2)) - this.inventoryMoney = new Number(this.inventoryMoney.toFixed(2)) - this.inroadTotal += (item.skuQuantityDetailList[j].inventoryNumInfo.waitOnShelfNum + item.skuQuantityDetailList[j].inventoryNumInfo.waitReceiveNum) - this.inroadTotalMoney += new Number(((item.skuQuantityDetailList[j].supplierPrice / 100) * (item.skuQuantityDetailList[j].inventoryNumInfo.waitOnShelfNum + item.skuQuantityDetailList[j].inventoryNumInfo.waitReceiveNum)).toFixed(2)) - this.inroadTotalMoney = new Number(this.inroadTotalMoney.toFixed(2)) - this.adviceProduceNum = item.skuQuantityDetailList[j].adviceProduceNum || '-' - this.availableProduceNum = item.skuQuantityDetailList[j].availableProduceNum || '-' - this.list.push(data); - - // 计算已发货货值 - for(let k = 0; k < this.allProductList.length; k++) { - if (this.allProductList[k].product_sku_id == data.productSkuId) { - this.deliveryMoney += (item.skuQuantityDetailList[j].supplierPrice / 100) * this.allProductList[k].product_sku_number - this.deliveryMoney = new Number(this.deliveryMoney.toFixed(2)) - } - } + + this.todayTotal += item.skuQuantityDetailList[j].todaySaleVolume + this.profitMoney += item.skuQuantityDetailList[j].todaySaleVolume * (item.skuQuantityDetailList[j].supplierPrice / 100 - costPrice) + this.todayMoney += (item.skuQuantityDetailList[j].supplierPrice / 100) * item.skuQuantityDetailList[j].todaySaleVolume + this.inventoryTotal += item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum + this.inventoryMoney += (item.skuQuantityDetailList[j].supplierPrice / 100) * item.skuQuantityDetailList[j].inventoryNumInfo.warehouseInventoryNum + this.inroadTotal += (item.skuQuantityDetailList[j].inventoryNumInfo.waitOnShelfNum + item.skuQuantityDetailList[j].inventoryNumInfo.waitReceiveNum) + this.inroadTotalMoney += (item.skuQuantityDetailList[j].supplierPrice / 100) * (item.skuQuantityDetailList[j].inventoryNumInfo.waitOnShelfNum + item.skuQuantityDetailList[j].inventoryNumInfo.waitReceiveNum) + this.adviceProduceNum = item.skuQuantityDetailList[j].adviceProduceNum || '-' + this.availableProduceNum = item.skuQuantityDetailList[j].availableProduceNum || '-' + this.list.push(data); } + } if (this.pageSize == res.result.subOrderList.length) { this.currentPage ++ @@ -757,6 +795,12 @@ import { Message } from 'element-ui' this.getList() }, 1500) } else { + this.profitMoney = Math.round(this.profitMoney * 100) / 100 + this.todayMoney = Math.round(this.todayMoney * 100) / 100 + this.profitPercent = Math.round((this.profitMoney / this.todayMoney) * 10000) /100 + '%' + this.inventoryMoney = Math.round(this.inventoryMoney * 100) / 100 + this.inroadTotalMoney = Math.round(this.inroadTotalMoney * 100) / 100 + this.isLoading = false Message.success('销售数据加载完成,可进行导出') @@ -782,7 +826,8 @@ import { Message } from 'element-ui' productSkuId: item.productSkuId, skuExtCode: item.skuExtCode, skcExtCode: item.skcExtCode, - productSkcPicture: item.productSkcPicture + productSkcPicture: item.productSkcPicture, + supplierPrice: this.getSupplierPrice(item.productSkuId) } let date = new Date() date.setDate(date.getDate() - 31) @@ -888,7 +933,8 @@ import { Message } from 'element-ui' temp = { 'SKC': 'skc', 'SKU': 'sku', - 'SKU货号': 'skuExtCode' + 'SKU货号': 'skuExtCode', + '申报价格': 'supplierPrice' } let beginTime = new Date(this.skuDownloadForm.date[0]) let endTime = new Date(this.skuDownloadForm.date[1]) @@ -914,7 +960,8 @@ import { Message } from 'element-ui' let temp = { sku: item.productSkuId, skc: item.productSkcId, - skuExtCode: item.skuExtCode + skuExtCode: item.skuExtCode, + supplierPrice: this.getSupplierPrice(item.productSkuId) } beginTime = new Date(this.skuDownloadForm.date[0]) endTime = new Date(this.skuDownloadForm.date[1]) @@ -966,6 +1013,22 @@ import { Message } from 'element-ui' reqSkusIds = [] } } + }, + getSupplierPrice(productSkuId) { + for (let i = 0; i < this.list.length; i++) { + if (this.list[i].productSkuId == productSkuId) { + return this.list[i].supplierPrice / 100 + } + } + return 0 + }, + getCostPrice(productSkuId) { + for (let i = 0; i < this.costList.length; i++) { + if (this.costList[i].sku == productSkuId) { + return this.costList[i].costPrice + } + } + return 0 } } } diff --git a/src/view/shein/CertCenterShein.vue b/src/view/shein/CertCenterShein.vue new file mode 100644 index 0000000..6ef2733 --- /dev/null +++ b/src/view/shein/CertCenterShein.vue @@ -0,0 +1,156 @@ + + + + + + + + 导出 + + {}"> + + + + + + + + + diff --git a/src/view/product/CopyProductShein.vue b/src/view/shein/CopyProductShein.vue similarity index 98% rename from src/view/product/CopyProductShein.vue rename to src/view/shein/CopyProductShein.vue index 30fd4e5..4594677 100644 --- a/src/view/product/CopyProductShein.vue +++ b/src/view/shein/CopyProductShein.vue @@ -51,11 +51,11 @@ label="商品列表" value="0"> - - + --> @@ -256,6 +256,9 @@ import { Message } from 'element-ui' createTime: item.create_time }; }) + } else if (res.code == 100004 || res.code == 20302) { + this.isLoading = false + this.$store.commit("setSheinAlertShow", true) } }, productHandleSelectionChange(val) { diff --git a/src/view/shein/CostManageShein.vue b/src/view/shein/CostManageShein.vue new file mode 100644 index 0000000..f9eddf5 --- /dev/null +++ b/src/view/shein/CostManageShein.vue @@ -0,0 +1,354 @@ + + + + + + + + + + + + + 只显示未填写 + + + SKC ID: + + + + SKU ID: + + + + SKC货号: + + + + + + + + + + 导出 + 导入 + + {}"> + + + + {{ row.costPrice }} + + + + + + + + + + + + + + + + + 选择文件 + + 最多上传1个文件,单个文件最大10MB,仅支持Excel格式 + + + + + 关 闭 + 确 定 + + + + + + + + + diff --git a/src/view/sale/ExportSaleDataShein.vue b/src/view/shein/ExportSaleDataShein.vue similarity index 52% rename from src/view/sale/ExportSaleDataShein.vue rename to src/view/shein/ExportSaleDataShein.vue index e800fea..a3f7db1 100644 --- a/src/view/sale/ExportSaleDataShein.vue +++ b/src/view/shein/ExportSaleDataShein.vue @@ -2,7 +2,7 @@ @@ -46,22 +46,17 @@ - - 导出数据 - + + 只显示今日有销量 + {}"> @@ -90,6 +85,7 @@ import { Message } from 'element-ui' data () { return { list: [], + mallId: '', isLoading: false, pageSize: 100, currentPage: 1, @@ -104,61 +100,7 @@ import { Message } from 'element-ui' startDate: '', endDate: '', skuIds: [], - jsonFields: { - "商品名称": "productName", - "SPU": "productId", - "SKC": "productSkcId", - "SKU ID": "productSkuId", - "SKU属性": "className", - "SKU货号": "skuExtCode", - "加入站点时长": "onSalesDurationOffline", - "图片链接": "productSkcPicture", - "申报价格(CNY)": { - "field": "supplierPrice", - callback: (value) => { - return value /100; - } - }, - "开款核价状态": { - "field": "isVerifyPrice", - callback: (value) => { - return value ? '核价通过': '核价未通过 / 无法备货'; - } - }, - "缺货数量": "lackQuantity", - "建议备货量": "adviceQuantity", - "可售天数": "availableSaleDays", - "库存可售天数": "availableSaleDaysFromInventory", - "仓内库存可售天数": "warehouseAvailableSaleDays", - "近7日用户加购数量": "inCartNumber7d", - "用户累计加购数量": "inCardNumber", - "已订阅待提醒到货": "nomsgSubsCntCntSth", - "销售数据 - 今日": "todaySaleVolume", - "销售数据 - 近7日": "lastSevenDaysSaleVolume", - "销售数据 - 近30天": "lastThirtyDaysSaleVolume", - "库存数据 - 仓内可用库存": "inventoryNumInfo.warehouseInventoryNum", - "库存数据 - 仓内暂不可用库存": "inventoryNumInfo.waitOnShelfNum", - "库存数据 - 已发货库存": "inventoryNumInfo.waitReceiveNum", - "库存数据 - 已下单待发货库存": "inventoryNumInfo.waitDeliveryInventoryNum", - "库存数据 - 待审核备货库存": "inventoryNumInfo.waitApproveInventoryNum", - "VMI备货单数 - 待发货": "vmiOrderInfo.waitDeliveryNum", - "VMI备货单数 - 在途单数": "vmiOrderInfo.transportationNum", - "VMI备货单数 - 发货延迟": "vmiOrderInfo.deliveryDelayNum", - "VMI备货单数 - 到货延迟": "vmiOrderInfo.arrivalDelayNum", - "非VMI备货单数 - 待发货": "notVmiOrderInfo.waitDeliveryNum", - "非VMI备货单数 - 在途单数": "notVmiOrderInfo.transportationNum", - "非VMI备货单数 - 发货延迟": "notVmiOrderInfo.deliveryDelayNum", - "非VMI备货单数 - 到货延迟": "notVmiOrderInfo.arrivalDelayNum", - "备货逻辑": "purchaseConfig", - "可用库存货值(CNY)": "productTotalPrice", - "在途库存货值(CNY)": "inroadTotalPrice", - "店铺名称": "mallName", - "评分": "mark", - "是否热销": 'hotTag', - "生产建议信息 - 建议生产数": 'adviceProduceNum', - "生产建议信息 - 剩余件数": 'availableProduceNum', - "类目": 'category' - }, + showTodaySale: false, skuSaleNumberFields: {}, skuSaleNumberList: [], @@ -166,134 +108,52 @@ import { Message } from 'element-ui' skuDownloadForm: { date: '' }, + costList: [] } }, computed: { + filteredData() { + const filteredData = this.list.filter(item => { + if (this.showTodaySale) { + return item.todaySale > 0 + } + return true + }) + + return filteredData + }, colConfigs () { return [ - { - slot: 'goodsThumb', - label: '图片' - }, - { - prop: 'supplierCode', - label: '货号', - width: '120px', - align: 'center', - fixed: 'left' - }, - { - prop: 'suffixZh', - label: '规格', - width: '160px', - align: 'center', - fixed: 'left' - }, - { - prop: 'categoryName', - label: '分类', - "show-overflow-tooltip": true, - width: '100px' - }, - - { - prop: 'mallStatusName', - label: '状态', - width: '120px', - align: 'center' - }, - { - prop: 'skc', - label: 'SKC', - width: '160px', - align: 'center' - }, - { - prop: 'ableSaleDays', - label: '可售天数', - align: 'center' - }, - { - prop: 'cost', - label: '价格', - width: '120px', - align: 'center' - }, - - { - prop: 'todaySale', - label: '今日销量', - width: '120px', - align: 'center' - }, - { - prop: 'saleInfoWeek', - label: '近7天销量', - width: '120px', - align: 'center' - }, - { - prop: 'saleInfoMonth', - label: '本月销量', - width: '120px', - align: 'center' - }, - { - prop: 'saleInfoPreMonth', - label: '上月销量', - width: '120px', - align: 'center' - }, - - { - prop: 'purchaseConfig', - label: '备货逻辑', - width: '160px', - align: 'center' - }, - { - prop: 'onWayNum', - label: '在途数量', - width: '160px', - align: 'center' - }, - { - prop: 'ivtNum', - label: '库存数量', - width: '160px', - align: 'center' - }, - { - prop: 'productTotalPrice', - label: '库存货值(CNY)', - width: '180px', - align: 'center', - fixed: "right", - sortable: true, - 'sort-method': (a, b) => { + {slot: 'goodsThumb',label: '图片'}, + {prop: 'supplierCode',label: '货号',width: '120px',align: 'center',fixed: 'left'}, + {prop: 'suffixZh',label: '规格',width: '160px',align: 'center',fixed: 'left'}, + {prop: 'categoryName',label: '分类',"show-overflow-tooltip": true,width: '100px'}, + {prop: 'mallStatusName',label: '状态',width: '120px',align: 'center'}, + {prop: 'skc',label: 'SKC',width: '160px',align: 'center'}, + {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: 'todayProfit',label: '利润',width: '120px',align: 'center',sortable: true,'sort-method': (a, b) => { + return a.todayProfit - b.todayProfit + }}, + {prop: 'saleInfoWeek',label: '近7天销量',width: '120px',align: 'center'}, + {prop: 'saleInfoMonth',label: '本月销量',width: '120px',align: 'center'}, + {prop: 'saleInfoPreMonth',label: '上月销量',width: '120px',align: 'center'}, + {prop: 'purchaseConfig',label: '备货逻辑',width: '160px',align: 'center'}, + {prop: 'onWayNum',label: '在途数量',width: '160px',align: 'center'}, + {prop: 'ivtNum',label: '库存数量',width: '160px',align: 'center'}, + {prop: 'productTotalPrice',label: '库存货值(CNY)',width: '180px',align: 'center',fixed: "right",sortable: true,'sort-method': (a, b) => { return a.productTotalPrice - b.productTotalPrice } }, - { - prop: 'inroadTotalPrice', - label: '在途货值(CNY)', - width: '180px', - align: 'center', - fixed: "right", - sortable: true, - 'sort-method': (a, b) => { + {prop: 'inroadTotalPrice',label: '在途货值(CNY)',width: '180px',align: 'center',fixed: "right",sortable: true,'sort-method': (a, b) => { return a.inroadTotalPrice - b.inroadTotalPrice } }, - - { - prop: 'purchaseConfig', - label: '备货逻辑', - align: 'center', - width: '120px', - fixed: "right", - sortable: true, + {prop: 'purchaseConfig', + label: '备货逻辑',align: 'center',width: '120px',fixed: "right",sortable: true, 'sort-method': (a, b) => { if (a.purchaseConfig > b.purchaseConfig) { return 1 @@ -304,8 +164,6 @@ import { Message } from 'element-ui' } } } - - ] } }, @@ -329,7 +187,20 @@ import { Message } from 'element-ui' }, methods: { - beforeGetList() { + async getUserInfo() { + let res = await sendGeiwohuoAPIMessage({ + url: 'sso-prefix/auth/getUser?uuid=' + Date.now(), + method: 'GET' + }) + if (res.code == '0' && res.msg == "OK") { + this.mallId = res.info.merchantCode + } else if (res.code == 100004 || res.code == 20302) { + this.isLoading = false + this.$store.commit("setSheinAlertShow", true) + } + }, + async beforeGetList() { + await this.getUserInfo() this.list = [] this.currentPage = 1 this.todayMoney = 0.0 @@ -339,6 +210,7 @@ import { Message } from 'element-ui' this.inroadTotalMoney = 0.0 this.inroadTotal = 0 + await this.getSkuCostList() this.isLoading = true this.getList() }, @@ -368,6 +240,7 @@ import { Message } from 'element-ui' data = {...data, ableSaleDays: sku.ableSaleDays, cost: sku.cost, + skuCode: sku.skuCode, purchaseConfig: (sku.operateTime?sku.operateTime:'/') + '+' + (sku.prepareDay?sku.prepareDay:'/'), saleInfoMonth: sku.saleInfoMonth, saleInfoPreMonth: sku.saleInfoPreMonth, @@ -376,18 +249,20 @@ import { Message } from 'element-ui' todaySale: sku.todaySale, onWayNum: sku.onWayNum, ivtNum: sku.ivtNum, - productTotalPrice: (sku.cost * sku.ivtNum).toFixed(2), - inroadTotalPrice: (sku.cost * sku.onWayNum).toFixed(2)} + costPrice: null, + todayProfit: null, + productTotalPrice: Math.round((sku.cost * sku.ivtNum)*100)/100, + inroadTotalPrice: Math.round((sku.cost * sku.onWayNum)*100)/100} this.todayTotal += sku.todaySale - this.todayMoney += new Number((sku.cost * sku.todaySale).toFixed(2)) - this.todayMoney = new Number(this.todayMoney.toFixed(2)) + this.todayMoney += Math.round((sku.cost * sku.todaySale)*100)/100 + this.todayMoney = Math.round(this.todayMoney * 100) / 100 this.inventoryTotal += sku.ivtNum - this.inventoryMoney += new Number((sku.cost * sku.ivtNum).toFixed(2)) - this.inventoryMoney = new Number(this.inventoryMoney.toFixed(2)) + this.inventoryMoney += Math.round((sku.cost * sku.ivtNum)*100)/100 + this.inventoryMoney = Math.round(this.inventoryMoney*100)/100 this.inroadTotal += sku.onWayNum - this.inroadTotalMoney += new Number((sku.cost * sku.onWayNum).toFixed(2)) - this.inroadTotalMoney = new Number(this.inroadTotalMoney.toFixed(2)) + this.inroadTotalMoney += Math.round((sku.cost * sku.onWayNum)*100)/100 + this.inroadTotalMoney = Math.round(this.inroadTotalMoney*100)/100 this.list.push(data); } } @@ -398,12 +273,24 @@ import { Message } from 'element-ui' this.getList() }, 1500) } else { + for (let i = 0; i < this.list.length; i++) { + for (let j = 0; j < this.costList.length; j++) { + if (this.list[i].skuCode == this.costList[j].sku) { + this.list[i].costPrice = this.costList[j].costPrice + this.list[i].todayProfit = Math.round((this.list[i].cost - this.costList[j].costPrice) * this.list[i].todaySale * 100) / 100 + break + } + } + } this.isLoading = false Message.success('销售数据加载完成,可进行导出') this.$nextTick(() => { //在数据加载完,重新渲染表格 this.$refs['table0'].doLayout(); }) } + } else if (res.code == 100004 || res.code == 20302) { + this.isLoading = false + this.$store.commit("setSheinAlertShow", true) } else { setTimeout(() => { this.getList() @@ -413,18 +300,16 @@ import { Message } from 'element-ui' this.isLoading = false }) }, - startDownload() { - 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; - } + async getSkuCostList() { + let res = await this.$http.post(`/api/skuCost/listAll`, null, { + params: { + mallId: this.mallId } }) - } + if (res.code == 0) { + this.costList = res.data + } + }, } } diff --git a/src/view/shein/ExportSaleStatShein.vue b/src/view/shein/ExportSaleStatShein.vue new file mode 100644 index 0000000..2556090 --- /dev/null +++ b/src/view/shein/ExportSaleStatShein.vue @@ -0,0 +1,905 @@ + + + + + + + 时间范围: + + + + 开始统计 + 下载图片 + + 下载SKC统计 + + + 下载SKU统计 + + + + + + + + + + + + + + {{ saleAmount }}/{{ saleCount }} + + + + + + + + + + + + + + + + + + + + + + + + % + + + + + + + + + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + {{ scope.row.amount }} + + + + + {{ scope.row.profitAmount }} + + + + + {{ scope.row.profitPercent + '%' }} + + + + + + + + + + + + + + + + + diff --git a/src/view/shipping/WaitCreate.vue b/src/view/shipping/WaitCreate.vue index 18ea625..3686e98 100644 --- a/src/view/shipping/WaitCreate.vue +++ b/src/view/shipping/WaitCreate.vue @@ -19,8 +19,7 @@ - 开始创建 - {{ `结束创建(${choosedList.length}/${createTotal})` }} + 开始创建 @@ -225,12 +224,10 @@ Message.error("请选择待创建备货单") return } - console.log(this.arr) this.arr.map(item => { let temp = this.choosedList.filter(i => { return i.subPurchaseOrderSn == item.subPurchaseOrderSn }) - console.log(temp) if (temp.length == 0) { this.choosedList.push(item) console.log(this.choosedList) @@ -261,20 +258,12 @@ this.loadAll() } }, - beginCreateConfirm() { + beforeBegin() { if (this.choosedList.length <= 0) { Message.error('请先添加备货单'); return; } - this.createDlgShow = true - }, - beforeBegin() { - this.$refs.robForm.validate((valid) => { - if (valid) { - this.createDlgShow = false - this.beginCreate() - } - }) + this.beginCreate() }, getList (data, mallId, mallName, currentPage) { sendChromeAPIMessage({ @@ -334,74 +323,43 @@ getStyle(url) { return "background-image: url(" + url + "); width: 72px; height: 72px; cursor: pointer; border-radius: 6px; border: 1px solid rgba(0, 0, 0, 0.14);"; }, - beginCreate() { - if (this.isBegin) { - this.isBegin = false; - return; + async beginCreate() { + let waitCreateList = [] + for (let i = 0; i < this.mallList.length; i++) { + let subPurchaseOrderSnList = [] + this.choosedList.map(item => { + if (item.mallId == this.mallList[i].mallId) { + subPurchaseOrderSnList.push(item.subPurchaseOrderSn) + } + }) + if (subPurchaseOrderSnList.length > 0) { + waitCreateList.push({ + mallId: this.mallList[i].mallId, + subPurchaseOrderSnList: subPurchaseOrderSnList + }) + } } - this.createTotal = this.choosedList.length - this.isBegin = true; + for (let j = 0; j < waitCreateList.length; j++) { + let res = await sendChromeAPIMessage({ + url: 'oms/bg/venom/api/supplier/purchase/manager/batchAcceptSubPurchaseOrder', + needMallId: true, + anti: true, + mallId: waitCreateList[j].mallId, + data: { + subPurchaseOrderSnList: waitCreateList[j].subPurchaseOrderSnList, + confirmFulfilment: false + }}) - this.choosedList.map((data, index) => { - let deliverOrderDetailInfos = data.skuQuantityDetailList.map(item => { - if (this.robForm.isModifyMaxNum) { - return { - productSkuId: item.productSkuId, - deliverSkuNum: item.skuDeliveryQuantityMaxLimit - } - } else { - return { - productSkuId: item.productSkuId, - deliverSkuNum: item.productSkuPurchaseQuantity + if (res.success && res.errorCode == 1000000) { + if (res.result.isSuccess) { + for (let n = 0; n < waitCreateList[j].subPurchaseOrderSnList.length; n++) { + this.remove(waitCreateList[j].subPurchaseOrderSnList[n]) + } } } - }) - let packageInfos = [] - data.orderDetailVOList.map(item => { - let packageDetailSaveInfos = [] - if (this.robForm.isModifyMaxNum) { - packageDetailSaveInfos.push({ - productSkuId: item.productSkuId, - skuNum: item.skuDeliveryQuantityMaxLimit - }) - - } else { - packageDetailSaveInfos.push({ - productSkuId: item.productSkuId, - skuNum: item.productSkuPurchaseQuantity - }) - } - packageInfos.push({packageDetailSaveInfos: packageDetailSaveInfos}) - }) - - let addressInfo = this.addressList.filter(k => { - return k.mallId == data.mallId - }) - - let deliveryOrderCreateInfos = [] - deliveryOrderCreateInfos.push({ - deliverOrderDetailInfos: deliverOrderDetailInfos, - subPurchaseOrderSn: data.subPurchaseOrderSn, - deliveryAddressId: addressInfo[0].addressId, - packageInfos: packageInfos - }) - - let deliveryOrderCreateGroupList = [] - deliveryOrderCreateGroupList.push({ - deliveryOrderCreateInfos: deliveryOrderCreateInfos, - receiveAddressInfo: data.receiveAddressInfo, - subWarehouseId: data.subWarehouseId - }) - }) - - let _this = this; - let tt = setInterval(function() { - if (_this.choosedList.length == 0) { - _this.isBegin = false; - clearInterval(tt); - } - }, 1000) + } + }, formatTime(time) { return timestampToTime(time) diff --git a/yarn.lock b/yarn.lock index 380bcef..efac6ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2054,6 +2054,11 @@ address@^1.1.2: resolved "https://registry.npmmirror.com/address/-/address-1.2.2.tgz" integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== +adler-32@~1.3.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2" + integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz" @@ -2358,6 +2363,11 @@ balanced-match@^1.0.0: resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz" @@ -2568,6 +2578,14 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" +cfb@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44" + integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA== + dependencies: + adler-32 "~1.3.0" + crc-32 "~1.2.0" + chalk@4.1.0: version "4.1.0" resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.0.tgz" @@ -2751,6 +2769,11 @@ clone@^1.0.2: resolved "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +codepage@~1.15.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" + integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz" @@ -2953,6 +2976,11 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +crc-32@~1.2.0, crc-32@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-5.1.0.tgz" @@ -2997,6 +3025,13 @@ css-declaration-sorter@^6.3.1: resolved "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz" integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== +css-line-break@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz" + integrity sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w== + dependencies: + utrie "^1.0.2" + css-loader@^6.5.0: version "6.8.1" resolved "https://registry.npmmirror.com/css-loader/-/css-loader-6.8.1.tgz" @@ -3897,6 +3932,11 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-saver@^2.0.5: + version "2.0.5" + resolved "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" + integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz" @@ -3989,6 +4029,11 @@ forwarded@0.2.0: resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== +frac@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" + integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + fraction.js@^4.2.0: version "4.2.0" resolved "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.2.0.tgz" @@ -4335,6 +4380,14 @@ html-webpack-plugin@^5.1.0: pretty-error "^4.0.0" tapable "^2.0.0" +html2canvas@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz" + integrity sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA== + dependencies: + css-line-break "^2.1.0" + text-segmentation "^1.0.3" + htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz" @@ -6788,6 +6841,13 @@ sprintf-js@~1.0.2: resolved "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +ssf@~0.11.2: + version "0.11.2" + resolved "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" + integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + dependencies: + frac "~1.1.2" + ssri@^8.0.1: version "8.0.1" resolved "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz" @@ -7060,6 +7120,13 @@ terser@^5.10.0, terser@^5.16.8: commander "^2.20.0" source-map-support "~0.5.20" +text-segmentation@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz" + integrity sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw== + dependencies: + utrie "^1.0.2" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz" @@ -7341,6 +7408,13 @@ utils-merge@1.0.1: resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +utrie@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz" + integrity sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw== + dependencies: + base64-arraybuffer "^1.0.2" + uuid@^8.3.2: version "8.3.2" resolved "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz" @@ -7722,11 +7796,21 @@ window-size@0.1.0: resolved "https://registry.npmmirror.com/window-size/-/window-size-0.1.0.tgz" integrity sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg== +wmf@~1.0.1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" + integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +word@~0.3.0: + version "0.3.0" + resolved "https://registry.npmmirror.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961" + integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA== + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.npmmirror.com/wordwrap/-/wordwrap-0.0.2.tgz" @@ -7764,6 +7848,19 @@ ws@^8.13.0: resolved "https://registry.npmmirror.com/ws/-/ws-8.13.0.tgz" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== +xlsx@^0.18.5: + version "0.18.5" + resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0" + integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ== + dependencies: + adler-32 "~1.3.0" + cfb "~1.2.1" + codepage "~1.15.0" + crc-32 "~1.2.1" + ssf "~0.11.2" + wmf "~1.0.1" + word "~0.3.0" + y18n@^5.0.5: version "5.0.8" resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz"
{{ todayTotal }}
{{ todayTotal }}/{{ todayMoney }}
{{ todayMoney }}
{{ profitMoney }}/{{ profitPercent }}
{{ inroadTotalMoney }}
{{ deliveryTotal }}
{{ deliveryMoney }}