Commit bf9f35cc by wangyalan-git

物品新增和导入物品

parent bf15f9b2
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<el-button type="primary" @click="handleAdd">新增</el-button> <el-button type="primary" @click="handleAdd">新增</el-button>
<el-button type="success" @click="handleAdd">扫码入库</el-button> <el-button type="success" @click="handleAdd">扫码入库</el-button>
<el-button type="info" @click="handleAdd">扫码出库</el-button> <el-button type="info" @click="handleAdd">扫码出库</el-button>
<el-button type="warning" @click="handleAdd">导入</el-button> <el-button type="warning" @click="handleImport">导入</el-button>
</el-row> </el-row>
<div class="table-container"> <div class="table-container">
<el-table :data="list" <el-table :data="list"
...@@ -119,14 +119,16 @@ ...@@ -119,14 +119,16 @@
</div> </div>
</el-card> </el-card>
<!-- 弹窗--> <!-- 弹窗-->
<add-goods ref="addGoods" @ok="getList"></add-goods> <add-goods-modal ref="addGoods" @ok="getList"></add-goods-modal>
<import-goods-modal ref="importGoods" @ok="getList"></import-goods-modal>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment' import moment from 'moment'
import { getGoodsList,getGoodsCategoryList,getStockRooms, getAuditDetail, updateMcht } from '@/api/inventory' import { getGoodsList,getGoodsCategoryList,getStockRooms, getAuditDetail, updateMcht } from '@/api/inventory'
import {getSuppliersList} from '@/api/supplier' import {getSuppliersList} from '@/api/supplier'
import AddGoods from './modules/addGoodsModal' import AddGoodsModal from './modules/addGoodsModal'
import ImportGoodsModal from './modules/importGoodsModal'
// 列表查询参数默认值 // 列表查询参数默认值
const defaultListQuery = { const defaultListQuery = {
pageNum: 1, pageNum: 1,
...@@ -139,7 +141,10 @@ const defaultListQuery = { ...@@ -139,7 +141,10 @@ const defaultListQuery = {
export default { export default {
name: 'StoreList', name: 'StoreList',
components: {AddGoods}, components: {
AddGoodsModal,
ImportGoodsModal
},
data() { data() {
return { return {
listQuery: Object.assign({}, defaultListQuery), listQuery: Object.assign({}, defaultListQuery),
...@@ -218,8 +223,13 @@ export default { ...@@ -218,8 +223,13 @@ export default {
this.listLoading = false this.listLoading = false
}) })
}, },
// 新增
handleAdd(){ handleAdd(){
this.$refs.addGoods.add() this.$refs.addGoods.add()
},
// 导入
handleImport(){
this.$refs.importGoods.add()
} }
} }
} }
......
...@@ -13,11 +13,12 @@ ...@@ -13,11 +13,12 @@
<el-table <el-table
:data="formData.tableData" :data="formData.tableData"
style="width: 100%" style="width: 100%"
@row-dblclick="dbclick"> @row-dblclick="dbclick"
:row-class-name="tableRowClassName">
<el-table-column prop="name" label="物品名称"> <el-table-column prop="name" label="物品名称">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'" <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'"
:rules="[{required: true,trigger: 'blur',message: '物品名称不能为空'}]"> :rules="[{required: true,trigger: 'change',message: '物品名称不能为空'}]">
<el-autocomplete <el-autocomplete
class="input-width" class="input-width"
v-model="scope.row.name" v-model="scope.row.name"
...@@ -230,8 +231,12 @@ export default { ...@@ -230,8 +231,12 @@ export default {
isOK: true isOK: true
},) },)
}, },
tableRowClassName ({row, rowIndex}) {
// 把每一行的索引放进row
row.index = rowIndex;
},
dbclick(row, event, column) { dbclick(row, event, column) {
for (var i of this.tableData) { for (var i of this.formData.tableData) {
i.isOK = false i.isOK = false
} }
row.isOK = !row.isOK row.isOK = !row.isOK
......
...@@ -3,40 +3,30 @@ ...@@ -3,40 +3,30 @@
:title="title" :title="title"
center center
width="1000px"> width="1000px">
<!-- start -->
<el-row style="padding: 10px 0;text-align: left;">
<!-- excel表格上传 --> <!-- excel表格上传 -->
<el-upload <el-upload
class="upload-demo" :auto-upload="false"
action="https://jsonplaceholder.typicode.com/posts/" :on-change="elInFile"
multiple
accept=".xlsx"
:on-exceed="exceed"
:limit="1"
:on-remove="remove" :on-remove="remove"
:http-request="uploadFile" ref="upload"
> action="https://jsonplaceholder.typicode.com"
<!-- <i class="el-icon-upload"></i>--> class="upload-demo"
<!-- <div class="el-upload__text">--> accept=".xlsx, .xls">
<!-- 将文件拖到此处,或--> <el-button slot="trigger" size="mini" type="primary" plain>选取文件</el-button>
<!-- <em>点击上传</em>--> <div slot="tip" class="el-upload__tip">只能选取Excel文件</div>
<!-- </div>-->
<el-button size="small" type="primary">点击上传</el-button>
<div class="el-upload__tip" slot="tip">1次只能上传1个xls文件,且不超过500kb</div>
</el-upload> </el-upload>
</el-row>
<div class="scroll-container no-bottom" <div class="scroll-container no-bottom"
ref="scrollContainer"> ref="scrollContainer">
<el-form :model="formData" ref="formData"> <el-form :model="formData" ref="formData">
<el-table <el-table
:data="formData.tableData" :data="formData.tableData"
style="width: 100%" style="width: 100%"
@row-dblclick="dbclick"> @row-dblclick="dbclick"
:row-class-name="tableRowClassName">
<el-table-column prop="name" label="物品名称"> <el-table-column prop="name" label="物品名称">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'" <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'"
:rules="[{required: true,trigger: 'blur',message: '物品名称不能为空'}]"> :rules="[{required: true,trigger: 'change',message: '物品名称不能为空'}]">
<el-autocomplete <el-autocomplete
class="input-width" class="input-width"
v-model="scope.row.name" v-model="scope.row.name"
...@@ -51,7 +41,8 @@ ...@@ -51,7 +41,8 @@
</el-table-column> </el-table-column>
<el-table-column label="型号"> <el-table-column label="型号">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.goodsNo'" :rules="[{required: true,trigger: 'blur',message: '型号不能为空'}]"> <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.goodsNo'"
:rules="[{required: true,trigger: 'blur',message: '型号不能为空'}]">
<el-input v-if="scope.row.isOK" v-model="scope.row.goodsNo" class="input-width" <el-input v-if="scope.row.isOK" v-model="scope.row.goodsNo" class="input-width"
placeholder="型号" placeholder="型号"
:disabled="scope.row.id? true: false"></el-input> :disabled="scope.row.id? true: false"></el-input>
...@@ -61,7 +52,8 @@ ...@@ -61,7 +52,8 @@
</el-table-column> </el-table-column>
<el-table-column label="条形码"> <el-table-column label="条形码">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.barCode'" :rules="[{required: true,trigger: 'blur',message: '条形码不能为空'}]"> <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.barCode'"
:rules="[{required: true,trigger: 'blur',message: '条形码不能为空'}]">
<el-input v-if="scope.row.isOK" v-model="scope.row.barCode" class="input-width" <el-input v-if="scope.row.isOK" v-model="scope.row.barCode" class="input-width"
placeholder="条形码" placeholder="条形码"
:disabled="scope.row.id? true: false"></el-input> :disabled="scope.row.id? true: false"></el-input>
...@@ -89,7 +81,8 @@ ...@@ -89,7 +81,8 @@
</el-table-column> </el-table-column>
<el-table-column label="数量"> <el-table-column label="数量">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.goodsNum'" :rules="[{required: true,trigger: 'blur',message: '数量不能为空'}]"> <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.goodsNum'"
:rules="[{required: true,trigger: 'blur',message: '数量不能为空'}]">
<el-input v-if="scope.row.isOK" v-model="scope.row.goodsNum" class="input-width" <el-input v-if="scope.row.isOK" v-model="scope.row.goodsNum" class="input-width"
placeholder="数量"></el-input> placeholder="数量"></el-input>
<span v-else>{{scope.row.goodsNum}}</span> <span v-else>{{scope.row.goodsNum}}</span>
...@@ -98,7 +91,8 @@ ...@@ -98,7 +91,8 @@
</el-table-column> </el-table-column>
<el-table-column label="价格(元)"> <el-table-column label="价格(元)">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.prict'" :rules="[{required: true,trigger: 'blur',message: '价格不能为空'}]"> <el-form-item size="mini" :prop="'tableData.' + scope.$index + '.prict'"
:rules="[{required: true,trigger: 'blur',message: '价格不能为空'}]">
<el-input v-if="scope.row.isOK" v-model="scope.row.prict" class="input-width" <el-input v-if="scope.row.isOK" v-model="scope.row.prict" class="input-width"
placeholder="价格" placeholder="价格"
:disabled="scope.row.id? true: false"></el-input> :disabled="scope.row.id? true: false"></el-input>
...@@ -175,6 +169,7 @@ export default { ...@@ -175,6 +169,7 @@ export default {
name: 'importGoodsModal', name: 'importGoodsModal',
data() { data() {
return { return {
files: null, //文件列表
visible: false, visible: false,
title: null, title: null,
loading: false, loading: false,
...@@ -187,6 +182,81 @@ export default { ...@@ -187,6 +182,81 @@ export default {
goodsList: [] goodsList: []
} }
}, },
beforeCreate() {
/**
* 读取Excel文件,转为{@link Object}对象(自定义函数)
* @return {@link Object}:workbook,整个文档对象;
*/
FileReader.prototype.read2workbook = function () {
let redABS = false //是否将文件读取为二进制字符串
let bytes = new Uint8Array(this.result) //无符号整型数组
if (redABS) {
// let fix = new TextDecoder(encode || 'UTF-8').decode(bytes);
let fix = fixdata(bytes)
let b2a = btoa(fix) //js原生方法:将字符转为base64编码。对应的atob(base64)方法,将base64转字符
var wb = XLSX.read(b2a, {
type: 'base64'
})
} else {
let len = bytes.byteLength
let binarys = new Array(len) //创建定长数组,存储文本
for (let i = 0; i < len; i++)
binarys[i] = String.fromCharCode(bytes[i])
let binary = binarys.join('')
var wb = XLSX.read(binary, {
type: 'binary'
})
}
return wb //workbook
}
/**
* 解析为...格式
*/
FileReader.prototype.read2 = function (format = 'json') {
let wb = this.read2workbook()
if (!wb)
return null
let r = {}
let formats = ['json', 'formulae', 'html', 'txt', 'csv', 'dif', 'slk', 'eth'] //可被解析的格式
format = formats.indexOf(format) == -1 ? 'json' : format
wb.SheetNames.forEach(name => { //遍历每张纸数据
r[name] = XLSX.utils['sheet_to_' + format](wb.Sheets[name])
})
return r
}
/**
* 解析为JSON
* @description: 此解析方式,XLSX将使用表格首行的每列名称,当作sheet数组对象的Key。
* 故Excel每个工作表格的第一行必须有表头,且名称不可重复。
*/
FileReader.prototype.read2JS = function () {
return this.read2()
}
/* 重写readAsBinaryString函数 */
FileReader.prototype.readAsBinaryString = function (f) {
if (!this.onload) //如果this未重写onload函数,则创建一个公共处理方式
this.onload = e => { //在this.onload函数中,完成公共处理
let rs = this.read2workbook()
}
this.readAsArrayBuffer(f) //内部会回调this.onload方法
}
/**
* char值转String
* @param data {@link Array}:char值;
* @return {@link String}
*/
function fixdata(data) {
let w = 1024 << 10 //每次读取1M字节
let len = Math.floor(data.byteLength / w)
let o = new Array(len)
for (var i = 0; i < len; i++)
o[i] = String.fromCharCode.apply(null, new Uint8Array(data.slice(i * w, (i + 1) * w)))
o[i] = String.fromCharCode.apply(null, new Uint8Array(data.slice(i * w)))
return o.join('')
}
},
methods: { methods: {
// 物品类别 // 物品类别
getGoodsCategoryList() { getGoodsCategoryList() {
...@@ -208,7 +278,6 @@ export default { ...@@ -208,7 +278,6 @@ export default {
}, },
// 物品 // 物品
getGoodsList() { getGoodsList() {
console.log(12121212)
getGoodsList().then(res => { getGoodsList().then(res => {
for (var i of res.data.list) { for (var i of res.data.list) {
i.value = i.name i.value = i.name
...@@ -235,17 +304,20 @@ export default { ...@@ -235,17 +304,20 @@ export default {
close() { close() {
this.visible = false this.visible = false
}, },
tableRowClassName ({row, rowIndex}) {
// 把每一行的索引放进row
row.index = rowIndex;
},
dbclick(row, event, column) { dbclick(row, event, column) {
for (var i of this.tableData) { console.log('row, event, column',row, event, column)
for (var i of this.formData.tableData) {
i.isOK = false i.isOK = false
} }
row.isOK = !row.isOK row.isOK = !row.isOK
this.formData.tableData.splice(row.index,1,row)
console.log('this.formData.tableData',this.formData.tableData)
}, },
submit(formName) { submit(formName) {
// if (!this.formData.tableData.length || !this.formData.tableData[0].name) {
// this.$message.warning('请添加物品')
// return
// }
this.$refs[formName].validate((valid) => { this.$refs[formName].validate((valid) => {
if (valid) { if (valid) {
let data = this.formData.tableData let data = this.formData.tableData
...@@ -254,7 +326,7 @@ export default { ...@@ -254,7 +326,7 @@ export default {
this.$emit('ok') this.$emit('ok')
this.visible = false this.visible = false
}) })
}else { } else {
this.$message.warning('请检查必填项') this.$message.warning('请检查必填项')
} }
}) })
...@@ -270,7 +342,6 @@ export default { ...@@ -270,7 +342,6 @@ export default {
return '' return ''
} }
let name = null let name = null
console.log('arr,id',arr,id)
if (type) { if (type) {
name = arr.filter(item => item.id == id)[0].supplierName name = arr.filter(item => item.id == id)[0].supplierName
} else { } else {
...@@ -279,6 +350,7 @@ export default { ...@@ -279,6 +350,7 @@ export default {
return name return name
}, },
// 物品名称搜索作用
querySearch(queryString, cb) { querySearch(queryString, cb) {
var goodsList = this.goodsList var goodsList = this.goodsList
var results = queryString ? goodsList.filter(this.createFilter(queryString)) : goodsList var results = queryString ? goodsList.filter(this.createFilter(queryString)) : goodsList
...@@ -298,82 +370,84 @@ export default { ...@@ -298,82 +370,84 @@ export default {
this.formData.tableData[index].stockRoomId = item.stockRoomId this.formData.tableData[index].stockRoomId = item.stockRoomId
this.formData.tableData[index].prict = item.prict this.formData.tableData[index].prict = item.prict
this.formData.tableData[index].supplierId = item.supplierId this.formData.tableData[index].supplierId = item.supplierId
this.formData.tableData[index].supplierId = item.supplierId
this.formData.tableData[index].goodsCategoryId = item.goodsCategoryId this.formData.tableData[index].goodsCategoryId = item.goodsCategoryId
console.log('item', item)
}, },
//解析excel //删除文件
async uploadFile(params) { remove() {
const _file = params.file; this.formData.tableData = []
const fileReader = new FileReader(); },
fileReader.onload = (ev) => { /**
try { * input-file调用此函数时,默认传入"$event"
const data = ev.target.result; * @param e {@link Object}:$event事件对象;
const workbook = XLSX.read(data, { */
type: 'binary' inFile(e) {
}); this.files = (e.target || e.srcElement).files //获取"input-file"的FileList对象
for (let sheet in workbook.Sheets) { if (!this.files || !this.files.length)
//循环读取每个文件 return
const sheetArray = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]); for (let i = 0, len = this.files.length; i < len; i++)
//若当前sheet没有数据,则continue this.read(this.files[i])
if(sheetArray.length == 0){ },
continue; /**
* 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用。
* @param f {@link Object}:当前上传的文件;
* @param fs {@link Array}:当前文件列表;
*/
elInFile(f, fs) {
if (fs.length > 1) {
fs.splice(0, 1)
} }
console.log("读取文件"); this.read(f.raw)
console.log(sheetArray); },
for(let item in sheetArray){ /**
let rowTable = {}; * 解析
//这里的rowTable的属性名注意要与上面表格的prop一致 * @param f {@link File}
//sheetArray的属性名与上传的表格的列名一致 */
rowTable.name = sheetArray[item].物品名称; read(f) {
rowTable.goodsNo = sheetArray[item].型号; let rd = new FileReader()
rowTable.goodsNum = sheetArray[item].数量; rd.onload = e => { //this.readAsArrayBuffer函数内,会回调this.onload函数。在这里处理结果
rowTable.prict = sheetArray[item].价格(); let sheetArray = rd.read2JS()
rowTable.barCode = sheetArray[item].条形码; let tables = []
let stockRoomName = sheetArray[item].库房 for (var sheet of sheetArray.Sheet1) {
let goodsCategoryName = sheetArray[item].物品类别; let rowTable = {}
let supplierName =sheetArray[item].供应商; rowTable.name = sheet['物品名称']
if(rowTable.name){ rowTable.goodsNo = sheet['型号']
let isExist = this.goodsList.findIndex(item =>{item.name === rowTable.name}) rowTable.goodsNum = sheet['数量']
isExist == -1 && (rowTable.id = null) rowTable.prict = sheet['价格']
isExist != -1 && (rowTable.id = this.goodsList[isExist].id) rowTable.barCode = sheet['条形码']
if (sheet['物品名称']) {
let isExist = this.goodsList.findIndex(item =>
item.name === sheet['物品名称']
)
isExist === -1 && (rowTable.id = null)
isExist !== -1 && (rowTable.id = this.goodsList[isExist].id)
} }
if(goodsCategoryName){ if (sheet['物品类别']) {
let isExist = this.goodsList.findIndex(item =>{item.name === goodsCategoryName}) let isExist = this.categoryOptions.findIndex(item =>
isExist == -1 && (rowTable.goodsCategoryId = null) item.name === sheet['物品类别']
isExist != -1 && (rowTable.goodsCategoryId = this.goodsList[isExist].id) )
isExist === -1 && (rowTable.goodsCategoryId = null)
isExist !== -1 && (rowTable.goodsCategoryId = this.categoryOptions[isExist].id)
} }
if(supplierName){ if (sheet['供应商']) {
let isExist = this.goodsList.findIndex(item =>{item.supplierName === supplierName}) let isExist = this.supplierOptions.findIndex(item =>
isExist == -1 && (rowTable.supplierId = null) item.supplierName === sheet['供应商']
isExist != -1 && (rowTable.supplierId = this.goodsList[isExist].id) )
isExist === -1 && (rowTable.supplierId = null)
isExist !== -1 && (rowTable.supplierId = this.supplierOptions[isExist].id)
} }
if(stockRoomName){ if (sheet['所属库房']) {
let isExist = this.goodsList.findIndex(item =>{item.name === stockRoomName}) let isExist = this.depotOptions.findIndex(item =>
isExist == -1 && (rowTable.stockRoomId = null) item.name === sheet['所属库房']
isExist != -1 && (rowTable.stockRoomId = this.goodsList[isExist].id) )
isExist === -1 && (rowTable.stockRoomId = null)
isExist !== -1 && (rowTable.stockRoomId = this.depotOptions[isExist].id)
} }
this.formData.tableData.push(rowTable) tables.push(rowTable)
console.log('rowTable',rowTable, this.formData.tableData) this.formData.tableData = tables
} }
} }
} catch (e) { rd.readAsBinaryString(f)
this.$message.warning('文件类型不正确!');
} }
};
fileReader.readAsBinaryString(_file);
},
//上传1个以上文件时弹窗提示错误
exceed: function() {
this.$message.error("最多只能上传1个xls文件");
},
//删除文件
remove() {
this.formData.tableData = [];
}
} }
} }
</script> </script>
...@@ -387,6 +461,11 @@ export default { ...@@ -387,6 +461,11 @@ export default {
.input-width { .input-width {
width: 100px; width: 100px;
} }
.el-upload__tip {
color: #999;
font-size: 10px;
}
</style> </style>
<style> <style>
.no-bottom .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item { .no-bottom .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment