397 lines
13 KiB
Vue
397 lines
13 KiB
Vue
<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>
|