admin/addon/cashier/source/os/pages/stock/add_allocate.vue

615 lines
15 KiB
Vue

<template>
<base-page>
<view class="content-wrap" @click="goodsShow = false">
<view class="title">添加调拨单</view>
<view class="screen-warp form-content">
<view class="form-item store-info" v-if="storeInfo">
<view class="form-label">当前门店:</view>
<view class="form-inline">{{ storeInfo.store_name }}</view>
</view>
<view class="form-item">
<label class="form-label">
<text class="required">*</text>
调拨方式
</label>
<view class="form-inline">
<select-lay
:zindex="10"
:value="type"
name="names"
placeholder="请选择调拨方式"
:options="screen.allocateTypeList"
@selectitem="selectAllocateType"
></select-lay>
</view>
</view>
<view class="form-item">
<label class="form-label">
<text class="required">*</text>
{{ storeName }}
</label>
<view class="form-inline">
<select-lay
:zindex="10"
:value="screen.store_id"
name="names"
:placeholder="'请选择' + storeName"
:options="screen.storeList"
@selectitem="selectStore"
></select-lay>
</view>
</view>
<view class="form-item">
<label class="form-label">
<text class="required">*</text>
调拨时间
</label>
<view class="form-inline">
<uni-datetime-picker :start="screen.startDate" v-model="screen.birthday" type="timestamp" :clearIcon="false" @change="changeTime" />
</view>
</view>
</view>
<view class="table-wrap">
<view class="table-head">
<view class="table-tr">
<view class="table-th" style="flex: 3;">产品名称/规格/编码</view>
<view class="table-th" style="flex: 1;">当前库存</view>
<view class="table-th" style="flex: 1;">单位</view>
<view class="table-th" style="flex: 2;">成本价</view>
<view class="table-th" style="flex: 2;">数量</view>
<view class="table-th" style="flex: 1;">总金额</view>
<view class="table-th" style="flex: 1;">操作</view>
</view>
</view>
<view class="table-body">
<view class="table-tr">
<view class="table-td select-goods-input" style="flex: 3;" @click.stop="goodsShow = true">
<input type="text" v-model="name" @confirm="getGoodsData" placeholder="请输入产品名称/规格/编码" />
<scroll-view class="select-goods-frame" :scroll-y="true" v-show="goodsShow">
<view :class="['goods-item', { select: selectGoodsId == item.sku_id }]" v-for="(item, index) in goodsList" @click.stop="selectGoods(item)">
{{ item.sku_name }}
</view>
<view class="goods-item-empty" v-if="!goodsList.length">暂无商品</view>
</scroll-view>
</view>
<view class="table-td" style="flex: 1;"></view>
<view class="table-td" style="flex: 1;"></view>
<view class="table-td" style="flex: 2;"></view>
<view class="table-td" style="flex: 2;"></view>
<view class="table-td" style="flex: 1;"></view>
<view class="table-td" style="flex: 1;"></view>
</view>
<block v-for="(item, index) in goodsList" :key="index">
<view class="table-tr" v-if="goodsIdArr.includes(item.sku_id)">
<view class="table-td goods-name" style="flex: 3;">
<image :src="$util.img(item.sku_image, { size: 'small' })" mode="aspectFill"></image>
<text class="name multi-hidden">{{ item.sku_name }}</text>
</view>
<view class="table-td" style="flex: 1;">{{ item.real_stock || 0 }}</view>
<view class="table-td" style="flex: 1;">{{ item.unit }}</view>
<view class="table-td" style="flex: 2;">{{ item.cost_price || 0 }}</view>
<view class="table-td" style="flex: 2;">
<input type="number" class="goods-num" v-model="item.goods_num" placeholder="请输入数量" @input="calcTotalData" />
</view>
<view class="table-td" style="flex: 1;">{{ (item.goods_num * item.cost_price || 0).toFixed(2) }}</view>
<view class="table-td" style="flex: 1;"><button type="default" class="delete" @click="delGoods(item.sku_id)">删除</button></view>
</view>
</block>
<view class="table-tr table-empty" v-if="!goodsIdArr.length">暂无数据,请选择商品数据</view>
</view>
</view>
<view class="action-wrap">
<view class="table-total">合计:共{{ totalData.kindsNum }}种{{ totalData.countNum }}件产品,合计金额{{ totalData.price.toFixed(2) }}</view>
<view class="btn-wrap">
<button type="default" class="stockout-btn" @click="stockOutFn">确认调拨</button>
<button type="default" @click="backFn">返回</button>
</view>
</view>
</view>
</base-page>
</template>
<script>
export default {
data() {
return {
name: '', //产品名称
goodsList:[],
goodsIdArr:[],
selectGoodsId: 0,
goodsShow: false,
totalData:{
kindsNum:0,
countNum:0,
price: 0
},
isSubmit: false,
// 筛选面板的时间
type: 'out',
storeName: '出库门店',
screen:{
store_id: "",
storeList:[],
startDate:'1998-01-30 00:00:00',
birthday:'',
allocateTypeList: [
{
label: '调拨入库',
value: 'out'
},
{
label: '调拨出库',
value: 'in'
}
]
},
scanCode: {
code: '',
lastTime: 0
}
};
},
onLoad(option) {
uni.hideTabBar();
},
onShow() {
this.screen.birthday = this.$util.timeFormat(Date.parse(new Date())/1000);
this.getStoreLists();
this.getGoodsData();
// #ifdef APP-PLUS
plus.key.addEventListener('keyup', this.listenerScancode, true);
// #endif
// #ifdef H5
window.addEventListener('keypress', this.listenerScancode, true);
// #endif
},
onHide() {
// #ifdef APP-PLUS
plus.key.removeEventListener('keyup', this.listenerScancode, true);
// #endif
// #ifdef H5
window.removeEventListener('keypress', this.listenerScancode, true);
// #endif
},
watch: {
goodsIdArr(data){
this.calcTotalData();
}
},
methods: {
selectAllocateType(id){
this.type = id == -1 ? '' : this.screen.allocateTypeList[id].value;
this.storeName = id == -1 ? '出库门店' : this.screen.allocateTypeList[id].label;
if(this.type == 'in') this.getGoodsData(); //当是入库的时候,需要查出库门店的商品
},
selectStore(id){
this.screen.store_id = id == -1 ? '' : this.screen.storeList[id].value;
},
changeTime(data){
this.screen.birthday = data;
},
getGoodsData() {
let data = {search: this.name};
if(this.type == 'in')
data.temp_store_id = this.screen.store_id;
this.$api.sendRequest({
url: '/stock/storeapi/manage/getskulist',
data:data,
success: res => {
this.goodsList = [];
if (res.code >= 0 && res.data.length != 0) {
this.goodsList = res.data;
this.selectGoodsId = this.goodsList[0].sku_id;
}else{
this.$util.showToast({
title:res.message
});
}
}
});
},
selectGoods(data){
this.selectGoodsId = data.sku_id;
if(!this.goodsIdArr.includes(data.sku_id))
this.goodsIdArr.push(data.sku_id);
this.goodsShow = false;
},
delGoods(id){
this.goodsIdArr.splice(this.goodsIdArr.indexOf(id),1);
this.$forceUpdate();
},
getStoreLists(){
this.screen.storeList = [];
this.$api.sendRequest({
url: '/stock/storeapi/store/lists',
success: res => {
if(res.code >= 0){
let data = res.data;
let storeId = uni.getStorageSync('store_id');
for(let i = 0; i < data.length; i++){
if(storeId != data[i]['store_id']){
this.screen.storeList.push({
'label': data[i]['store_name'],
'value': data[i]['store_id'].toString()
});
}
}
this.screen.store_id = this.screen.storeList[0].value;
}
}
});
},
stockOutFn(){
if(!this.type){
this.$util.showToast({
title: "请选择调拨方式"
});
return false;
}
if(!this.screen.store_id){
this.$util.showToast({
title: "请选择出库门店"
});
return false;
}
if(!this.screen.birthday){
this.$util.showToast({
title: "请选择调拨时间"
});
return false;
}
if(!this.goodsIdArr.length){
this.$util.showToast({
title: "请选择调拨数据"
});
return false;
}
// 检测库存是否填写,且提取数据
let isStock = false;
let saveData = [];
try{
this.goodsList.forEach((item,index)=>{
if(this.goodsIdArr.includes(item.sku_id)){
if(!parseInt(item.goods_num || 0)){
isStock = true;
let toast = "请输入" + item.sku_name + "的调拨数量";
this.$util.showToast({
title: toast
});
return false;
throw new Error('end');
}
var obj = {};
obj.goods_num = item.goods_num;
obj.goods_price = item.cost_price;
obj.goods_sku_id = item.sku_id;
saveData.push(obj);
}
})
}catch(e){
if(e.message != "end") throw e;
}
if(isStock) return false;
if(this.isSubmit) return false;
this.isSubmit = true;
this.$api.sendRequest({
url: '/stock/storeapi/allocate/addallocate',
data:{
allot_type: this.type,
temp_store_id: this.screen.store_id,
allot_time: this.screen.birthday,
goods_sku_list: JSON.stringify(saveData)
},
success: res => {
this.isSubmit = false;
this.$util.showToast({
title:res.message
});
if (res.code >= 0) {
setTimeout(()=>{
this.backFn();
},500);
this.resetFn();
}
}
});
},
backFn(){
this.$util.redirectTo('/pages/stock/allocate');
},
calcTotalData(){
this.totalData.countNum = 0;
this.totalData.kindsNum = 0;
this.totalData.price = 0;
this.goodsList.forEach((item,index)=>{
if(this.goodsIdArr.includes(item.sku_id)){
this.totalData.price += parseFloat(item.cost_price || 0) * parseInt(item.goods_num || 1);
this.totalData.countNum += parseInt(item.goods_num || 0);
}
})
this.totalData.kindsNum = this.goodsIdArr.length;
},
resetFn(){
this.goodsIdArr = [];
this.selectGoodsId = this.goodsList[0].sku_id;
this.goodsShow = false;
this.totalData.kindsNum = 0;
this.totalData.countNum = 0;
this.totalData.price = 0;
},
/**
* 监听扫码事件
* @param {Object} e
*/
listenerScancode(e){
const clearBarCode = ()=> {
this.scanCode = { lastTime: 0, code: '' }
}
// #ifdef H5
var currCode = e.keyCode || e.which || e.charCode;
// #endif
// #ifdef APP-PLUS
const keycode = ['keycode_7': 0, 'keycode_8': 1, 'keycode_9': 2, 'keycode_10': 3, 'keycode_11': 4, 'keycode_12':
5, 'keycode_13': 6, 'keycode_14': 7, 'keycode_15': 8, 'keycode_16': 9
];
var currCode = keyArr['keycode_' + e.keyCode] || '';
// #endif
var currTime = new Date().getTime();
if (this.scanCode.lastTime > 0) {
if (currTime - this.scanCode.lastTime <= 100) {
this.scanCode.code += String.fromCharCode(currCode);
} else if (currTime - this.scanCode.lastTime > 500) {
// 输入间隔500毫秒清空
clearBarCode();
}
} else {
this.scanCode.code = String.fromCharCode(currCode);
}
this.scanCode.lastTime = currTime;
// #ifdef H5
if (currCode == 13) {
// #endif
// #ifdef APP-PLUS
if (e.keyCode == 66) {
// #endif
if (this.scanCode.code && this.scanCode.code.length >= 8) this.getSkuBycode(this.scanCode.code)
// 回车输入后清空
clearBarCode();
}
},
/**
* 获取商品信息通过条形码
*/
getSkuBycode(code){
this.$api.sendRequest({
url: '/cashier/storeapi/goods/skuinfo',
data: {
sku_no: code.trim()
},
success: res => {
if (res.code == 0) {
if (res.data) {
res.data.goods_num = 0;
this.selectGoods(res.data)
} else {
this.$util.showToast({
title: '未找到该商品!'
})
}
} else {
this.$util.showToast({
title: res.message,
})
}
}
})
}
}
};
</script>
<style lang="scss">
.form-content {
display: flex;
flex-wrap: wrap;
margin-top: 0.2rem;
.store-info {
.form-inline {
padding-left: 0.05rem;
}
}
.form-item {
margin-bottom: 0.1rem;
display: flex;
.form-label {
width: 1.3rem;
text-align: right;
padding-right: 0.1rem;
box-sizing: border-box;
height: 0.32rem;
line-height: 0.32rem;
.required {
color: red;
margin-right: 0.03rem;
}
}
.form-inline {
width: 2.4rem;
line-height: 0.32rem;
margin-right: 0.1rem;
box-sizing: border-box;
.form-input {
border-width: 0.01rem;
border-style: solid;
background-color: #fff;
color: rgba(0, 0, 0, 0.85);
border-radius: 0.02rem;
padding-left: 0.1rem;
height: 0.32rem;
line-height: 0.32rem;
font-size: 0.14rem;
border-color: #e6e6e6;
border-radius: 0.02rem;
}
}
}
}
.content-wrap {
position: relative;
padding: 0.15rem;
background-color: #fff;
min-height: 100vh;
box-sizing: border-box;
.title {
font-size: 0.18rem;
margin-bottom: 0.2rem;
text-align: center;
}
.table-wrap {
position: relative;
margin-top: 40rpx;
border: 1rpx solid #ccc;
.table-head {
background-color: #f7f7f7;
}
.table-body {
overflow: auto;
max-height: 6rem;
.table-tr {
&:nth-child(1) {
position: absolute;
left: 0;
right: 0;
background: #fff;
z-index: 2;
}
&:nth-child(2) {
margin-top: 0.51rem;
}
&:last-of-type .table-td {
border-bottom: 0;
}
}
}
.table-tr {
display: flex;
}
.table-th,
.table-td {
display: flex;
align-items: center;
justify-content: center;
padding: 0.15rem 0.3rem;
border-bottom: 0.01rem solid #ccc;
border-right: 0.01rem solid #ccc;
text-align: center;
&:last-of-type {
border-right: 0;
justify-content: flex-end;
}
&.goods-name {
justify-content: flex-start;
image {
width: 0.45rem;
height: 0.45rem;
flex-shrink: 0;
}
.name {
margin-left: 0.1rem;
}
}
}
.goods-num {
border: 0.01rem solid #eee;
height: 0.35rem;
line-height: 0.35rem;
border-radius: 0.05rem;
}
input {
font-size: $uni-font-size-base;
}
.delete {
margin: 0;
font-size: $uni-font-size-base;
background-color: $uni-color-primary;
color: #fff;
}
.table-empty {
justify-content: center;
padding: 0.3rem;
color: #999;
}
}
.action-wrap {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
padding: 0.1rem 0.15rem 0.2rem;
align-items: center;
border-top: 0.01rem solid #ccc;
.btn-wrap {
display: flex;
align-items: center;
justify-content: center;
button {
margin: 0;
min-width: 2.75rem;
height: 0.4rem;
line-height: 0.4rem;
font-size: $uni-font-size-base;
&.stockout-btn {
margin-right: 0.15rem;
background-color: $uni-color-primary;
color: #fff;
}
}
}
}
.select-goods-input {
position: relative;
input {
flex: 1;
font-size: $uni-font-size-base;
}
}
.select-goods-frame {
position: absolute;
z-index: 2;
padding: 0.05rem 0;
top: 0.45rem;
left: 0;
width: 5rem;
height: 5rem;
background-color: #fff;
box-shadow: 0 0 36rpx rgba(0, 0, 0, 0.4);
.goods-item {
padding: 10rpx 30rpx;
line-height: 1.5;
text-align: left;
&.select {
background-color: $uni-color-primary;
color: #fff;
}
}
.goods-item-empty {
padding: 10rpx 30rpx;
line-height: 1.5;
text-align: center;
}
}
}
</style>