Commit bf9f35cc by wangyalan-git

物品新增和导入物品

parent bf15f9b2
......@@ -65,7 +65,7 @@
<el-button type="primary" @click="handleAdd">新增</el-button>
<el-button type="success" @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>
<div class="table-container">
<el-table :data="list"
......@@ -119,14 +119,16 @@
</div>
</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>
</template>
<script>
import moment from 'moment'
import { getGoodsList,getGoodsCategoryList,getStockRooms, getAuditDetail, updateMcht } from '@/api/inventory'
import {getSuppliersList} from '@/api/supplier'
import AddGoods from './modules/addGoodsModal'
import AddGoodsModal from './modules/addGoodsModal'
import ImportGoodsModal from './modules/importGoodsModal'
// 列表查询参数默认值
const defaultListQuery = {
pageNum: 1,
......@@ -139,7 +141,10 @@ const defaultListQuery = {
export default {
name: 'StoreList',
components: {AddGoods},
components: {
AddGoodsModal,
ImportGoodsModal
},
data() {
return {
listQuery: Object.assign({}, defaultListQuery),
......@@ -218,8 +223,13 @@ export default {
this.listLoading = false
})
},
// 新增
handleAdd(){
this.$refs.addGoods.add()
},
// 导入
handleImport(){
this.$refs.importGoods.add()
}
}
}
......
......@@ -13,11 +13,12 @@
<el-table
:data="formData.tableData"
style="width: 100%"
@row-dblclick="dbclick">
@row-dblclick="dbclick"
:row-class-name="tableRowClassName">
<el-table-column prop="name" label="物品名称">
<template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'"
:rules="[{required: true,trigger: 'blur',message: '物品名称不能为空'}]">
:rules="[{required: true,trigger: 'change',message: '物品名称不能为空'}]">
<el-autocomplete
class="input-width"
v-model="scope.row.name"
......@@ -230,8 +231,12 @@ export default {
isOK: true
},)
},
tableRowClassName ({row, rowIndex}) {
// 把每一行的索引放进row
row.index = rowIndex;
},
dbclick(row, event, column) {
for (var i of this.tableData) {
for (var i of this.formData.tableData) {
i.isOK = false
}
row.isOK = !row.isOK
......
......@@ -3,40 +3,30 @@
:title="title"
center
width="1000px">
<!-- start -->
<el-row style="padding: 10px 0;text-align: left;">
<!-- excel表格上传 -->
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
multiple
accept=".xlsx"
:on-exceed="exceed"
:limit="1"
:auto-upload="false"
:on-change="elInFile"
:on-remove="remove"
:http-request="uploadFile"
>
<!-- <i class="el-icon-upload"></i>-->
<!-- <div class="el-upload__text">-->
<!-- 将文件拖到此处,或-->
<!-- <em>点击上传</em>-->
<!-- </div>-->
<el-button size="small" type="primary">点击上传</el-button>
<div class="el-upload__tip" slot="tip">1次只能上传1个xls文件,且不超过500kb</div>
ref="upload"
action="https://jsonplaceholder.typicode.com"
class="upload-demo"
accept=".xlsx, .xls">
<el-button slot="trigger" size="mini" type="primary" plain>选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能选取Excel文件</div>
</el-upload>
</el-row>
<div class="scroll-container no-bottom"
ref="scrollContainer">
<el-form :model="formData" ref="formData">
<el-table
:data="formData.tableData"
style="width: 100%"
@row-dblclick="dbclick">
@row-dblclick="dbclick"
:row-class-name="tableRowClassName">
<el-table-column prop="name" label="物品名称">
<template slot-scope="scope">
<el-form-item size="mini" :prop="'tableData.' + scope.$index + '.name'"
:rules="[{required: true,trigger: 'blur',message: '物品名称不能为空'}]">
:rules="[{required: true,trigger: 'change',message: '物品名称不能为空'}]">
<el-autocomplete
class="input-width"
v-model="scope.row.name"
......@@ -51,7 +41,8 @@
</el-table-column>
<el-table-column label="型号">
<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"
placeholder="型号"
:disabled="scope.row.id? true: false"></el-input>
......@@ -61,7 +52,8 @@
</el-table-column>
<el-table-column label="条形码">
<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"
placeholder="条形码"
:disabled="scope.row.id? true: false"></el-input>
......@@ -89,7 +81,8 @@
</el-table-column>
<el-table-column label="数量">
<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"
placeholder="数量"></el-input>
<span v-else>{{scope.row.goodsNum}}</span>
......@@ -98,7 +91,8 @@
</el-table-column>
<el-table-column label="价格(元)">
<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"
placeholder="价格"
:disabled="scope.row.id? true: false"></el-input>
......@@ -175,6 +169,7 @@ export default {
name: 'importGoodsModal',
data() {
return {
files: null, //文件列表
visible: false,
title: null,
loading: false,
......@@ -187,6 +182,81 @@ export default {
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: {
// 物品类别
getGoodsCategoryList() {
......@@ -208,7 +278,6 @@ export default {
},
// 物品
getGoodsList() {
console.log(12121212)
getGoodsList().then(res => {
for (var i of res.data.list) {
i.value = i.name
......@@ -235,17 +304,20 @@ export default {
close() {
this.visible = false
},
tableRowClassName ({row, rowIndex}) {
// 把每一行的索引放进row
row.index = rowIndex;
},
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
}
row.isOK = !row.isOK
this.formData.tableData.splice(row.index,1,row)
console.log('this.formData.tableData',this.formData.tableData)
},
submit(formName) {
// if (!this.formData.tableData.length || !this.formData.tableData[0].name) {
// this.$message.warning('请添加物品')
// return
// }
this.$refs[formName].validate((valid) => {
if (valid) {
let data = this.formData.tableData
......@@ -254,7 +326,7 @@ export default {
this.$emit('ok')
this.visible = false
})
}else {
} else {
this.$message.warning('请检查必填项')
}
})
......@@ -270,7 +342,6 @@ export default {
return ''
}
let name = null
console.log('arr,id',arr,id)
if (type) {
name = arr.filter(item => item.id == id)[0].supplierName
} else {
......@@ -279,6 +350,7 @@ export default {
return name
},
// 物品名称搜索作用
querySearch(queryString, cb) {
var goodsList = this.goodsList
var results = queryString ? goodsList.filter(this.createFilter(queryString)) : goodsList
......@@ -298,82 +370,84 @@ export default {
this.formData.tableData[index].stockRoomId = item.stockRoomId
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].goodsCategoryId = item.goodsCategoryId
console.log('item', item)
},
//解析excel
async uploadFile(params) {
const _file = params.file;
const fileReader = new FileReader();
fileReader.onload = (ev) => {
try {
const data = ev.target.result;
const workbook = XLSX.read(data, {
type: 'binary'
});
for (let sheet in workbook.Sheets) {
//循环读取每个文件
const sheetArray = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
//若当前sheet没有数据,则continue
if(sheetArray.length == 0){
continue;
//删除文件
remove() {
this.formData.tableData = []
},
/**
* input-file调用此函数时,默认传入"$event"
* @param e {@link Object}:$event事件对象;
*/
inFile(e) {
this.files = (e.target || e.srcElement).files //获取"input-file"的FileList对象
if (!this.files || !this.files.length)
return
for (let i = 0, len = this.files.length; i < len; i++)
this.read(this.files[i])
},
/**
* 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用。
* @param f {@link Object}:当前上传的文件;
* @param fs {@link Array}:当前文件列表;
*/
elInFile(f, fs) {
if (fs.length > 1) {
fs.splice(0, 1)
}
console.log("读取文件");
console.log(sheetArray);
for(let item in sheetArray){
let rowTable = {};
//这里的rowTable的属性名注意要与上面表格的prop一致
//sheetArray的属性名与上传的表格的列名一致
rowTable.name = sheetArray[item].物品名称;
rowTable.goodsNo = sheetArray[item].型号;
rowTable.goodsNum = sheetArray[item].数量;
rowTable.prict = sheetArray[item].价格();
rowTable.barCode = sheetArray[item].条形码;
let stockRoomName = sheetArray[item].库房
let goodsCategoryName = sheetArray[item].物品类别;
let supplierName =sheetArray[item].供应商;
if(rowTable.name){
let isExist = this.goodsList.findIndex(item =>{item.name === rowTable.name})
isExist == -1 && (rowTable.id = null)
isExist != -1 && (rowTable.id = this.goodsList[isExist].id)
this.read(f.raw)
},
/**
* 解析
* @param f {@link File}
*/
read(f) {
let rd = new FileReader()
rd.onload = e => { //this.readAsArrayBuffer函数内,会回调this.onload函数。在这里处理结果
let sheetArray = rd.read2JS()
let tables = []
for (var sheet of sheetArray.Sheet1) {
let rowTable = {}
rowTable.name = sheet['物品名称']
rowTable.goodsNo = sheet['型号']
rowTable.goodsNum = sheet['数量']
rowTable.prict = sheet['价格']
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){
let isExist = this.goodsList.findIndex(item =>{item.name === goodsCategoryName})
isExist == -1 && (rowTable.goodsCategoryId = null)
isExist != -1 && (rowTable.goodsCategoryId = this.goodsList[isExist].id)
if (sheet['物品类别']) {
let isExist = this.categoryOptions.findIndex(item =>
item.name === sheet['物品类别']
)
isExist === -1 && (rowTable.goodsCategoryId = null)
isExist !== -1 && (rowTable.goodsCategoryId = this.categoryOptions[isExist].id)
}
if(supplierName){
let isExist = this.goodsList.findIndex(item =>{item.supplierName === supplierName})
isExist == -1 && (rowTable.supplierId = null)
isExist != -1 && (rowTable.supplierId = this.goodsList[isExist].id)
if (sheet['供应商']) {
let isExist = this.supplierOptions.findIndex(item =>
item.supplierName === sheet['供应商']
)
isExist === -1 && (rowTable.supplierId = null)
isExist !== -1 && (rowTable.supplierId = this.supplierOptions[isExist].id)
}
if(stockRoomName){
let isExist = this.goodsList.findIndex(item =>{item.name === stockRoomName})
isExist == -1 && (rowTable.stockRoomId = null)
isExist != -1 && (rowTable.stockRoomId = this.goodsList[isExist].id)
if (sheet['所属库房']) {
let isExist = this.depotOptions.findIndex(item =>
item.name === sheet['所属库房']
)
isExist === -1 && (rowTable.stockRoomId = null)
isExist !== -1 && (rowTable.stockRoomId = this.depotOptions[isExist].id)
}
this.formData.tableData.push(rowTable)
console.log('rowTable',rowTable, this.formData.tableData)
tables.push(rowTable)
this.formData.tableData = tables
}
}
} catch (e) {
this.$message.warning('文件类型不正确!');
rd.readAsBinaryString(f)
}
};
fileReader.readAsBinaryString(_file);
},
//上传1个以上文件时弹窗提示错误
exceed: function() {
this.$message.error("最多只能上传1个xls文件");
},
//删除文件
remove() {
this.formData.tableData = [];
}
}
}
</script>
......@@ -387,6 +461,11 @@ export default {
.input-width {
width: 100px;
}
.el-upload__tip {
color: #999;
font-size: 10px;
}
</style>
<style>
.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