StockIn.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <template>
  2. <van-nav-bar
  3. title="入库" left-arrow left-text="返回" right-text="拍照" fixed placeholder @click-left="goBack()"
  4. @click-right="goTakePhoto"
  5. />
  6. <van-search v-model="stockInSearch" placeholder="请输入搜索关键词" @search="searchStockIn" />
  7. <div class="content">
  8. <div class="van-list-stock-in">
  9. <van-list
  10. v-model:loading="loading" class="list-stock-in" :finished="finished" finished-text=""
  11. :immediate-check="false" @load="loadStockInList"
  12. >
  13. <div v-for="(item, index) in stockInList" :key="item.id" class="list-container">
  14. <van-form :scroll-to-error="true">
  15. <div class="in-header">
  16. <strong>{{ index + 1 }}. {{ item.name }}</strong>
  17. <van-button type="primary" plain @click="stockIn(item)">入库</van-button>
  18. </div>
  19. <van-field v-model="item.no" name="no" label="物料编号:" readonly />
  20. <van-field v-model="item.name" name="name" label="物料名称:" readonly />
  21. <van-field v-model="item.type" name="type" label="规格型号:" readonly />
  22. </van-form>
  23. </div>
  24. </van-list>
  25. </div>
  26. <van-empty v-if="stockInList.length === 0" description="暂无入库单" />
  27. </div>
  28. <van-dialog v-model:show="isShowStockIn" title="填写入库信息" :show-confirm-button="false">
  29. <van-form :scroll-to-error="true">
  30. <van-field v-model="formData.no" name="no" label="物料编号:" readonly />
  31. <van-field v-model="formData.name" name="name" label="物料名称:" readonly />
  32. <van-field v-model="formData.type" name="type" label="规格型号:" readonly />
  33. <van-field v-model="formData.batchNo" name="batchNo" label="批号:" placeholder="点击输入批号" />
  34. <van-field v-model="formData.num" name="num" label="入库数量:" placeholder="点击输入数量" />
  35. <van-field
  36. v-model="formData.transferName" is-link readonly name="transfer" label="中转区货位:" placeholder="点击选择中转区货位"
  37. @click="isShowTransfer = true"
  38. />
  39. <van-field
  40. v-model="formData.idleName" is-link readonly name="warehouse" label="入库货位:" placeholder="点击选择入库货位"
  41. @click="isShowIdle = true"
  42. />
  43. </van-form>
  44. <template #footer>
  45. <div class="footer-btn">
  46. <van-button style="width: 40%;" plain type="primary" @click="cancelStockIn">
  47. 取消
  48. </van-button>
  49. <van-button style="width: 40%;" type="primary" @click="stockInConfirm">
  50. 提交
  51. </van-button>
  52. </div>
  53. </template>
  54. </van-dialog>
  55. <position-selector
  56. v-model:show="isShowTransfer" position-type="transfer" :default-selected-id="formData.transferId"
  57. @confirm="onTransferPositionSelected"
  58. />
  59. <position-selector
  60. v-model:show="isShowIdle" position-type="idle" :default-selected-id="formData.idleId"
  61. @confirm="onIdlePositionSelected"
  62. />
  63. </template>
  64. <script setup>
  65. import { ref, onMounted } from 'vue';
  66. import { useRouter } from 'vue-router';
  67. import PositionSelector from './PositionSelector.vue';
  68. import { showFailToast, showSuccessToast } from 'vant';
  69. import { processException } from '../common/Common.js';
  70. import { ajaxApiGet, ajaxApiPost } from '../common/utils.js';
  71. const router = useRouter();
  72. const stockInSearch = ref('');
  73. const stockInList = ref([]);
  74. const loading = ref(false);
  75. const finished = ref(false);
  76. const page = ref(1);
  77. const total = ref(0);
  78. const pageSize = ref(10);
  79. const formData = ref({
  80. id: '',
  81. no: '',
  82. name: '',
  83. type: '',
  84. num: '',
  85. batchNo: '',
  86. transferName: '',
  87. transferId: '',
  88. transferNo: '',
  89. idleName: '',
  90. idleId: '',
  91. idleNo: '',
  92. });
  93. const isShowStockIn = ref(false);
  94. const isShowTransfer = ref(false);
  95. const isShowIdle = ref(false);
  96. const goBack = () => {
  97. router.push('/app-menus');
  98. };
  99. // 搜索入库物料
  100. const searchStockIn = value => {
  101. console.log(value);
  102. page.value = 1;
  103. total.value = 0;
  104. stockInList.value = [];
  105. loadStockInList();
  106. };
  107. // 处理中转区货位选择结果
  108. const onTransferPositionSelected = item => {
  109. console.log(item, '中转区货位选择结果');
  110. formData.value.transferName = item.name;
  111. formData.value.transferId = item.id;
  112. formData.value.transferNo = item.no;
  113. };
  114. // 处理入库货位选择结果
  115. const onIdlePositionSelected = item => {
  116. console.log(item, '入库货位选择结果');
  117. formData.value.idleName = item.name;
  118. formData.value.idleId = item.id;
  119. formData.value.idleNo = item.no;
  120. };
  121. // 入库
  122. const stockIn = item => {
  123. console.log(item, '入库');
  124. formData.value.id = item.id;
  125. formData.value.no = item.no;
  126. formData.value.name = item.name;
  127. formData.value.type = item.type;
  128. isShowStockIn.value = true;
  129. };
  130. // 入库确认
  131. const stockInConfirm = () => {
  132. console.log(formData.value, '入库确认');
  133. if (!formData.value.num) {
  134. showFailToast('请输入入库数量');
  135. return;
  136. }
  137. if (!formData.value.transferId) {
  138. showFailToast('请选择中转区货位');
  139. return;
  140. }
  141. if (!formData.value.idleId) {
  142. showFailToast('请选择入库货位');
  143. return;
  144. }
  145. submitStockIn();
  146. };
  147. // 加载入库物料列表
  148. const loadStockInList = async () => {
  149. try {
  150. const res = await getList(page.value, pageSize.value);
  151. // 搜索时替换数据,上拉加载时追加数据
  152. stockInList.value =
  153. page.value === 1
  154. ? res.data
  155. : [...stockInList.value, ...res.data];
  156. total.value = res.total;
  157. // 检查是否已加载全部数据
  158. if (stockInList.value.length >= total.value) {
  159. finished.value = true;
  160. } else {
  161. page.value++; // 只有在成功加载后才增加页码
  162. }
  163. } catch (error) {
  164. processException(error);
  165. finished.value = true;
  166. } finally {
  167. loading.value = false;
  168. }
  169. };
  170. // 获取入库物料列表API
  171. const getList = (page, pageSize) => {
  172. const start = (page - 1) * pageSize;
  173. const length = pageSize;
  174. const filter = '';
  175. const url = `/api/InventoryResource/queryStockInInventory?start=${start}&length=${length}&filter=${filter}`;
  176. return new Promise((resolve, reject) => {
  177. ajaxApiGet(url).then(
  178. success => {
  179. const { errorCode, errorMessage, datas, total } = success;
  180. if (errorCode === 0) {
  181. if (datas && datas.length) {
  182. resolve({ data: datas, total: total });
  183. } else {
  184. resolve({ data: [], total: 0 });
  185. }
  186. } else {
  187. const error = { status: 200, responseText: errorMessage };
  188. reject(error);
  189. }
  190. },
  191. error => {
  192. reject(error);
  193. },
  194. );
  195. });
  196. };
  197. // 提交API
  198. const submitStockIn = () => {
  199. const url = '/api/stockInResource/scanGeneratorStockIn';
  200. const params = {
  201. ...formData.value,
  202. };
  203. ajaxApiPost(url, params).then(
  204. success => {
  205. if (success.errorCode === 0) {
  206. showSuccessToast('入库成功');
  207. } else {
  208. showFailToast(success.errorMessage);
  209. }
  210. },
  211. error => {
  212. processException(error);
  213. },
  214. );
  215. };
  216. // 取消入库
  217. const cancelStockIn = () => {
  218. clearFormData();
  219. isShowStockIn.value = false;
  220. };
  221. // 清除表单数据
  222. const clearFormData = () => {
  223. formData.value = {
  224. no: '',
  225. name: '',
  226. type: '',
  227. num: '',
  228. batchNo: '',
  229. transferId: '',
  230. transferName: '',
  231. transferNo: '',
  232. idleId: '',
  233. idleName: '',
  234. idleNo: '',
  235. };
  236. };
  237. // 拍照
  238. const goTakePhoto = () => {
  239. router.push('/stock-in-photo');
  240. };
  241. onMounted(() => {
  242. loadStockInList();
  243. });
  244. </script>
  245. <style scoped>
  246. .van-search {
  247. padding-bottom: 4px !important;
  248. }
  249. .list-container {
  250. padding: 3px 10px;
  251. border: 1px solid #ccc;
  252. border-radius: 4px;
  253. margin: 6px 12px;
  254. }
  255. .in-header {
  256. display: flex;
  257. justify-content: space-between;
  258. align-items: center;
  259. border-bottom: 1px solid #ccc;
  260. padding-bottom: 4px;
  261. }
  262. .footer-btn {
  263. display: flex;
  264. justify-content: space-around;
  265. align-items: center;
  266. margin-bottom: 10px;
  267. }
  268. </style>