2 changed files with 411 additions and 0 deletions
@ -0,0 +1,29 @@ |
|||
import http from '@/utils/httpRequest' |
|||
|
|||
export const downloadSupplierPriceTemplate = () => http({ |
|||
url: http.adornUrl('/sys/initialImport/supplierPrice/template'), |
|||
method: 'get', |
|||
responseType: 'blob' |
|||
}) |
|||
|
|||
export const previewSupplierPrice = (file, site) => { |
|||
const formData = new FormData() |
|||
formData.append('file', file) |
|||
formData.append('site', site) |
|||
return http({ |
|||
url: http.adornUrl('/sys/initialImport/supplierPrice/preview'), |
|||
method: 'post', |
|||
data: formData, |
|||
headers: { |
|||
'Content-Type': 'multipart/form-data' |
|||
}, |
|||
timeout: 120000 |
|||
}) |
|||
} |
|||
|
|||
export const saveSupplierPrice = data => http({ |
|||
url: http.adornUrl('/sys/initialImport/supplierPrice/save'), |
|||
method: 'post', |
|||
data: http.adornData(data), |
|||
timeout: 600000 |
|||
}) |
|||
@ -0,0 +1,382 @@ |
|||
<template> |
|||
<div class="mod-initial-import"> |
|||
<div class="page-toolbar"> |
|||
<div> |
|||
<div class="page-title">期初导入</div> |
|||
<div class="page-subtitle">按业务类型导入系统启用前的基础数据</div> |
|||
</div> |
|||
</div> |
|||
<div class="rq"> |
|||
<el-table :data="importItems" border style="width: 100%"> |
|||
<el-table-column prop="name" label="期初导入功能" min-width="220" /> |
|||
<el-table-column prop="description" label="说明" min-width="520" show-overflow-tooltip /> |
|||
<el-table-column label="操作" width="220" align="center"> |
|||
<template slot-scope="scope"> |
|||
<el-button |
|||
type="primary" |
|||
icon="el-icon-upload2" |
|||
@click="openImportDialog(scope.row.type)"> |
|||
{{ scope.row.name }} |
|||
</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</div> |
|||
<el-dialog |
|||
title="供应商价格期初导入" |
|||
v-drag |
|||
:visible.sync="dialogVisible" |
|||
width="94%" |
|||
top="5vh" |
|||
:show-close="!saving" |
|||
:close-on-click-modal="false" |
|||
:close-on-press-escape="!saving" |
|||
:before-close="handleDialogClose" |
|||
@closed="resetDialog"> |
|||
<div class="dialog-toolbar"> |
|||
<el-button |
|||
type="primary" |
|||
icon="el-icon-download" |
|||
:loading="templateDownloading" |
|||
:disabled="previewLoading || saving" |
|||
@click="handleDownloadTemplate"> |
|||
下载导入模板 |
|||
</el-button> |
|||
<el-upload |
|||
ref="supplierPriceUpload" |
|||
action="#" |
|||
accept=".xls,.xlsx" |
|||
:auto-upload="false" |
|||
:show-file-list="false" |
|||
:limit="1" |
|||
:disabled="previewLoading || saving" |
|||
:on-change="handleFileChange" |
|||
:on-exceed="handleFileExceed"> |
|||
<el-button |
|||
icon="el-icon-upload2" |
|||
:loading="previewLoading" |
|||
:disabled="previewLoading || saving"> |
|||
选择导入文件 |
|||
</el-button> |
|||
</el-upload> |
|||
<span class="file-name" :title="fileName">{{ fileName || '未选择文件' }}</span> |
|||
<span class="preview-count">已读取 {{ previewRows.length }} 行</span> |
|||
</div> |
|||
|
|||
<el-table |
|||
v-loading="previewLoading" |
|||
:data="previewRows" |
|||
border |
|||
height="520" |
|||
size="mini" |
|||
empty-text="请选择Excel文件进行预览" |
|||
:row-class-name="previewRowClassName" |
|||
class="supplier-price-preview"> |
|||
<el-table-column |
|||
v-for="column in columns" |
|||
:key="column.prop" |
|||
:prop="column.prop" |
|||
:label="column.label" |
|||
:min-width="column.width" |
|||
:align="column.align" |
|||
show-overflow-tooltip /> |
|||
</el-table> |
|||
|
|||
<div slot="footer" class="dialog-footer"> |
|||
<el-button |
|||
type="primary" |
|||
icon="el-icon-check" |
|||
:loading="saving" |
|||
:disabled="previewLoading || saving || !previewRows.length" |
|||
@click="handleSave"> |
|||
保存 |
|||
</el-button> |
|||
<el-button :disabled="previewLoading || saving" @click="dialogVisible = false">关闭</el-button> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { |
|||
downloadSupplierPriceTemplate, |
|||
previewSupplierPrice, |
|||
saveSupplierPrice |
|||
} from '@/api/initialImport' |
|||
|
|||
export default { |
|||
name: 'SysInitialImport', |
|||
data () { |
|||
return { |
|||
importItems: [ |
|||
{ |
|||
type: 'supplierPrice', |
|||
name: '供应商价格期初导入', |
|||
description: '导入供应商物料的MOQ、阶梯数量和阶梯价格。' |
|||
} |
|||
], |
|||
dialogVisible: false, |
|||
previewLoading: false, |
|||
saving: false, |
|||
templateDownloading: false, |
|||
fileName: '', |
|||
previewRows: [], |
|||
missingItems: [], |
|||
missingSuppliers: [], |
|||
columns: [ |
|||
{ prop: 'rawCode', label: 'RAW CODE', width: 120, align: 'center' }, |
|||
{ prop: 'supplier', label: 'Short_NPC', width: 100, align: 'center' }, |
|||
{ prop: 'moqColor', label: 'MOQ/COLOR', width: 80, align: 'center' }, |
|||
{ prop: 'startDate', label: 'START DATE', width: 100, align: 'center' }, |
|||
{ prop: 'tierQty1', label: 'Tier_QTY_1', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty2', label: 'Tier_QTY_2', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty3', label: 'Tier_QTY_3', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty4', label: 'Tier_QTY_4', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty5', label: 'Tier_QTY_5', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty6', label: 'Tier_QTY_6', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty7', label: 'Tier_QTY_7', width: 80, align: 'center' }, |
|||
{ prop: 'tierQty8', label: 'Tier_QTY_8', width: 80, align: 'center' }, |
|||
{ prop: 'priceTier1', label: 'Price_Tier_1', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier2', label: 'Price_Tier_2', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier3', label: 'Price_Tier_3', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier4', label: 'Price_Tier_4', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier5', label: 'Price_Tier_5', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier6', label: 'Price_Tier_6', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier7', label: 'Price_Tier_7', width: 90, align: 'center' }, |
|||
{ prop: 'priceTier8', label: 'Price_Tier_8', width: 90, align: 'center' } |
|||
] |
|||
} |
|||
}, |
|||
methods: { |
|||
openImportDialog (type) { |
|||
if (type !== 'supplierPrice') { |
|||
return |
|||
} |
|||
this.dialogVisible = true |
|||
}, |
|||
handleFileChange (file) { |
|||
const rawFile = file && file.raw |
|||
if (!rawFile) { |
|||
return |
|||
} |
|||
const site = this.$store.state.user.site |
|||
if (!site) { |
|||
this.$message.error('当前登录用户没有Site') |
|||
this.clearSelectedFile() |
|||
return |
|||
} |
|||
this.fileName = file.name || '' |
|||
this.previewRows = [] |
|||
this.missingItems = [] |
|||
this.missingSuppliers = [] |
|||
this.previewLoading = true |
|||
previewSupplierPrice(rawFile, site).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
this.previewRows = data.data || [] |
|||
this.missingItems = data.missingItems || [] |
|||
this.missingSuppliers = data.missingSuppliers || [] |
|||
this.$message.success(`Excel读取成功,共${this.previewRows.length}行`) |
|||
this.showMissingDataAlert() |
|||
} else { |
|||
this.$message.error((data && data.msg) || 'Excel读取失败') |
|||
this.clearSelectedFile() |
|||
} |
|||
}).catch(error => { |
|||
const message = error && error.response && error.response.data && error.response.data.msg |
|||
? error.response.data.msg |
|||
: 'Excel读取失败,请检查文件格式' |
|||
this.$message.error(message) |
|||
this.clearSelectedFile() |
|||
}).finally(() => { |
|||
this.previewLoading = false |
|||
}) |
|||
}, |
|||
handleFileExceed (files) { |
|||
if (this.previewLoading || !files || !files.length) { |
|||
return |
|||
} |
|||
this.clearSelectedFile() |
|||
this.handleFileChange({ raw: files[0], name: files[0].name }) |
|||
}, |
|||
handleDownloadTemplate () { |
|||
this.templateDownloading = true |
|||
downloadSupplierPriceTemplate().then(response => { |
|||
const blob = new Blob([response.data], { |
|||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|||
}) |
|||
const url = window.URL.createObjectURL(blob) |
|||
const link = document.createElement('a') |
|||
link.href = url |
|||
link.download = '供应商价格期初导入模板.xlsx' |
|||
document.body.appendChild(link) |
|||
link.click() |
|||
document.body.removeChild(link) |
|||
window.URL.revokeObjectURL(url) |
|||
}).catch(() => { |
|||
this.$message.error('模板下载失败,请联系管理员') |
|||
}).finally(() => { |
|||
this.templateDownloading = false |
|||
}) |
|||
}, |
|||
handleSave () { |
|||
if (!this.previewRows.length) { |
|||
this.$message.warning('没有可保存的导入数据') |
|||
return |
|||
} |
|||
const site = this.$store.state.user.site |
|||
if (!site) { |
|||
this.$message.error('当前登录用户没有Site') |
|||
return |
|||
} |
|||
const invalidCount = this.previewRows.filter(row => row && row.valid === false).length |
|||
if (invalidCount > 0) { |
|||
this.$confirm( |
|||
`存在${invalidCount}行淡黄色数据。如果继续保存,不存在的数据行将跳过,是否继续?`, |
|||
'数据校验提示', |
|||
{ |
|||
confirmButtonText: '继续保存', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
} |
|||
).then(() => { |
|||
this.performSave(site) |
|||
}).catch(() => {}) |
|||
return |
|||
} |
|||
this.performSave(site) |
|||
}, |
|||
performSave (site) { |
|||
this.saving = true |
|||
saveSupplierPrice({ |
|||
site, |
|||
rows: this.previewRows |
|||
}).then(({ data }) => { |
|||
if (data && data.code === 0) { |
|||
const savedCount = data.savedCount == null ? this.previewRows.length : data.savedCount |
|||
const skippedCount = data.skippedCount || 0 |
|||
const skippedText = skippedCount > 0 ? `,跳过${skippedCount}行` : '' |
|||
this.$message.success(`保存完成,成功${savedCount}行${skippedText}`) |
|||
this.dialogVisible = false |
|||
} else { |
|||
this.$message.error((data && data.msg) || '保存失败') |
|||
} |
|||
}).catch(error => { |
|||
const message = error && error.response && error.response.data && error.response.data.msg |
|||
? error.response.data.msg |
|||
: '保存失败,请稍后重试' |
|||
this.$message.error(message) |
|||
}).finally(() => { |
|||
this.saving = false |
|||
}) |
|||
}, |
|||
showMissingDataAlert () { |
|||
if (!this.missingItems.length && !this.missingSuppliers.length) { |
|||
return |
|||
} |
|||
const messages = [] |
|||
if (this.missingItems.length) { |
|||
messages.push(`以下Item不存在:${this.missingItems.join('、')}`) |
|||
} |
|||
if (this.missingSuppliers.length) { |
|||
messages.push(`以下供应商简称不存在:${this.missingSuppliers.join('、')}`) |
|||
} |
|||
const content = this.$createElement( |
|||
'div', |
|||
{ style: { maxHeight: '360px', overflowY: 'auto', wordBreak: 'break-all', lineHeight: '1.6' } }, |
|||
messages.map(message => this.$createElement('p', { style: { margin: '0 0 8px' } }, message)) |
|||
) |
|||
this.$alert(content, '数据校验提示', { |
|||
confirmButtonText: '确定', |
|||
type: 'warning' |
|||
}).catch(() => {}) |
|||
}, |
|||
previewRowClassName ({ row }) { |
|||
return row && row.valid === false ? 'initial-import-warning-row' : '' |
|||
}, |
|||
handleDialogClose (done) { |
|||
if (!this.saving) { |
|||
done() |
|||
} |
|||
}, |
|||
clearSelectedFile () { |
|||
this.fileName = '' |
|||
if (this.$refs.supplierPriceUpload) { |
|||
this.$refs.supplierPriceUpload.clearFiles() |
|||
} |
|||
}, |
|||
resetDialog () { |
|||
this.previewLoading = false |
|||
this.saving = false |
|||
this.templateDownloading = false |
|||
this.previewRows = [] |
|||
this.missingItems = [] |
|||
this.missingSuppliers = [] |
|||
this.clearSelectedFile() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.mod-initial-import { |
|||
padding: 16px; |
|||
} |
|||
|
|||
.page-toolbar { |
|||
display: flex; |
|||
align-items: flex-end; |
|||
justify-content: space-between; |
|||
margin-bottom: 14px; |
|||
} |
|||
|
|||
.page-title { |
|||
color: #303133; |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
} |
|||
|
|||
.page-subtitle { |
|||
margin-top: 4px; |
|||
color: #909399; |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.dialog-toolbar { |
|||
display: flex; |
|||
align-items: center; |
|||
min-height: 40px; |
|||
margin-bottom: 12px; |
|||
gap: 10px; |
|||
} |
|||
|
|||
.file-name { |
|||
display: inline-block; |
|||
max-width: 360px; |
|||
overflow: hidden; |
|||
color: #606266; |
|||
text-overflow: ellipsis; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
.preview-count { |
|||
margin-left: auto; |
|||
color: #606266; |
|||
font-variant-numeric: tabular-nums; |
|||
} |
|||
|
|||
.supplier-price-preview { |
|||
width: 100%; |
|||
} |
|||
|
|||
.supplier-price-preview /deep/ .initial-import-warning-row > td { |
|||
background-color: #fff7d6 !important; |
|||
} |
|||
|
|||
.supplier-price-preview /deep/ .initial-import-warning-row:hover > td { |
|||
background-color: #fff0b3 !important; |
|||
} |
|||
|
|||
.dialog-footer { |
|||
text-align: right; |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue