397 lines
11 KiB
Vue
397 lines
11 KiB
Vue
<template>
|
||
<div class="container">
|
||
<div class="filter">
|
||
<el-input
|
||
class="input_item"
|
||
placeholder="输入商品名称"
|
||
prefix-icon="el-icon-search"
|
||
v-model="filter.productName"
|
||
clearable
|
||
></el-input>
|
||
<el-select
|
||
v-model="filter.storeId"
|
||
placeholder="选择店铺"
|
||
filterable
|
||
clearable
|
||
>
|
||
<el-option
|
||
v-for="item in shopList"
|
||
:key="item.store_id"
|
||
:label="item.store_name"
|
||
:value="item.store_id"
|
||
></el-option>
|
||
</el-select>
|
||
|
||
<el-button type="primary" size="medium" @click="getGoodsList">
|
||
搜索
|
||
</el-button>
|
||
</div>
|
||
|
||
<div class="list">
|
||
<div class="tool">
|
||
<el-button type="primary" @click="openBatchAdd">批量新增</el-button>
|
||
|
||
<el-button
|
||
type="success"
|
||
@click="handleExport"
|
||
:disabled="!selectedRowKeys.length"
|
||
>
|
||
导出数据
|
||
</el-button>
|
||
|
||
<el-upload
|
||
action=""
|
||
:show-file-list="false"
|
||
:limit="1"
|
||
:before-upload="beforeGoodsDataUpload"
|
||
>
|
||
<el-button type="warning">导入数据</el-button>
|
||
</el-upload>
|
||
|
||
<el-button type="danger" @click="HandleSyncGoods">同步数据</el-button>
|
||
|
||
<el-popover placement="bottom" :width="400" trigger="click">
|
||
<template slot="reference">
|
||
<el-button>下载错误报告</el-button>
|
||
</template>
|
||
<div>
|
||
<el-input v-model="errReportFilePath" placeholder="输入文件地址">
|
||
<template slot="append">
|
||
<el-button
|
||
type="primary"
|
||
size="medium"
|
||
@click="HandleDownloadErrorReport"
|
||
>
|
||
确定
|
||
</el-button>
|
||
</template>
|
||
</el-input>
|
||
</div>
|
||
</el-popover>
|
||
|
||
<el-button type="info" plain @click="handleSyncProductMaping">
|
||
自动计算并上架商品
|
||
</el-button>
|
||
</div>
|
||
<el-table
|
||
:data="tableData"
|
||
style="width: 100%"
|
||
@selection-change="handleSelectionChange"
|
||
ref="productTable"
|
||
>
|
||
<el-table-column type="selection" width="55"></el-table-column>
|
||
<el-table-column prop="id" label="ID" />
|
||
<el-table-column prop="storeId" label="店铺ID" />
|
||
<el-table-column prop="productName" label="商品名称" />
|
||
<el-table-column prop="description" label="商品描述" />
|
||
<el-table-column prop="specValue" label="商品规格">
|
||
<template #default="scope">
|
||
{{ scope.row.specValue }}{{ scope.row.specUnit }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="400">
|
||
<template #default="scope">
|
||
<el-button
|
||
size="mini"
|
||
type="primary"
|
||
plain
|
||
@click="editGoods(scope.row)"
|
||
>
|
||
编辑配置
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="danger"
|
||
plain
|
||
@click="handleDelete(scope.row)"
|
||
>
|
||
删除配置
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="info"
|
||
plain
|
||
@click="downloadTemplate(scope.row)"
|
||
>
|
||
下载模板
|
||
</el-button>
|
||
<el-button
|
||
size="mini"
|
||
type="success"
|
||
plain
|
||
@click="getProductMapping(scope.row)"
|
||
>
|
||
店铺商品映射
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<el-pagination
|
||
background
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:current-page="pagination.pageNum"
|
||
:page-size="pagination.pageSize"
|
||
:total="pagination.total"
|
||
@current-change="handleCurrentChange"
|
||
@size-change="handleSizeChange"
|
||
/>
|
||
</div>
|
||
|
||
<GoodsItem
|
||
ref="batchFormRef"
|
||
:mode="formMode"
|
||
:initialData="formData"
|
||
:shopListData="shopList"
|
||
@success="handleSuccess"
|
||
></GoodsItem>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import GoodsToolApi from '@/api/goodsTool'
|
||
import GoodsItem from './GoodsItem.vue'
|
||
|
||
export default {
|
||
components: {
|
||
GoodsItem,
|
||
},
|
||
data() {
|
||
return {
|
||
filter: {
|
||
productName: '',
|
||
storeId: '',
|
||
},
|
||
pagination: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
total: 0,
|
||
},
|
||
shopList: [],
|
||
tableData: [],
|
||
selectedRowKeys: [],
|
||
formMode: 'add',
|
||
formData: [],
|
||
apiUrl: '/api/products',
|
||
errReportFilePath: '',
|
||
}
|
||
},
|
||
mounted() {
|
||
this.getShopList()
|
||
this.getGoodsList()
|
||
},
|
||
methods: {
|
||
async getGoodsList() {
|
||
let res = await GoodsToolApi.getProductMapperList({
|
||
...this.filter,
|
||
pageNum: this.pagination.pageNum,
|
||
pageSize: this.pagination.pageSize,
|
||
})
|
||
this.tableData = res.data.items
|
||
this.pagination.total = res.data.records
|
||
},
|
||
|
||
async getShopList() {
|
||
let res = await GoodsToolApi.getShopList()
|
||
this.shopList = res.data.items
|
||
},
|
||
|
||
handleCurrentChange(val) {
|
||
this.pagination.pageNum = val
|
||
this.getGoodsList()
|
||
},
|
||
|
||
handleSizeChange(val) {
|
||
this.pagination.pageSize = val
|
||
this.getGoodsList()
|
||
},
|
||
|
||
openBatchAdd() {
|
||
this.formMode = 'add'
|
||
this.formData = []
|
||
this.$refs.batchFormRef.open()
|
||
},
|
||
|
||
openBatchEdit() {
|
||
const selectedProducts = this.tableData.filter((item) => item.selected)
|
||
|
||
if (selectedProducts.length === 0) {
|
||
this.$message.warning('请先选择要编辑的商品')
|
||
return
|
||
}
|
||
|
||
this.formMode = 'edit'
|
||
this.formData = selectedProducts
|
||
this.$refs.batchFormRef.open()
|
||
},
|
||
|
||
editGoods(data) {
|
||
this.formMode = 'edit'
|
||
this.formData = [data]
|
||
this.$refs.batchFormRef.open()
|
||
},
|
||
|
||
async getProductMapping(data) {
|
||
this.$confirm('确定要映射选中的商品配置吗?', '友情提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'danger',
|
||
}).then(async () => {
|
||
console.log(data)
|
||
const res = await GoodsToolApi.getProductMapping({ id: data.id })
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
this.getProductMapperList()
|
||
}
|
||
})
|
||
},
|
||
|
||
handleSuccess(data) {
|
||
this.fetchProductList()
|
||
},
|
||
|
||
handleSelectionChange(selection) {
|
||
this.selectedRowKeys = selection.map((item) => item.id)
|
||
},
|
||
|
||
handleDelete(data) {
|
||
this.$confirm(
|
||
'确定要删除选中的商品配置吗?此操作不可撤销。',
|
||
'友情提示',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'danger',
|
||
}
|
||
).then(async () => {
|
||
console.log(data)
|
||
const res = await GoodsToolApi.deleteGoods({ id: data.id })
|
||
if (res.status == 200) {
|
||
this.$message.success('已删除')
|
||
this.getProductMapperList()
|
||
}
|
||
})
|
||
},
|
||
|
||
HandleSyncGoods() {
|
||
this.$confirm('确定要获取同步未分配的商品数据?', '友情提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'danger',
|
||
}).then(async () => {
|
||
const res = await GoodsToolApi.getSyncBaseMapingProducts()
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
this.getProductMapperList()
|
||
}
|
||
})
|
||
},
|
||
|
||
async HandleDownloadErrorReport() {
|
||
if (!this.errReportFilePath) {
|
||
this.$message.warning('请输入文件地址')
|
||
return
|
||
}
|
||
const res = await GoodsToolApi.HandleDownloadErrorReport({
|
||
file: this.errReportFilePath,
|
||
})
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
this.downloadFile(res.data, `${this.errReportFilePath}.xlsx`)
|
||
}
|
||
},
|
||
|
||
async handleSyncProductMaping() {
|
||
const res = await GoodsToolApi.syncProductMaping()
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
}
|
||
},
|
||
|
||
async handleExport() {
|
||
if (!this.selectedRowKeys.length) {
|
||
this.$message.warning('请先选择要导出的商品')
|
||
return
|
||
}
|
||
|
||
const res = await GoodsToolApi.batchExportGoods(this.selectedRowKeys)
|
||
if (res.status == 200) {
|
||
this.downloadFile(response.data, '商品映射实体数据.xlsx')
|
||
}
|
||
},
|
||
|
||
async beforeGoodsDataUpload(file) {
|
||
const name = file.name.toLocaleLowerCase()
|
||
if (!name.endsWith('.xlsx') || !name.endsWith('.csv')) {
|
||
this.$message.error('文件格式错误,仅支持xlsx或csv格式')
|
||
return
|
||
}
|
||
handleImportGoodsData(file)
|
||
},
|
||
|
||
async handleImportGoodsData(file) {
|
||
const data = new FormData()
|
||
data.append('file', file)
|
||
const res = await GoodsToolApi.importGoodsData(data)
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
}
|
||
},
|
||
|
||
async downloadTemplate(data) {
|
||
const res = await GoodsToolApi.downloadTempGoods({ id: data.id })
|
||
if (res.status == 200) {
|
||
this.$message.success('操作成功')
|
||
this.downloadFile(res, '商品商品映射数据模板.xlsx')
|
||
}
|
||
},
|
||
|
||
downloadFile(blobData, fileName) {
|
||
const url = window.URL.createObjectURL(new Blob([blobData]))
|
||
|
||
const link = document.createElement('a')
|
||
link.href = url
|
||
link.setAttribute('download', fileName)
|
||
|
||
document.body.appendChild(link)
|
||
link.click()
|
||
|
||
document.body.removeChild(link)
|
||
window.URL.revokeObjectURL(url)
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.filter {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20px;
|
||
margin: 20px;
|
||
gap: 10px;
|
||
border-radius: 5px;
|
||
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
|
||
|
||
.input_item {
|
||
width: 250px;
|
||
}
|
||
}
|
||
.list {
|
||
padding: 20px;
|
||
margin: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
border-radius: 5px;
|
||
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
|
||
}
|
||
.tool {
|
||
display: flex;
|
||
gap: 10px;
|
||
::v-deep .el-button {
|
||
margin-left: 0 !important;
|
||
}
|
||
}
|
||
</style>
|