Files
temu-plugin/src/view/shein/CostManageShein.vue
liushiwei 9c2b6c434c 调整
2024-10-19 17:44:22 +08:00

397 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
<ai-title
slot="title"
title="成本管理"
isShowBottomBorder>
</ai-title>
<template slot="content">
<div style="margin-bottom: 5px">
<el-alert
title="郑重承诺由于业务逻辑需要TEMU助手将会以最小范围内存储SKU成本信息平台将会做好保密不泄露、不出售任何数据。使用与成本管理以及利润计算等相关功能将视为授权TEMU助手存储相关信息。"
type="error"
:closable="false">
</el-alert>
</div>
<ai-search-bar>
<template #left>
<div class="search-item">
<el-checkbox v-model="search.unSet">只显示未填写</el-checkbox>
</div>
<div class="search-item">
<label>SKC ID</label>
<el-input size="small" clearable placeholder="请输入SKC ID" v-model="search.skc"></el-input>
</div>
<div class="search-item">
<label>SKU ID</label>
<el-input size="small" clearable placeholder="请输入SKU ID" v-model="search.sku"></el-input>
</div>
<div class="search-item">
<label>SKC货号</label>
<el-input size="small" clearable placeholder="请输入SKC货号" v-model="search.skcCode"></el-input>
</div>
</template>
<template #right>
<!--<el-button type="primary" @click="toLoad">加载</el-button>-->
</template>
</ai-search-bar>
<ai-card title="SKU明细" style="padding-bottom: 40px;">
<template #right>
<el-button type="primary" @click="exportToExcel">导出</el-button>
<el-button type="primary" @click="toUpload">导入</el-button>
</template>
<ai-table
:isShowPagination="false"
:tableData="filteredData"
:col-configs="colConfigs"
height="600"
style="margin-top: 8px;"
@getList="() => {}">
<el-table-column slot="costPrice" label="成本价格" :sortable="true" :sort-method="(a, b) => a.costPrice - b.costPrice">
<template slot-scope="{ row }">
<el-input
v-if="row.edit"
v-model="row.editValue"
type="number"
size="small"
></el-input>
<span v-else>{{ row.costPrice }}</span>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" width="80px" show-overflow-tooltip align="center" fixed="right">
<template slot-scope="{ row }">
<el-button
v-if="!row.edit"
size="small"
icon="el-icon-edit"
@click="row.edit = true"
></el-button>
<el-button
v-if="row.edit"
size="small"
type="success"
icon="el-icon-circle-check"
@click="handleSave(row)"
></el-button>
</template>
</el-table-column>
</ai-table>
</ai-card>
<AiDialog
title="成本导入"
:visible.sync="costDlgShow"
:close-on-click-modal="false"
customFooter
width="1290px">
<el-form :model="costForm" ref="costForm" label-width="180px" class="form">
<el-form-item label="上传excel" prop="file" :rules="[{ required: true, message: '请上传文件', trigger: 'blur' }]" style="width: 100%;">
<ai-uploader isImport v-model="costForm.file" fileType="file" :limit="1"
acceptType=".xlsx," :clearable="false">
<template #trigger>
<el-button icon="iconfont iconfangda">选择文件</el-button>
</template>
<template #tips>最多上传1个文件,单个文件最大10MB仅支持Excel格式</template>
</ai-uploader>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="costDlgShow = false">关 闭</el-button>
<el-button type="primary" @click="importConfirm">确 定</el-button>
</span>
</AiDialog>
</template>
</ai-list>
</template>
<script>
import {sendGeiwohuoAPIMessage} from '@/api/chromeApi'
import {timestampToTime} from '@/utils/date'
import { Message } from 'element-ui'
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export default {
name: 'CostManageShein',
data () {
return {
isLoading: false,
list: [],
mallId: '',
colConfigs: [
{ prop: 'skc', label: 'SKC ID', align: 'left' },
{ prop: 'skcCode', label: 'SKC货号', align: 'left' },
{ prop: 'sku', label: 'SKU ID', align: 'left' },
{ prop: 'skuAttr', label: '属性集', align: 'left' },
{ prop: 'skuCode', label: 'SKU货号', align: 'left' },
{ prop: 'price', label: '申报价格', align: 'left', sortable: true, 'sort-method': (a, b) => a.price - b.price },
{ slot: 'costPrice', label: '成本价格', align: 'left' },
{ prop: 'profitPercent', label: '利润率(%)', align: 'left', sortable: true, 'sort-method': (a, b) => a.profitPercent - b.profitPercent }
],
search: {
unSet: false,
skc: '',
sku: '',
skcCode: ''
},
tableData: [],
currentPage: 1,
costList: [],
costDlgShow: false,
costForm: {
file: null
}
}
},
computed: {
filteredData() {
const filteredData = this.list.filter(item => {
let flag1 = true, flag2 = true, flag3 = true, flag4 = true
if (this.search.unSet) {
if (item.costPrice) flag1 = false
}
if (this.search.skc) {
if (!item.skc.toLowerCase().includes(this.search.skc.toLowerCase())) {
flag2 = false
}
}
if (this.search.sku) {
if (!item.sku.toLowerCase().includes(this.search.sku.toLowerCase())) {
flag3 = false
}
}
if (this.search.skcCode) {
if (!item.skcCode.toLowerCase().includes(this.search.skcCode.toLowerCase())) {
flag4 = false
}
}
return flag1 && flag2 && flag3 && flag4
})
return filteredData
}
},
mounted () {
this.$http.post('/api/malluser/info').then(res => {
if (res.code == 0) {
this.$store.commit('setUserInfo', res.data)
if (res.data.flag != 1) {
Message.error('您的账号未激活或已失效,请激活后使用')
this.$store.commit('setActiveDlgShow', true)
return;
}
this.getUserInfo()
this.isLoading = true
}
})
},
methods: {
async getUserInfo() {
let res = await sendGeiwohuoAPIMessage({
url: 'sso-prefix/auth/getUser?uuid=' + Date.now(),
method: 'GET'
})
if (res.code == '0' && res.msg == "OK") {
this.mallId = res.info.merchantCode
this.getList([])
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
async getList (skcList) {
let res = await sendGeiwohuoAPIMessage({
url: `idms/goods-skc/list`,
method: 'POST',
data: {
pageNumber: this.currentPage,
pageSize: 100,
sortBy7dSaleCnt: 2
}})
if (res.code == '0') {
for(let i = 0;i < res.info.list.length; i++) {
let item = res.info.list[i];
let data = {skc: item.skc,
skcCode: item.supplierCode
}
skcList.push(item.skc)
for (let j = 0; j < item.skuList.length; j++) {
let sku = item.skuList[j]
if (sku.attr == '合计') continue
data = {...data, sku: sku.skuCode,
skuAttr: sku.attr,
skuCode: sku.supplierSku,
price: null,
costPrice: '',
profitPercent: null,
edit: false,
editValue: null
}
this.list.push(data)
}
}
if (res.info.list.length == 100 && (res.info.count > 100*this.currentPage)) {
this.currentPage++
await this.sleepSync(200)
await this.getList(skcList)
} else {
await this.getPriceInfo(skcList)
this.getSkuCostList()
}
} else if (res.code == 100004 || res.code == 20302) {
this.isLoading = false
this.$store.commit("setSheinAlertShow", true)
}
},
async getPriceInfo(skcList) {
let i = 0, len = 100
while(i < skcList.length) {
let tempSkcList = []
for (; i < skcList.length; i++) {
tempSkcList.push(skcList[i])
if (tempSkcList.length % len == 0) {
break
}
}
let res = await sendGeiwohuoAPIMessage({
url: `idms/goods-skc/price`,
method: 'POST',
data: tempSkcList})
if (res.code == '0') {
for (let key in res.info) {
for (let i = 0; i < this.list.length; i++) {
if (key == this.list[i].sku) {
this.list[i].price = res.info[key]
break
}
}
}
}
}
},
sleepSync(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
},
getSkuCostList() {
this.$http.post(`/api/skuCost/listAll`, null, {
params: {
mallId: this.mallId
}
}).then(res => {
if (res.code == 0) {
this.costList = res.data
for (let i = 0; i < this.costList.length; i++) {
for (let j = 0; j < this.list.length; j++) {
if (this.costList[i].sku == this.list[j].sku) {
this.list[j].costPrice = this.costList[i].costPrice
this.list[j].editValue = this.costList[i].costPrice
this.list[j].profitPercent = Math.round((this.list[j].price - this.list[j].costPrice) / this.list[j].price * 10000) /100
}
}
}
this.isLoading = false
}
})
},
handleSave(row) {
this.$http.post(`/api/skuCost/addOrUpdate`, [{
mallId: this.mallId,
costPrice: row.editValue,
skc: row.skc,
sku: row.sku
}]).then((res) => {
if (res.code == 0) {
row.edit = false
row.costPrice = row.editValue
row.profitPercent = Math.round((row.price - row.costPrice) / row.price * 10000) / 100
Message.success("修改成功")
}
})
},
toUpload() {
this.costDlgShow = true
},
importConfirm() {
this.isLoading = true
this.$refs.costForm.validate((valid) => {
const data = new FormData()
data.append('file', this.costForm.file[0].raw);
this.$http.post(`/api/skuCost/importStock`, data).then(res => {
if (res.code === 0) {
this.costDlgShow = false
this.$message.success('导入成功')
this.currentPage = 1
this.list = []
this.isLoading = false
this.getList()
} else {
this.isLoading = false
}
})
})
},
exportToExcel() {
// 假设你有一个表格数据的数组
const data = [
["店铺ID", "SKC ID", "SKC货号", "SKU ID", "属性集", "SKU货号", "申报价格", "成本价格"]
]
this.filteredData.map(item => {
data.push([this.mallId, item.skc, item.skcCode, item.sku, item.skuAttr, item.skuCode, item.price, item.costPrice])
})
// 将数据转换为工作表
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, 'SKU列表.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>