|
@@ -1,102 +1,321 @@
|
|
|
<template>
|
|
<template>
|
|
|
<view class="container">
|
|
<view class="container">
|
|
|
- <u-navbar title="快速盘点" :border="false" fixed safe-area-inset-top>
|
|
|
|
|
- <template #left>
|
|
|
|
|
- <u-icon name="arrow-left" color="#333333" size="20" @click="goBack"></u-icon>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #right>
|
|
|
|
|
- <u-text type="primary" text="提交" @click="onSubmit"></u-text>
|
|
|
|
|
- </template>
|
|
|
|
|
- </u-navbar>
|
|
|
|
|
|
|
+ <u-navbar title="快速盘点" :border="false" fixed safe-area-inset-top bgColor="#22ac38"
|
|
|
|
|
+ titleStyle="font-size:36rpx;color:#fff">
|
|
|
|
|
+ <template #left>
|
|
|
|
|
+ <u-icon name="arrow-left" color="#fff" size="20" @click="goBack"></u-icon>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #right>
|
|
|
|
|
+ <text style="color: #ffffff;" @click="onSubmit">提交</text>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </u-navbar>
|
|
|
<!-- 盘点信息选择区域 -->
|
|
<!-- 盘点信息选择区域 -->
|
|
|
- <view class="select-area" style="margin-top: 44px;">
|
|
|
|
|
- <u-cell-group>
|
|
|
|
|
- <u-cell title="盘点方式" :value="checkMethod" @click="showCheckMethodPicker = true" isLink />
|
|
|
|
|
- <u-cell title="目标库位" :value="location" @click="handleLocationSelect" isLink />
|
|
|
|
|
|
|
+ <view class="select-area" style="margin-top: 44px">
|
|
|
|
|
+ <u-cell-group :border="true">
|
|
|
|
|
+ <u-cell
|
|
|
|
|
+ title="盘点方式"
|
|
|
|
|
+ :value="checkMethod"
|
|
|
|
|
+ @click="showCheckMethodPicker = true"
|
|
|
|
|
+ :isLink="true"
|
|
|
|
|
+ :border="true"
|
|
|
|
|
+ />
|
|
|
|
|
+ <u-cell
|
|
|
|
|
+ title="目标库位"
|
|
|
|
|
+ :value="location"
|
|
|
|
|
+ @click="handleLocationSelect"
|
|
|
|
|
+ :isLink="true"
|
|
|
|
|
+ :border="true"
|
|
|
|
|
+ />
|
|
|
</u-cell-group>
|
|
</u-cell-group>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 盘点方式选择器 -->
|
|
<!-- 盘点方式选择器 -->
|
|
|
- <u-picker :show="showCheckMethodPicker" :columns="[checkMethodOptions]" @confirm="onCheckMethodConfirm"
|
|
|
|
|
- @cancel="showCheckMethodPicker = false" />
|
|
|
|
|
|
|
+ <u-picker
|
|
|
|
|
+ :show="showCheckMethodPicker"
|
|
|
|
|
+ :columns="[checkMethodOptions]"
|
|
|
|
|
+ @confirm="onCheckMethodConfirm"
|
|
|
|
|
+ @cancel="showCheckMethodPicker = false"
|
|
|
|
|
+ :showToolbar="true"
|
|
|
|
|
+ title="选择盘点方式"
|
|
|
|
|
+ :closeOnClickOverlay="true"
|
|
|
|
|
+ cancelText="取消"
|
|
|
|
|
+ confirmText="确定"
|
|
|
|
|
+ :itemHeight="44"
|
|
|
|
|
+ :visibleItemCount="5"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 库位选择弹出层 -->
|
|
|
|
|
+ <u-popup
|
|
|
|
|
+ :show="showLocationPopup"
|
|
|
|
|
+ mode="bottom"
|
|
|
|
|
+ @close="close"
|
|
|
|
|
+ @open="open"
|
|
|
|
|
+ :closeOnClickOverlay="true"
|
|
|
|
|
+ :round="10"
|
|
|
|
|
+ :safeAreaInsetBottom="true"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="location-popup">
|
|
|
|
|
+ <view class="location-popup-header">
|
|
|
|
|
+ <text style="flex: 1">选择库位</text>
|
|
|
|
|
+ <u-text
|
|
|
|
|
+ style="width: 40px; flex: none"
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ text="确定"
|
|
|
|
|
+ @click="onLocationConfirm"
|
|
|
|
|
+ ></u-text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="location-popup-content">
|
|
|
|
|
+ <u-input
|
|
|
|
|
+ v-model="selectedLocation"
|
|
|
|
|
+ placeholder="请输入库位"
|
|
|
|
|
+ customStyle="background-color: #f6f6f6; border-radius: 4px;"
|
|
|
|
|
+ ></u-input>
|
|
|
|
|
+ <view class="location-list">
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="location-item"
|
|
|
|
|
+ v-for="(item, index) in locationList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ @click="selectLocation(item)"
|
|
|
|
|
+ :class="{ 'location-item--selected': selectedLocation === item }"
|
|
|
|
|
+ >
|
|
|
|
|
+ <text>{{ item }}</text>
|
|
|
|
|
+ <u-icon
|
|
|
|
|
+ v-if="selectedLocation === item"
|
|
|
|
|
+ name="checkmark"
|
|
|
|
|
+ color="#19be6b"
|
|
|
|
|
+ size="16"
|
|
|
|
|
+ ></u-icon>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </u-popup>
|
|
|
|
|
|
|
|
<!-- 订单列表 -->
|
|
<!-- 订单列表 -->
|
|
|
<view class="product-details">
|
|
<view class="product-details">
|
|
|
- <LocationOrderItem v-for="(item, index) in products" :key="index" :item="item" />
|
|
|
|
|
|
|
+ <LocationOrderItem v-for="(item, index) in products" :isLink :key="index" :item="item" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <view class="add-btn" @click="handleAdd">
|
|
|
|
|
+ <u-icon name="plus-circle" size="40" color="#19be6b" @click="openScan"></u-icon>
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
- <view class="add-btn" @click="handleAdd">
|
|
|
|
|
- <u-icon name="plus-circle" size="40" color="#19be6b" @click="openScan"></u-icon>
|
|
|
|
|
- </view>
|
|
|
|
|
|
|
|
|
|
<!-- 底部扫码输入框 -->
|
|
<!-- 底部扫码输入框 -->
|
|
|
- <view class="fixed-bottom pad-20" style="background: #ffffff;">
|
|
|
|
|
- <u-search placeholder="请输入快递单号/订单编号" v-model="searchValue" @confirm="onSearch" :show-action="false"
|
|
|
|
|
- custom-style="margin-right:10px"></u-search>
|
|
|
|
|
|
|
+ <view class="fixed-bottom pad-20" style="background: #ffffff">
|
|
|
|
|
+ <u-search
|
|
|
|
|
+ placeholder="请输入快递单号/订单编号"
|
|
|
|
|
+ v-model="searchValue"
|
|
|
|
|
+ @search="onSearch"
|
|
|
|
|
+ :show-action="false"
|
|
|
|
|
+ custom-style="margin-right:10px"
|
|
|
|
|
+ ></u-search>
|
|
|
<u-icon name="scan" size="28" color="#19be6b" @click="openScan"></u-icon>
|
|
<u-icon name="scan" size="28" color="#19be6b" @click="openScan"></u-icon>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import {
|
|
|
|
|
- reactive,
|
|
|
|
|
- ref
|
|
|
|
|
-} from 'vue'
|
|
|
|
|
-import LocationOrderItem from './components/LocationOrderItem.vue'
|
|
|
|
|
|
|
+import { reactive, ref } from "vue";
|
|
|
|
|
+import { onLoad,onUnload } from "@dcloudio/uni-app";
|
|
|
|
|
+import LocationOrderItem from "./components/LocationOrderItem.vue";
|
|
|
|
|
+
|
|
|
|
|
+const goBack = () => {
|
|
|
|
|
+ uni.navigateBack();
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
// 盘点方式相关
|
|
// 盘点方式相关
|
|
|
-const showCheckMethodPicker = ref(false)
|
|
|
|
|
-const checkMethod = ref('实际数量')
|
|
|
|
|
-const checkMethodOptions = ['实际数量', '增加数量', '减少数量']
|
|
|
|
|
|
|
+const showCheckMethodPicker = ref(false);
|
|
|
|
|
+const checkMethod = ref("实际数量");
|
|
|
|
|
+const resetType = ref(1);
|
|
|
|
|
+const checkMethodOptions = ["实际数量", "增加数量", "减少数量"];
|
|
|
|
|
+
|
|
|
|
|
+//获取用户的默认仓库
|
|
|
|
|
+const getUserDefaultWarehouse = () => {
|
|
|
|
|
+ uni.$u.http.get("/app/appUser/getUserBindGodown").then((res) => {
|
|
|
|
|
+ if (res.code == 200) {
|
|
|
|
|
+ getWarehouseLocationList(res.data.id);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
// 库位相关
|
|
// 库位相关
|
|
|
-const location = ref('k01-01-4A')
|
|
|
|
|
|
|
+const location = ref("");
|
|
|
|
|
+const showLocationPopup = ref(false);
|
|
|
|
|
+const locationList = ref([]);
|
|
|
|
|
+const selectedLocation = ref("");
|
|
|
|
|
+
|
|
|
|
|
+//根据仓库获取库位列表
|
|
|
|
|
+const godownId = ref()
|
|
|
|
|
+const getWarehouseLocationList = (id) => {
|
|
|
|
|
+ godownId.value = id
|
|
|
|
|
+ uni.$u.http.get("/app/stock/getGodownPosition?godownId=" + id).then((res) => {
|
|
|
|
|
+ if (res.code == 200) {
|
|
|
|
|
+ locationList.value = res.data;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
// 其他数据
|
|
// 其他数据
|
|
|
-const searchValue = ref('')
|
|
|
|
|
-const products = ref([{
|
|
|
|
|
- orderNo: '4846464',
|
|
|
|
|
- logisticsNo: "DPK2023497491611",
|
|
|
|
|
- inspectionDate: "2024-11-14",
|
|
|
|
|
- badCount: 5,
|
|
|
|
|
- operator: '李程雪',
|
|
|
|
|
-},
|
|
|
|
|
-{
|
|
|
|
|
- orderNo: '4846464',
|
|
|
|
|
- logisticsNo: "DPK2023497491611",
|
|
|
|
|
- inspectionDate: "2024-11-14",
|
|
|
|
|
- badCount: 5,
|
|
|
|
|
- operator: '李程雪',
|
|
|
|
|
-}
|
|
|
|
|
-])
|
|
|
|
|
|
|
+const searchValue = ref("");
|
|
|
|
|
+const products = ref([]);
|
|
|
|
|
|
|
|
// 方法
|
|
// 方法
|
|
|
const onCheckMethodConfirm = (e) => {
|
|
const onCheckMethodConfirm = (e) => {
|
|
|
- checkMethod.value = e.value[0]
|
|
|
|
|
- showCheckMethodPicker.value = false
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ checkMethod.value = e.value[0];
|
|
|
|
|
+ showCheckMethodPicker.value = false;
|
|
|
|
|
+ resetType.value = e.indexs[0] + 1;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const handleLocationSelect = () => {
|
|
const handleLocationSelect = () => {
|
|
|
- // 跳转到库位选择页面
|
|
|
|
|
- uni.navigateTo({
|
|
|
|
|
- url: '/pages/location-select/index'
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ showLocationPopup.value = true;
|
|
|
|
|
+ selectedLocation.value = location.value;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const onLocationConfirm = () => {
|
|
|
|
|
+ if (selectedLocation.value) {
|
|
|
|
|
+ location.value = selectedLocation.value;
|
|
|
|
|
+ showLocationPopup.value = false;
|
|
|
|
|
+ selectedLocation.value = "";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.$u.toast("请选择库位");
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const selectLocation = (item) => {
|
|
|
|
|
+ selectedLocation.value = item;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+//盘点提交
|
|
|
|
|
+const onSubmit = () => {
|
|
|
|
|
+ if (products.value.length === 0) {
|
|
|
|
|
+ uni.$u.toast('请添加盘点订单');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 构建请求参数
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ godownId: godownId.value,
|
|
|
|
|
+ positionCode: location.value,
|
|
|
|
|
+ orderInfo: products.value.map(item => ({
|
|
|
|
|
+ orderId: item.orderId,
|
|
|
|
|
+ waybillCode: item.waybillCode,
|
|
|
|
|
+ bookNum: item.badNum,
|
|
|
|
|
+ remark: item.remark || ''
|
|
|
|
|
+ })),
|
|
|
|
|
+ resetType: resetType.value
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 调用重置库存API
|
|
|
|
|
+ uni.$u.http.post('/app/stock/resetStock', params).then(res => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ uni.$u.toast('盘点成功');
|
|
|
|
|
+ location.value = ""
|
|
|
|
|
+ products.value = []
|
|
|
|
|
+ searchValue.value = ""
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.$u.toast(res.msg || '提交失败');
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ uni.$u.toast('提交失败');
|
|
|
|
|
+ console.error(err);
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const onSearch = () => {
|
|
const onSearch = () => {
|
|
|
- // 实现搜索逻辑
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ if (!searchValue.value) {
|
|
|
|
|
+ uni.$u.toast('请输入快递单号或订单编号');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 判断搜索类型:纯数字为订单号(searchType=1),字母+数字组合为物流单号(searchType=2)
|
|
|
|
|
+ const searchType = /^[0-9]+$/.test(searchValue.value) ? 1 : 2;
|
|
|
|
|
+
|
|
|
|
|
+ // 调用接口获取订单数据
|
|
|
|
|
+ uni.$u.http.get('/app/stock/searchBadOrderForReset', {
|
|
|
|
|
+ params: {
|
|
|
|
|
+ searchType,
|
|
|
|
|
+ search: searchValue.value
|
|
|
|
|
+ }
|
|
|
|
|
+ }).then(res => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ // 检查是否已存在相同订单
|
|
|
|
|
+ const exists = products.value.some(item =>
|
|
|
|
|
+ item.orderId === res.data.orderId ||
|
|
|
|
|
+ item.waybillCode === res.data.waybillCode
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (exists) {
|
|
|
|
|
+ uni.$u.toast('该订单已添加');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加新订单到列表
|
|
|
|
|
+ products.value.push(res.data);
|
|
|
|
|
+ searchValue.value = ''; // 清空搜索框
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.$u.toast(res.msg || '查询失败');
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ uni.$u.toast('查询失败');
|
|
|
|
|
+ console.error(err);
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const openScan = () => {
|
|
const openScan = () => {
|
|
|
- // 实现扫描逻辑
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ // #ifdef APP-PLUS || MP-WEIXIN
|
|
|
|
|
+ uni.scanCode({
|
|
|
|
|
+ success: (res) => {
|
|
|
|
|
+ searchValue.value = res.result;
|
|
|
|
|
+ onSearch();
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ uni.showToast({
|
|
|
|
|
+ title: '扫码失败',
|
|
|
|
|
+ icon: 'error'
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // #endif
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
-function handleAdd(){
|
|
|
|
|
- uni.navigateTo({
|
|
|
|
|
- url:"/pages/index/wms/speedy-check-add"
|
|
|
|
|
- })
|
|
|
|
|
|
|
+function handleAdd() {
|
|
|
|
|
+ if (!location.value) {
|
|
|
|
|
+ uni.$u.toast("请选择库位");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ uni.navigateTo({
|
|
|
|
|
+ url: "/pages/index/wms/speedy-check-add?location=" + location.value,
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+const close = () => {
|
|
|
|
|
+ showLocationPopup.value = false;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const open = () => {
|
|
|
|
|
+ showLocationPopup.value = true;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+onLoad(() => {
|
|
|
|
|
+ getUserDefaultWarehouse();
|
|
|
|
|
+
|
|
|
|
|
+ uni.$on('selectedProducts', (list) => {
|
|
|
|
|
+ products.value = list;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // #ifdef APP-PLUS
|
|
|
|
|
+ uni.$u.useGlobalEvent((e) => {
|
|
|
|
|
+ if (e.barcode) {
|
|
|
|
|
+ searchValue.value = e.barcode;
|
|
|
|
|
+ onSearch();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // #endif
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+onUnload(() => {
|
|
|
|
|
+ uni.$off('selectedProducts');
|
|
|
|
|
+});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
@@ -120,11 +339,66 @@ function handleAdd(){
|
|
|
box-shadow: 0 -2rpx 6rpx rgba(0, 0, 0, 0.1);
|
|
box-shadow: 0 -2rpx 6rpx rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.add-btn{
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- bottom: 30%;
|
|
|
|
|
- z-index: 99;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
|
|
+.add-btn {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 30%;
|
|
|
|
|
+ z-index: 99;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.location-input-wrapper {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.location-popup {
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+
|
|
|
|
|
+ &-header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding-bottom: 24rpx;
|
|
|
|
|
+ border-bottom: 1px solid #eee;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+
|
|
|
|
|
+ text {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .u-button {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 20rpx;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-content {
|
|
|
|
|
+ padding: 20rpx 0;
|
|
|
|
|
+ max-height: 600rpx;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.location-list {
|
|
|
|
|
+ margin-top: 20rpx;
|
|
|
|
|
+ max-height: 400rpx;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.location-item {
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ border-bottom: 1px solid #eee;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+
|
|
|
|
|
+ &--selected {
|
|
|
|
|
+ color: #19be6b;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-</style>
|
|
|
|
|
|
|
+</style>
|