This commit is contained in:
liushiwei
2024-08-07 14:46:26 +08:00
parent 0808f42ce7
commit 25ba3eb387
14 changed files with 1066 additions and 48 deletions

View File

@@ -42,8 +42,49 @@ function init() {
flag = true
}
}
const regex = /price-adjust-confirm[^\n]+content/
let modelsAll = document.querySelectorAll('div[class*="price-adjust-confirm"]')
const results = Array.from(modelsAll).filter(item => regex.test(item.getAttribute('class')))
for (let i = 0; i < results.length; i++) {
let tipsObj = results[i].querySelector('div[class*="_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 = results[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 models2 = document.querySelectorAll('div[class^="price-adjust-confirm-system_contentWrp"]')
/*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')
@@ -194,6 +235,43 @@ function init() {
flag = true
}
}
let models6 = document.querySelectorAll('div[class^="grape-price-adjust-confirm_content"]')
for (let i = 0; i < models6.length; i++) {
let tipsObj = models6[i].querySelector('div[class^="grape-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 = models6[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 {

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "TEMU助手",
"description": "TEMU助手 - 自动化提高生产效率",
"version": "3.2.8",
"version": "3.2.11",
"background": {
"service_worker": "/background.js"
},

View File

@@ -212,6 +212,11 @@ const router = new VueRouter({
name: 'saleStatTemu',
component: () => import('../view/sale/ExportSaleStatTemu.vue')
},
{
path: 'priceAdjustment',
name: 'priceAdjustment',
component: () => import('../view/sale/PriceAdjustment.vue')
},
{
path: 'costManageShein',
name: 'costManageShein',
@@ -237,6 +242,16 @@ const router = new VueRouter({
name: 'copyProductShein',
component: () => import('../view/shein/CopyProductShein.vue')
},
{
path: 'orderListShein',
name: 'orderListShein',
component: () => import('../view/shein/OrderListShein.vue')
},
{
path: 'returnRecordShein',
name: 'returnRecordShein',
component: () => import('../view/shein/ReturnRecordShein.vue')
},
// {
// path: 'statistics',

View File

@@ -114,9 +114,14 @@ const userCheck = (mallId) => {
})
}
const sleepSync = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
export default {
dict,
dateUtil,
sleepSync,
userCheck
}

View File

@@ -136,6 +136,7 @@
<el-menu-item index="/saleOut">售罄看板</el-menu-item>
<el-menu-item index="/afterSaleStat">售后统计</el-menu-item>
<el-menu-item index="/afterSaleDeductStat">售后赔付统计</el-menu-item>
<el-menu-item index="/priceAdjustment">调价管理</el-menu-item>
</el-submenu>
<el-submenu index="/shein">
<template slot="title">
@@ -146,6 +147,8 @@
<el-menu-item index="/saleDataShein">销售数据</el-menu-item>
<el-menu-item index="/certCenterShein">证书中心</el-menu-item>
<el-menu-item index="/copyProductShein">商品复制</el-menu-item>
<el-menu-item index="/orderListShein">发货订单</el-menu-item>
<el-menu-item index="/returnRecordShein">退货与报废单列表</el-menu-item>
<el-menu-item index="/saleStatShein">商家账单统计</el-menu-item>
</el-submenu>
<el-menu-item index="/info">
@@ -188,7 +191,7 @@
:close-on-click-modal="false"
width="1200">
<span style="font-size: large">1检查SHEIN商家后台是否登录如没登录请先登录之后再刷新助手<br></span>
<span style="font-size: large">2如果SHEIN商家后台已经登录仍然弹出当前窗口则需要SHEIN进行二次授权二次授权可在菜单商品管理->商品列表任意选择一个商品价格一栏点击修改在新打开的页面中可看到正在鉴权的字样即可完成二次授权</span>
<span style="font-size: large">2如果SHEIN商家后台已经登录仍然弹出当前窗口则需要SHEIN进行二次授权二次授权可在菜单商品管理->商品列表任意选择一个商品库存一栏点击修改在新打开的页面中可看到正在鉴权的字样即可完成二次授权</span>
<span slot="footer" class="dialog-footer">
<el-button @click="closeSheinAlert"> </el-button>
</span>

View File

@@ -311,7 +311,7 @@ import BiVueMindmap from "bi-vue-mindmap";
{
id: "01020102",
parentId: "010201",
title: "销售管理对应SHEIN商家后台“商品管理”->“备货信息”,统计当天的销售额、销量、库存等信息,计算成本和利润"
title: "销售管理对应SHEIN商家后台“商品管理”->“备货信息(新)”,统计当天的销售额、销量、库存等信息,计算成本和利润"
},
{
id: "01020103",
@@ -326,6 +326,16 @@ import BiVueMindmap from "bi-vue-mindmap";
{
id: "01020105",
parentId: "010201",
title: "发货订单对应SHEIN商家后台“订单管理”->“发货订单”,提供急采/备货订单的导出,同时带上成本价格,方便对账与结算"
},
{
id: "01020106",
parentId: "010201",
title: "退货与报废单列表对应SHEIN商家后台“质量管理”->“退货与报废单列表”,提供退货订单明细的导出,同时带上成本价格,方便对账与结算"
},
{
id: "01020107",
parentId: "010201",
title: "商家账单统计对应SHEIN商家后台“财务管理”->“商家账单”统计一段时期内销售额、单量、成本、利润、利润率SKC/SKU维度统计排名支持导出"
},
],

View File

@@ -136,7 +136,7 @@ import JsonExcel from 'vue-json-excel'
this.isLoading = true
let startTime = this.searchDate[0].getTime()
let endTime = this.searchDate[1].getTime()
let endTime = this.searchDate[1].getTime() + 86400000
while(true) {
if ((endTime - startTime) > 2592000000) {
this.reqData.pageNum = 1

View File

@@ -216,7 +216,7 @@ import { Message } from 'element-ui'
mallName: '',
type: '0',
isLoading: false,
pageSize: 100,
pageSize: 50,
currentPage: 1,
todayTotal: 0,
todayMoney: 0.0,
@@ -727,6 +727,7 @@ import { Message } from 'element-ui'
sendChromeAPIMessage({
url: 'marvel-mms/cn/api/kiana/venom/sales/management/listWarehouse',
needMallId: true,
anti: true,
mallId: this.mallId,
data: {
pageNo: this.currentPage,

View File

@@ -319,7 +319,7 @@ import { DualAxes } from '@antv/g2plot'
dateRange: null,
currentPage: 1,
pageSize: 100,
pageSize: 50,
productList: [],
productCostList: [],
saleAmount: 0.0,

View File

@@ -0,0 +1,256 @@
<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>
<json-excel
:data="tableData"
:fields="jsonFields"
name="调价列表.xls"
worksheet="调价列表">
<el-button type="primary" :disabled="tableData.length == 0">下载数据</el-button>
</json-excel>
</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="250px" :show-overflow-tooltip='true' label="商品名称" fixed="left">
<template slot-scope="scope">
<div>
<el-image :src="scope.row.image" style="width: 40px; height: 40px" class="image" :preview-src-list="[scope.row.image]" />
{{ 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 JsonExcel from 'vue-json-excel'
export default {
name: 'MyNormalOrder',
data () {
return {
form: {
mallId: ''
},
startPage: 1,
endPage: 10,
reqData: {
pageInfo: {
pageSize: 100,
pageNo: 1
},
status: 2
},
colConfigs: [
{ slot: 'productName', label: '商品名称', width: '250px', align: 'left', fixed: 'left' },
{ prop: 'priceOrderSn', label: '调价单号', width: '140px', align: 'left', fixed: 'left' },
{ prop: 'skcId', 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: 'skuExtCode', label: 'SKU货号', width: '100px', align: 'left' },
{ prop: 'spec', label: 'SKU属性', width: '100px', align: 'left' },
{ prop: 'priceBeforeExchange', label: '原申报价格', width: '100px', align: 'left' },
{ prop: 'newSupplyPrice', label: '调整后申报价格', width: '100px', align: 'left' },
{ prop: 'operateUserName', label: '操作人', width: '100px', align: 'left' },
{ prop: 'operateSourceName', label: '操作页面', width: '100px', align: 'left' },
{ prop: 'operateTime', label: '操作时间', width: '100px', align: 'left' },
{ prop: 'source', label: '申请来源', width: '120px', align: 'left' },
{ prop: 'adjustReason', label: '调价原因', align: 'left' }
],
isLoading: false,
tableData: [],
jsonFields: {
"商品名称": "productName",
"图片": "image",
"调价单号": "priceOrderSn",
"SKC ID": "skcId",
"SKC货号": "skcExtCode",
"SKU ID": "productSkuId",
"SKU货号": "skuExtCode",
"SKU属性": "spec",
"原申报价格": "priceBeforeExchange",
"调整后申报价格": "newSupplyPrice",
"操作人": "operateUserName",
"操作页面": "operateSourceName",
"操作时间": "operateTime",
"申请来源": "source",
"调价原因": "adjustReason"
},
currentIndex: 0
}
},
components: {
JsonExcel
},
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.reqData.pageInfo.pageNo = this.startPage
this.tableData = []
this.currentIndex = 0
this.isLoading = true
this.load()
},
async load() {
let res = await sendChromeAPIMessage({
url: 'marvel-mms/cn/api/kiana/magneto/price-adjust/page-query',
needMallId: true,
mallId: this.form.mallId,
anti: true,
data: this.reqData})
if (res.errorCode == 1000000) {
for(let i = 0;i < res.result.list.length; i++) {
let item = res.result.list[i];
let data = {};
data.id = item.id
data.productName = item.productName
data.image = item.image
data.priceOrderSn = item.priceOrderSn
data.skcId = item.skcId
data.skcExtCode = item.skcExtCode
data.source = item.source
data.adjustReason = item.adjustReason
data.newSupplyPrice = item.newSupplyPrice / 100
for(let k = 0; k < item.skuInfoItemList.length; k++) {
data = {...data,
productSkuId: item.skuInfoItemList[k].productSkuId,
priceBeforeExchange: item.skuInfoItemList[k].priceBeforeExchange / 100,
skuExtCode: item.skuInfoItemList[k].skuExtCode,
spec: item.skuInfoItemList[k].spec,
operateUserName: null,
operateTime: null,
operateSourceName: null
}
this.tableData.push(data)
}
}
if (res.result.list.length == this.reqData.pageInfo.pageSize && this.reqData.pageInfo.pageNo < this.endPage) {
this.reqData.pageInfo.pageNo ++
await this.load()
} else {
await this.getPriceAdjustLog()
this.isLoading = false
}
}
},
async getPriceAdjustLog() {
for (let i = 0; i < this.tableData.length; i++) {
let res = await sendChromeAPIMessage({
url: 'marvel-mms/cn/api/kiana/gmp/bg/magneto/api/price/adjust/log',
needMallId: true,
mallId: this.form.mallId,
anti: true,
data: {priceOrderId: this.tableData[i].id}})
if (res.errorCode == 1000000) {
if (res.result.list && res.result.list.length > 0) {
this.tableData[i].operateSourceName = res.result.list[res.result.list.length - 1].operateSourceName
this.tableData[i].operateTime = timestampToTime(res.result.list[res.result.list.length - 1].operateTime)
this.tableData[i].operateUserName = res.result.list[res.result.list.length - 1].operateUserName
}
}
}
}
}
}
</script>
<style scoped lang="scss">
.list {
.title-right {
display: flex;
align-items: center;
& > div:first-child {
margin-right: 20px;
}
}
::v-deep.ai-list {
.ai-list__content--right-wrapper {
background: transparent;
box-shadow: none;
padding: 0!important;
}
}
}
</style>

View File

@@ -49,6 +49,9 @@
<div class="search-item" style="width: 160px;">
<el-checkbox v-model="showTodaySale">只显示今日有销量</el-checkbox>
</div>
<div class="search-item">
<el-button type="primary" @click="exportToExcel">导出数据</el-button>
</div>
</template>
<ai-table
ref="table0"
@@ -78,6 +81,8 @@
import {sendGeiwohuoAPIMessage} from '@/api/chromeApi'
import JsonExcel from 'vue-json-excel'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'ExportSaleData',
@@ -142,8 +147,6 @@ import { Message } from 'element-ui'
}},
{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) => {
@@ -218,57 +221,79 @@ import { Message } from 'element-ui'
},
getList () {
sendGeiwohuoAPIMessage({
url: 'gmpj/goods/goods/list',
url: 'idms/goods-skc/list',
method: 'POST',
data: {
"mallStatusList": [
1
],
"page": this.currentPage,
"perPage": this.pageSize
"pageNumber": this.currentPage,
"pageSize": this.pageSize,
"supplierCodes": "",
"skcs": "",
"spu": "",
"c7dSaleCntBegin": "",
"c7dSaleCntEnd": "",
"goodsLevelIdList": [],
"supplyStatus": "",
"shelfStatus": "",
"categoryIdList": [],
"skcStockBegin": "",
"skcStockEnd": "",
"skuStockBegin": "",
"skuStockEnd": "",
"skcSaleDaysBegin": "",
"skcSaleDaysEnd": "",
"skuSaleDaysBegin": "",
"skuSaleDaysEnd": "",
"planUrgentCountBegin": "",
"planUrgentCountEnd": "",
"shelfDateBegin": "",
"shelfDateEnd": "",
"stockWarnStatusList": [],
"labelFakeIdList": [],
"tspIdList": [],
"sortBy7dSaleCnt": 2
}}).then((res) => {
if (res.code == '0' && res.msg == "OK") {
for(let i = 0;i < res.info.list.length; i++) {
let item = res.info.list[i];
let data = {};
data.categoryName = item.categoryName
data.goodsThumb = item.goodsThumb
data.mallStatusName = item.mallStatusName
data.goodsThumb = item.picUrl
data.mallStatusName = item.shelfStatus.name
data.supplierCode = item.supplierCode
data.skc = item.skc
for(let j = 0;j < item.sizes.length; j++) {
let sku = item.sizes[j]
data = {...data,
ableSaleDays: sku.ableSaleDays,
cost: sku.cost,
for(let j = 0;j < item.skuList.length; j++) {
let sku = item.skuList[j]
if (sku.attr == '合计') continue
let temp = {...data,
ableSaleDays: sku.saleDays,
cost: sku.price,
skuCode: sku.skuCode,
purchaseConfig: (sku.operateTime?sku.operateTime:'/') + '+' + (sku.prepareDay?sku.prepareDay:'/'),
saleInfoMonth: sku.saleInfoMonth,
saleInfoPreMonth: sku.saleInfoPreMonth,
saleInfoWeek: sku.saleInfoWeek,
suffixZh: sku.suffixZh,
todaySale: sku.todaySale,
onWayNum: sku.onWayNum,
ivtNum: sku.ivtNum,
purchaseConfig: (sku.goodsDate?sku.goodsDate:'/') + '+' + (sku.stockDays?sku.stockDays:'/'),
saleInfoMonth: sku.c30dSaleCnt,
saleInfoWeek: sku.c7dSaleCnt,
suffixZh: sku.attr,
todaySale: sku.totalSaleVolume,
onWayNum: sku.transit,
ivtNum: sku.stock,
costPrice: null,
todayProfit: null,
productTotalPrice: Math.round((sku.cost * sku.ivtNum)*100)/100,
inroadTotalPrice: Math.round((sku.cost * sku.onWayNum)*100)/100}
productTotalPrice: Math.round((sku.price * sku.stock)*100)/100,
inroadTotalPrice: Math.round((sku.price * sku.transit)*100)/100}
this.todayTotal += sku.todaySale
this.todayMoney += Math.round((sku.cost * sku.todaySale)*100)/100
this.todayTotal += temp.todaySale
this.todayMoney += Math.round((temp.cost * temp.todaySale)*100)/100
this.todayMoney = Math.round(this.todayMoney * 100) / 100
this.inventoryTotal += sku.ivtNum
this.inventoryMoney += Math.round((sku.cost * sku.ivtNum)*100)/100
this.inventoryTotal += temp.ivtNum
this.inventoryMoney += Math.round((temp.cost * temp.ivtNum)*100)/100
this.inventoryMoney = Math.round(this.inventoryMoney*100)/100
this.inroadTotal += sku.onWayNum
this.inroadTotalMoney += Math.round((sku.cost * sku.onWayNum)*100)/100
this.inroadTotal += temp.onWayNum
this.inroadTotalMoney += Math.round((temp.cost * temp.onWayNum)*100)/100
this.inroadTotalMoney = Math.round(this.inroadTotalMoney*100)/100
this.list.push(data);
this.list.push(temp);
}
}
if (this.pageSize == res.info.list.length) {
this.currentPage ++
setTimeout(() => {
@@ -312,6 +337,36 @@ import { Message } from 'element-ui'
this.costList = res.data
}
},
exportToExcel() {
// 假设你有一个表格数据的数组
const data = [
["图片地址", "货号", "规格", "分类", "状态", "SKC", "可售天数", "价格", "成本", "今日销量", "利润", "近7天销量", "本月销量", "在途数量", "库存数量", "库存货值", "在途货值", "备货逻辑"]
]
this.filteredData.map(item => {
data.push([item.goodsThumb, item.supplierCode, item.suffixZh, item.categoryName, item.mallStatusName, item.skc, item.ableSaleDays, item.cost, item.costPrice, item.todaySale, item.todayProfit, item.saleInfoWeek, item.saleInfoMonth, item.onWayNum, item.ivtNum, item.productTotalPrice, item.inroadTotalPrice, item.purchaseConfig])
})
// 将数据转换为工作表
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>

View File

@@ -42,18 +42,25 @@
<ai-card title="数据概览" style="padding-bottom: 40px;">
<div>
<el-row :gutter="20">
<el-col :span="5">
<el-col :span="4">
<div>
<el-statistic
title="销售额/单数"
title="销售额"
:value="saleAmount"
>
<template slot="formatter">
{{ saleAmount }}/{{ saleCount }}
</template>
</el-statistic>
</div>
</el-col>
<el-col :span="5">
<el-col :span="4">
<div>
<el-statistic
title="单数"
:value="saleCount"
>
</el-statistic>
</div>
</el-col>
<el-col :span="4">
<div>
<el-statistic
group-separator=","
@@ -64,7 +71,7 @@
</el-statistic>
</div>
</el-col>
<el-col :span="5">
<el-col :span="4">
<div>
<el-statistic
group-separator=","
@@ -74,7 +81,7 @@
></el-statistic>
</div>
</el-col>
<el-col :span="5">
<el-col :span="4">
<div>
<el-statistic
group-separator=","

View File

@@ -0,0 +1,323 @@
<template>
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
<ai-title
slot="title"
title="发货订单"
isShowBottomBorder>
<template #rightBtn>
<div class="title-right">
<div>
<label>订单状态</label>
<el-select v-model="reqData.status" multiple placeholder="请选择" size="small">
<el-option
v-for="item in statusList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
<div>
<label style="width:90px">下单时间</label>
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</div>
<el-button type="button" :class="'el-button el-button--primary'" @click="toSearch">查询</el-button>
</div>
</template>
</ai-title>
<template slot="content">
<ai-search-bar>
<template #left>
<el-radio-group v-model="type" @change="changeTab">
<el-radio-button label="urgent">急采</el-radio-button>
<el-radio-button label="normal">备货</el-radio-button>
</el-radio-group>
</template>
<template #right>
</template>
</ai-search-bar>
<ai-card :title="type == 'urgent' ? '急采订单列表': '备货订单列表'" style="padding-bottom: 40px;">
<template #right>
<el-button type="primary" @click="exportToExcel">导出</el-button>
</template>
<ai-table
:isShowPagination="false"
:tableData="tableData"
:col-configs="colConfigs"
height="700"
style="margin-top: 8px;"
@getList="() => {}">
</ai-table>
</ai-card>
</template>
</ai-list>
</template>
<script>
import {sendGeiwohuoAPIMessage} from '@/api/chromeApi'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'OrderListShein',
data () {
return {
isLoading: false,
storeCode: '',
type: 'urgent',
colConfigs: [
{ prop: 'orderNo', label: '订单号', align: 'left' },
{ prop: 'skc', label: 'SKC ID', align: 'left' },
{ prop: 'skuCode', label: 'SKU ID', align: 'left' },
{ prop: 'supplierCode', label: '货号', align: 'left' },
{ prop: 'supplierSku', label: 'SKU货号', align: 'left' },
{ prop: 'suffixZh', label: '属性集' },
{ prop: 'price', label: '申报价格' },
{ prop: 'costPrice', label: '成本价格' },
{ prop: 'orderQuantity', label: '下单数量', align: 'left' },
{ prop: 'needQuantity', label: '需求数量', align: 'left' },
{ prop: 'deliveryQuantity', label: '送货数量', align: 'left' },
{ prop: 'groundingQuantity', label: '正品数量', align: 'left' },
{ prop: 'defectiveQuantity', label: '次品数量', align: 'left' },
{ prop: 'addTime', label: '下单时间', align: 'left' }
],
tableData: [],
dateRange: [],
reqData: {
"page": 1,
"allocateTimeEnd": null,
"allocateTimeStart": null,
"deliveryNo": null,
"deliveryNos": [],
"deliveryTimeEnd": "",
"deliveryTimeStart": "",
"finishTimeEnd": "",
"finishTimeStart": "",
"ids": [],
"inspectionTimeEnd": "",
"inspectionTimeStart": "",
"launchTimeEnd": "",
"launchTimeStart": "",
"mode": "",
"orderColumn": "",
"orderType": 1,
"overdueTypes": [],
"prepareTypes": [],
"requestDeliveryTimeEnd": "",
"requestDeliveryTimeStart": "",
"requestTakeParcelTimeEnd": "",
"requestTakeParcelTimeStart": "",
"reserveDeliveryTimeEnd": "",
"reserveDeliveryTimeStart": "",
"sellerOrderNo": null,
"sellerOrderNos": [],
"skcName": null,
"skcNames": [],
"sourceOrderNoArray": [],
"status": [
2,
5
],
"suffixZh": "",
"supplierCode": null,
"supplierCodes": [],
"supplierSkuList": [],
"supplierSku": null,
"skuCodeList": [],
"skuCode": null,
"perPage": 200
},
statusList: [
{id: 2, name: '待发货'},
{id: 3, name: '已送货'},
{id: 4, name: '已收货'},
{id: 5, name: '已退货'},
{id: 6, name: '已完成'},
{id: 7, name: '已上架'},
{id: 8, name: '已作废'},
],
currentPage: 1,
productList: []
}
},
mounted () {
this.getStoreCode()
},
methods: {
toSearch() {
if (!this.dateRange) {
Message.error("请选择时间范围")
return
}
this.reqData.allocateTimeStart = this.dateRange[0]
this.reqData.allocateTimeEnd = this.dateRange[1]
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()
}
})
},
changeTab() {
this.tableData = []
},
async getList () {
this.isLoading = true
this.reqData.page = 1
this.tableData = []
if (this.type == 'urgent') {
this.reqData.orderType = '1'
} else {
this.reqData.orderType = '2'
}
await this.getOrderList()
this.isLoading = false
},
async getOrderList() {
let res = await sendGeiwohuoAPIMessage({
url: `pfmp/order/list`,
method: 'POST',
data: this.reqData})
if (res.code == '0') {
for(let i = 0;i < res.info.data.length; i++) {
let item = res.info.data[i];
let data = {
orderNo: item.orderId,
supplierCode: item.goods.supplierCode,
statusName: item.statusName,
skc: item.goods.skcName,
imgPath: item.goods.imgPath,
addTime: item.addTime
}
for (let j = 0; j < item.detail.length; j++) {
data = {...data,
skuCode: item.detail[j].skuCode,
price: item.detail[j].supplyPrice,
orderQuantity: item.detail[j].orderQuantity,
needQuantity: item.detail[j].needQuantity,
deliveryQuantity: item.detail[j].deliveryQuantity,
groundingQuantity: item.detail[j].groundingQuantity,
defectiveQuantity: item.detail[j].defectiveQuantity,
costPrice: null,
supplierSku: item.detail[j].supplierSku,
suffixZh: item.detail[j].suffixZh}
this.tableData.push(data)
}
}
if (res.info.data.length == 200 && (res.info.meta.count > 200*this.currentPage)) {
this.reqData.page++
await this.$sleepSync(200)
await this.getOrderList()
} else {
this.tableData.map(item => {
item.costPrice = this.getCost(item.skuCode)
})
}
} else if (res.code == 100004 || res.code == 20302) {
this.$store.commit("setSheinAlertShow", true)
}
},
async getStoreCode() {
let res = await sendGeiwohuoAPIMessage({
url: 'sso-prefix/auth/getUser?uuid=' + Date.now(),
method: 'GET'
})
if (res.code == '0' && res.msg == "OK") {
this.storeCode = res.info.merchantCode
this.getPorductList()
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
getCost(sku) {
for (let i = 0; i < this.productList.length; i++) {
if (sku == this.productList[i].sku) {
return this.productList[i].costPrice
}
}
return 0
},
getPorductList() {
this.$http.post(`/api/skuCost/listAll`, null, {
params: {
mallId: this.storeCode
}
}).then(res => {
if (res.code == 0) {
this.productList = res.data
}
})
},
exportToExcel() {
// 假设你有一个表格数据的数组
const data = [
["订单号", "SKC ID", "SKU ID", "图片地址", "货号", "SKU货号", "属性集", "申报价格", "成本价格", "下单数量","需求数量","送货数量", "正品数量", "次品数量", "下单时间"]
]
this.tableData.map(item => {
data.push([item.orderNo, item.skc, item.skuCode, item.imgPath, item.supplierCode, item.supplierSku, item.suffixZh, item.price, item.costPrice, item.orderQuantity, item.needQuantity, item.deliveryQuantity, item.certifiedQuantity, item.defectiveQuantity, item.addTime])
})
// 将数据转换为工作表
const worksheet = XLSX.utils.aoa_to_sheet(data);
// 创建工作簿并添加工作表
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 生成Excel文件
const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
// 使用blob和FileReader创建一个Blob URL
const dataBlob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
const blobUrl = window.URL.createObjectURL(dataBlob);
// 使用saveAs下载文件
saveAs(dataBlob, '订单列表.xlsx');
// 清理
window.URL.revokeObjectURL(blobUrl);
}
}
}
</script>
<style scoped lang="scss">
.list {
.title-right {
display: flex;
align-items: center;
& > div:first-child {
margin-right: 20px;
}
}
::v-deep.ai-list {
.ai-list__content--right-wrapper {
background: transparent;
box-shadow: none;
padding: 0!important;
}
}
}
</style>

View File

@@ -0,0 +1,265 @@
<template>
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
<ai-title
slot="title"
title="退货与报废单列表"
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 HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</div>
<el-button type="button" :class="'el-button el-button--primary'" @click="toSearch">查询</el-button>
</div>
</template>
</ai-title>
<template slot="content">
<ai-card title="退货列表" style="padding-bottom: 40px;">
<template #right>
<el-button type="primary" @click="exportToExcel">导出</el-button>
</template>
<ai-table
:isShowPagination="false"
:tableData="tableData"
:col-configs="colConfigs"
height="700"
style="margin-top: 8px;"
@getList="() => {}">
</ai-table>
</ai-card>
</template>
</ai-list>
</template>
<script>
import {sendGeiwohuoAPIMessage} from '@/api/chromeApi'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'ReturnRecordShein',
data () {
return {
isLoading: false,
storeCode: '',
colConfigs: [
{ prop: 'returnOrderNo', label: '单据号', align: 'left' },
{ prop: 'returnReasonTypeName', label: '发起原因', align: 'left' },
{ prop: 'returnReason', label: '说明', align: 'left' },
{ prop: 'returnOrderStatusName', label: '状态', align: 'left' },
{ prop: 'skc', label: 'SKC' },
{ prop: 'sku', label: 'SKU' },
{ prop: 'supplierCode', label: '供方货号', align: 'left' },
{ prop: 'supplierSku', label: 'SKU货号', align: 'left' },
{ prop: 'suffixZh', label: '属性集' },
{ prop: 'returnCount', label: '退货数量', align: 'left' },
{ prop: 'costPrice', label: '成本价格' },
{ prop: 'returnExpressCompanyName', label: '物流公司', align: 'left' },
{ prop: 'expressNoList', label: '物流单号', align: 'left' },
{ prop: 'addTime', label: '创建时间', align: 'left' }
],
tableData: [],
dateRange: [],
reqData: {
addTimeEnd: null,
addTimeStart: null,
page: 1,
perPage: 200
},
productList: [],
skcList: []
}
},
mounted () {
this.getStoreCode()
},
methods: {
toSearch() {
if (!this.dateRange) {
Message.error("请选择时间范围")
return
}
this.reqData.addTimeStart = this.dateRange[0]
this.reqData.addTimeEnd = this.dateRange[1]
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()
}
})
},
async getList () {
this.isLoading = true
this.reqData.page = 1
this.tableData = []
this.skcList = []
await this.getOrderList()
this.isLoading = false
},
async getOrderList() {
let res = await sendGeiwohuoAPIMessage({
url: `pfmp/returnOrder/page`,
method: 'POST',
data: this.reqData})
if (res.code == '0') {
for(let i = 0;i < res.info.data.length; i++) {
let item = res.info.data[i];
let data = {
returnOrderNo: item.returnOrderNo,
returnReasonTypeName: item.returnReasonTypeName,
returnReason: item.returnReason,
returnOrderStatusName: item.returnOrderStatusName,
addTime: item.addTime,
expressNoList: item.expressNoList,
returnExpressCompanyName: item.returnExpressCompanyName,
addTime: item.addTime
}
let detail = await sendGeiwohuoAPIMessage({
url: `pfmp/returnOrder/getReturnOrderGoodsDetail`,
method: 'POST',
data: {
"returnOrderId": item.id,
"skcList": [],
"supplierCode": "",
"supplierSkuList": [],
"platformSkuList": [],
"page": 1,
"perPage": 100
}})
if (detail.code == '0') {
detail.info.data.map(item2 => {
item2.details.map(item3 => {
let temp = {
...data,
skc: item2.skc,
sku: item3.platformSku,
returnCount: item3.preReturnQuantity,
suffixZh: item3.suffixZh,
supplierSku: item3.supplierSku,
supplierCode: item2.supplierCode,
costPrice: null
}
this.tableData.push(temp)
})
})
}
}
if (res.info.data.length == 200 && (res.info.meta.count > 200*this.currentPage)) {
this.reqData.page++
await this.$sleepSync(200)
await this.getOrderList()
} else {
this.tableData.map(item => {
item.costPrice = this.getCost(item.sku)
})
}
} else if (res.code == 100004 || res.code == 20302) {
this.$store.commit("setSheinAlertShow", true)
}
},
async getStoreCode() {
let res = await sendGeiwohuoAPIMessage({
url: 'sso-prefix/auth/getUser?uuid=' + Date.now(),
method: 'GET'
})
if (res.code == '0' && res.msg == "OK") {
this.storeCode = res.info.merchantCode
this.getPorductList()
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
getCost(sku) {
for (let i = 0; i < this.productList.length; i++) {
if (sku == this.productList[i].sku) {
return this.productList[i].costPrice
}
}
return 0
},
getPorductList() {
this.$http.post(`/api/skuCost/listAll`, null, {
params: {
mallId: this.storeCode
}
}).then(res => {
if (res.code == 0) {
this.productList = res.data
}
})
},
exportToExcel() {
// 假设你有一个表格数据的数组
const data = [
["单据号", "发起原因", "说明", "状态", "SKC", "SKU", "供方货号", "SKU货号", "属性集", "退货数量", "成本价格", "物流公司", "物流单号", "创建时间"]
]
this.tableData.map(item => {
data.push([item.returnOrderNo, item.returnReasonTypeName, item.returnReason, item.returnOrderStatusName, item.skc, item.sku, item.supplierCode, item.supplierSku, item.suffixZh, item.returnCount, item.costPrice, item.returnExpressCompanyName, item.expressNoList, item.addTime])
})
// 将数据转换为工作表
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>