Browse Source

期初导入

master
常熟吴彦祖 4 weeks ago
parent
commit
6dfc9910c9
  1. 29
      src/api/initialImport.js
  2. 382
      src/views/modules/sys/initialImport.vue

29
src/api/initialImport.js

@ -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
})

382
src/views/modules/sys/initialImport.vue

@ -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>
Loading…
Cancel
Save