|
|
@@ -1,11 +1,354 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <h1>出库管理</h1>
|
|
|
+ <van-nav-bar
|
|
|
+ title="出库" left-arrow left-text="返回" right-text="拍照" fixed placeholder @click-left="goBack()"
|
|
|
+ @click-right="goTakePhoto"
|
|
|
+ />
|
|
|
+ <van-search v-model="stockOutSearch" placeholder="请输入搜索关键词" @search="searchStockOut" />
|
|
|
+ <div class="content">
|
|
|
+ <div class="van-list-stock-in">
|
|
|
+ <van-list
|
|
|
+ v-model:loading="loading" class="list-stock-in" :finished="finished" finished-text=""
|
|
|
+ :immediate-check="false" @load="loadStockOutList"
|
|
|
+ >
|
|
|
+ <div v-for="(item, index) in stockOutList" :key="item.id" class="list-container">
|
|
|
+ <van-form :scroll-to-error="true">
|
|
|
+ <div class="in-header">
|
|
|
+ <strong>{{ index + 1 }}. {{ item.inventoryName }}</strong>
|
|
|
+ <van-button type="primary" plain @click="stockOut(item)">出库</van-button>
|
|
|
+ </div>
|
|
|
+ <van-field v-model="item.inventoryNo" name="inventoryNo" label="物料编号:" readonly />
|
|
|
+ <van-field v-model="item.inventoryName" name="inventoryName" label="物料名称:" readonly />
|
|
|
+ <van-field v-model="item.inventoryType" name="inventoryType" label="规格型号:" readonly />
|
|
|
+ <van-field v-model="item.quantity" name="quantity" label="库存:" readonly />
|
|
|
+ <van-field v-model="item.positionName" name="positionName" label="货位:" readonly />
|
|
|
+ </van-form>
|
|
|
+ </div>
|
|
|
+ </van-list>
|
|
|
+ </div>
|
|
|
+ <van-empty v-if="stockOutList.length === 0" description="暂无出库库存" />
|
|
|
</div>
|
|
|
+ <van-dialog v-model:show="isShowStockOut" title="填写出库信息" :show-confirm-button="false">
|
|
|
+ <van-form :scroll-to-error="true">
|
|
|
+ <van-field v-model="formData.inventoryNo" name="inventoryNo" label="物料编号:" readonly />
|
|
|
+ <van-field v-model="formData.inventoryName" name="inventoryName" label="物料名称:" readonly />
|
|
|
+ <van-field v-model="formData.inventoryType" name="inventoryType" label="规格型号:" readonly />
|
|
|
+ <van-field v-model="formData.batchNo" name="batchNo" label="批号:" placeholder="点击输入批号" />
|
|
|
+ <van-field name="outAll" label="是否全部出库">
|
|
|
+ <template #input>
|
|
|
+ <van-switch v-model="formData.outAll" size="20px" />
|
|
|
+ </template>
|
|
|
+ </van-field>
|
|
|
+ <van-field
|
|
|
+ v-model="formData.quantity" name="quantity" label="出库数量:" placeholder="点击输入数量"
|
|
|
+ :readonly="formData.outAll"
|
|
|
+ />
|
|
|
+ <van-field
|
|
|
+ v-model="formData.transferName" is-link readonly name="transfer" label="中转区货位:" placeholder="点击选择中转区货位"
|
|
|
+ @click="isShowTransfer = true"
|
|
|
+ />
|
|
|
+ <van-field
|
|
|
+ v-model="formData.positionName" is-link readonly name="warehouse" label="出库货位:" placeholder="点击选择出库货位"
|
|
|
+ @click="isShowUsing = true"
|
|
|
+ />
|
|
|
+ </van-form>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="footer-btn">
|
|
|
+ <van-button style="width: 40%;" plain type="primary" @click="cancelStockOut">
|
|
|
+ 取消
|
|
|
+ </van-button>
|
|
|
+ <van-button style="width: 40%;" type="primary" @click="stockOutConfirm">
|
|
|
+ 提交
|
|
|
+ </van-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-dialog>
|
|
|
+ <position-selector
|
|
|
+ ref="transferPositionSelector" v-model:show="isShowTransfer" position-type="transfer"
|
|
|
+ is-user="stockOut" :default-selected-id="formData.transferId" @confirm="onTransferPositionSelected"
|
|
|
+ />
|
|
|
+ <position-selector
|
|
|
+ ref="usingPositionSelector" v-model:show="isShowUsing" position-type="using" is-user="stockOut"
|
|
|
+ :default-selected-id="formData.positionId"
|
|
|
+ @confirm="onUsingPositionSelected"
|
|
|
+ />
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
+import { ref, onMounted } from 'vue';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import PositionSelector from './PositionSelector.vue';
|
|
|
+import { processException } from '../common/Common.js';
|
|
|
+import { ajaxApiGet, ajaxApiPost } from '../common/utils.js';
|
|
|
+import { showFailToast, showSuccessToast, showConfirmDialog } from 'vant';
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const stockOutSearch = ref('');
|
|
|
+const transferPositionSelector = ref(null);
|
|
|
+const usingPositionSelector = ref(null);
|
|
|
+
|
|
|
+const stockOutList = ref([]);
|
|
|
+const loading = ref(false);
|
|
|
+const finished = ref(false);
|
|
|
+
|
|
|
+const page = ref(1);
|
|
|
+const total = ref(0);
|
|
|
+const pageSize = ref(10);
|
|
|
+
|
|
|
+const formData = ref({
|
|
|
+ inventoryId: '',
|
|
|
+ inventoryNo: '',
|
|
|
+ inventoryName: '',
|
|
|
+ inventoryType: '',
|
|
|
+ quantity: '',
|
|
|
+ batchNo: '',
|
|
|
+ transferName: '',
|
|
|
+ transferId: '',
|
|
|
+ transferNo: '',
|
|
|
+ positionId: '',
|
|
|
+ positionNo: '',
|
|
|
+ positionName: '',
|
|
|
+ outAll: true,
|
|
|
+});
|
|
|
+
|
|
|
+const isShowStockOut = ref(false);
|
|
|
+const isShowTransfer = ref(false);
|
|
|
+const isShowUsing = ref(false);
|
|
|
+
|
|
|
+const goBack = () => {
|
|
|
+ router.push('/app-menus');
|
|
|
+};
|
|
|
+
|
|
|
+// 搜索出库物料
|
|
|
+const searchStockOut = value => {
|
|
|
+ page.value = 1;
|
|
|
+ total.value = 0;
|
|
|
+ stockOutList.value = [];
|
|
|
+ loadStockOutList();
|
|
|
+};
|
|
|
+
|
|
|
+// 处理中转区货位选择结果
|
|
|
+const onTransferPositionSelected = item => {
|
|
|
+ console.log(item, '中转区货位选择结果');
|
|
|
+ formData.value.transferId = item.id;
|
|
|
+ formData.value.transferNo = item.no;
|
|
|
+ formData.value.transferName = item.name;
|
|
|
+};
|
|
|
+
|
|
|
+// 处理出库货位选择结果
|
|
|
+const onUsingPositionSelected = item => {
|
|
|
+ console.log(item, '出库货位选择结果');
|
|
|
+ getStockOutInfo(item);
|
|
|
+};
|
|
|
+
|
|
|
+// 出库
|
|
|
+const stockOut = item => {
|
|
|
+ console.log(item, '出库');
|
|
|
+ formData.value.inventoryId = item.inventoryId;
|
|
|
+ formData.value.inventoryNo = item.inventoryNo;
|
|
|
+ formData.value.inventoryName = item.inventoryName;
|
|
|
+ formData.value.inventoryType = item.inventoryType;
|
|
|
+ formData.value.quantity = item.quantity;
|
|
|
+ formData.value.batchNo = item.batchNo;
|
|
|
+ formData.value.positionId = item.positionId;
|
|
|
+ formData.value.positionName = item.positionName;
|
|
|
+ formData.value.positionNo = item.positionNo;
|
|
|
+ isShowStockOut.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 出库确认
|
|
|
+const stockOutConfirm = () => {
|
|
|
+ console.log(formData.value, '出库确认');
|
|
|
+
|
|
|
+ if (!formData.value.quantity) {
|
|
|
+ showFailToast('请输入出库数量');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!formData.value.transferId) {
|
|
|
+ showFailToast('请选择中转区货位');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!formData.value.positionId) {
|
|
|
+ showFailToast('请选择出库货位');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ showConfirmDialog({
|
|
|
+ title: '确认要出库吗?',
|
|
|
+ message: '如果确认要出库,请点击【确认】按钮,否则点击【取消】按钮。',
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ submitStockOut();
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ console.log('取消');
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 加载出库物料列表
|
|
|
+const loadStockOutList = async () => {
|
|
|
+ try {
|
|
|
+ const res = await getList(page.value, pageSize.value);
|
|
|
+
|
|
|
+ // 搜索时替换数据,上拉加载时追加数据
|
|
|
+ stockOutList.value =
|
|
|
+ page.value === 1
|
|
|
+ ? res.data
|
|
|
+ : [...stockOutList.value, ...res.data];
|
|
|
+
|
|
|
+ total.value = res.total;
|
|
|
+
|
|
|
+ // 检查是否已加载全部数据
|
|
|
+ if (stockOutList.value.length >= total.value) {
|
|
|
+ finished.value = true;
|
|
|
+ } else {
|
|
|
+ page.value++; // 只有在成功加载后才增加页码
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ finished.value = true;
|
|
|
+ if(error.responseText === '未查询出对应库存信息。') return;
|
|
|
+ processException(error);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取出库物料列表API
|
|
|
+const getList = (page, pageSize) => {
|
|
|
+ const start = (page - 1) * pageSize;
|
|
|
+ const length = pageSize;
|
|
|
+ const filter = '';
|
|
|
+ const url = `/api/StockOutResource/queryCurrentStockStockOut?start=${start}&length=${length}&filter=${filter}`;
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ ajaxApiGet(url).then(
|
|
|
+ success => {
|
|
|
+ const { errorCode, errorMessage, datas, total } = success;
|
|
|
+ if (errorCode === 0) {
|
|
|
+ if (datas && datas.length) {
|
|
|
+ resolve({ data: datas, total: total });
|
|
|
+ } else {
|
|
|
+ resolve({ data: [], total: 0 });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const error = { status: 200, responseText: errorMessage };
|
|
|
+ reject(error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ error => {
|
|
|
+ reject(error);
|
|
|
+ },
|
|
|
+ );
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 提交API
|
|
|
+const submitStockOut = () => {
|
|
|
+ const url = '/api/StockOutResource/scanGeneratorStockOut';
|
|
|
+ const params = {
|
|
|
+ ...formData.value,
|
|
|
+ };
|
|
|
+ ajaxApiPost(url, params).then(
|
|
|
+ success => {
|
|
|
+ if (success.errorCode === 0) {
|
|
|
+ const filter = stockOutSearch.value;
|
|
|
+ clearFormData();
|
|
|
+ searchStockOut(filter);
|
|
|
+ showSuccessToast('出库成功');
|
|
|
+ } else {
|
|
|
+ showFailToast(success.errorMessage);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ error => {
|
|
|
+ processException(error);
|
|
|
+ },
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+// 根据货位、物料、批号查询库存
|
|
|
+const getStockOutInfo = info => {
|
|
|
+ const positionId = info.id;
|
|
|
+ const inventoryId = formData.value.inventoryId;
|
|
|
+ const url = `/api/StockOutResource/queryByInventoryAndPosition?positionId=${positionId}&inventoryId=${inventoryId}`;
|
|
|
+ ajaxApiGet(url).then(
|
|
|
+ success => {
|
|
|
+ const { errorCode, errorMessage, data } = success;
|
|
|
+ if (errorCode === 0) {
|
|
|
+ console.log(data, '根据货位、物料、批号查询库存');
|
|
|
+ if (data) {
|
|
|
+ formData.value = { ...formData.value, ...data };
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ showFailToast(errorMessage);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ error => {
|
|
|
+ processException(error);
|
|
|
+ },
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+// 取消出库
|
|
|
+const cancelStockOut = () => {
|
|
|
+ clearFormData();
|
|
|
+};
|
|
|
+
|
|
|
+// 清除表单数据
|
|
|
+const clearFormData = () => {
|
|
|
+ formData.value = {
|
|
|
+ inventoryId: '',
|
|
|
+ inventoryNo: '',
|
|
|
+ inventoryName: '',
|
|
|
+ inventoryType: '',
|
|
|
+ quantity: '',
|
|
|
+ batchNo: '',
|
|
|
+ transferId: '',
|
|
|
+ transferName: '',
|
|
|
+ transferNo: '',
|
|
|
+ positionId: '',
|
|
|
+ positionName: '',
|
|
|
+ positionNo: '',
|
|
|
+ outAll: true,
|
|
|
+ };
|
|
|
+ transferPositionSelector.value.clearSelected();
|
|
|
+ usingPositionSelector.value.clearSelected();
|
|
|
+ isShowStockOut.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+// 拍照
|
|
|
+const goTakePhoto = () => {
|
|
|
+ router.push('/stock-out-photo');
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ loadStockOutList();
|
|
|
+});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
-<style scoped></style>
|
|
|
+<style scoped>
|
|
|
+.van-search {
|
|
|
+ padding-bottom: 4px !important;
|
|
|
+}
|
|
|
+
|
|
|
+.list-container {
|
|
|
+ padding: 3px 10px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin: 6px 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.in-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ border-bottom: 1px solid #ccc;
|
|
|
+ padding-bottom: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.footer-btn {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+</style>
|