From cc3001ab9e0ab8ce673b812a22ebea1edd332f2a Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期六, 14 三月 2026 15:38:33 +0800
Subject: [PATCH] fix: 完成仓储物流的功能开发
---
src/pages/inventoryManagement/stockManagement/add.vue | 426 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 426 insertions(+), 0 deletions(-)
diff --git a/src/pages/inventoryManagement/stockManagement/add.vue b/src/pages/inventoryManagement/stockManagement/add.vue
new file mode 100644
index 0000000..6c69d85
--- /dev/null
+++ b/src/pages/inventoryManagement/stockManagement/add.vue
@@ -0,0 +1,426 @@
+<template>
+ <view class="add-stock-page">
+ <PageHeader title="鏂板搴撳瓨" @back="goBack" />
+
+ <scroll-view scroll-y class="content-scroll">
+ <view class="form-section">
+ <view class="form-row">
+ <text class="form-label required">浜у搧鍚嶇О</text>
+ <view class="selector-trigger" @click="openProductSelector">
+ <text class="selector-text" :class="{ placeholder: !form.productName }">
+ {{ form.productName || '璇烽�夋嫨浜у搧' }}
+ </text>
+ <up-icon name="arrow-right" size="16" color="#999"></up-icon>
+ </view>
+ </view>
+ <view class="form-row">
+ <text class="form-label">瑙勬牸</text>
+ <up-input v-model="form.productModelName" disabled placeholder="璇烽�夋嫨浜у搧鍚庤嚜鍔ㄥ甫鍑�" />
+ </view>
+ <view class="form-row">
+ <text class="form-label">鍗曚綅</text>
+ <up-input v-model="form.unit" disabled placeholder="璇烽�夋嫨浜у搧鍚庤嚜鍔ㄥ甫鍑�" />
+ </view>
+ </view>
+
+ <!-- 鍚堟牸搴撳瓨鏃舵樉绀鸿繃纾呯浉鍏冲瓧娈� -->
+ <view v-if="isQualified" class="form-section">
+ <view class="section-title">杩囩淇℃伅</view>
+ <view class="form-row">
+ <text class="form-label">杞︾墝鍙�</text>
+ <up-input v-model="form.licensePlateNo" placeholder="璇疯緭鍏ヨ溅鐗屽彿" />
+ </view>
+ <view class="form-row">
+ <text class="form-label">姣涢噸(鍚�)</text>
+ <up-input
+ v-model="form.grossWeight"
+ type="number"
+ placeholder="璇疯緭鍏ユ瘺閲�"
+ />
+ </view>
+ <view class="form-row">
+ <text class="form-label">鐨噸(鍚�)</text>
+ <up-input
+ v-model="form.tareWeight"
+ type="number"
+ placeholder="璇疯緭鍏ョ毊閲�"
+ />
+ </view>
+ <view class="form-row">
+ <text class="form-label">鍑�閲�(鍚�)</text>
+ <up-input
+ v-model="form.netWeight"
+ type="number"
+ disabled
+ placeholder="鑷姩璁$畻"
+ />
+ </view>
+ <view class="form-row">
+ <text class="form-label">杩囩鏃ユ湡</text>
+ <view class="selector-trigger" @click="openWeighingDatePicker">
+ <text class="selector-text" :class="{ placeholder: !form.weighingDate }">
+ {{ form.weighingDate || '璇烽�夋嫨杩囩鏃ユ湡' }}
+ </text>
+ <up-icon name="calendar" size="16" color="#999"></up-icon>
+ </view>
+ </view>
+ <view class="form-row">
+ <text class="form-label">杩囩鍛�</text>
+ <up-input v-model="form.weighingOperator" placeholder="璇疯緭鍏ヨ繃纾呭憳" />
+ </view>
+ </view>
+
+ <view class="form-section">
+ <!-- <view class="form-row">
+ <text class="form-label required">鏁伴噺</text>
+ <up-input v-model="form.qualitity" type="number" placeholder="璇疯緭鍏ユ暟閲�" />
+ </view> -->
+ <view class="form-row">
+ <text class="form-label">澶囨敞</text>
+ <up-input v-model="form.remark" type="textarea" placeholder="閫夊~" />
+ </view>
+ </view>
+ </scroll-view>
+
+ <!-- 鎻愪氦鎸夐挳 -->
+ <view class="bottom-bar">
+ <view class="btn-submit" @click="handleSubmit">鎻愪氦</view>
+ </view>
+
+ <!-- 浜у搧閫夋嫨寮圭獥锛堢畝鍖栫増 ProductSelectDialog锛� -->
+ <up-popup :show="showProductPopup" mode="bottom" @close="showProductPopup = false">
+ <view class="product-popup">
+ <view class="popup-header">
+ <text class="popup-title">閫夋嫨浜у搧</text>
+ </view>
+ <view class="popup-search">
+ <up-input
+ v-model="productQuery.productName"
+ placeholder="浜у搧澶х被"
+ clearable
+ />
+ <up-input
+ v-model="productQuery.model"
+ placeholder="鍨嬪彿鍚嶇О"
+ clearable
+ />
+ <view class="popup-search-btn" @click="loadProductList">鎼滅储</view>
+ </view>
+ <scroll-view scroll-y class="product-list">
+ <view
+ v-for="item in productList"
+ :key="item.id"
+ class="product-item"
+ @click="selectProduct(item)"
+ >
+ <view class="product-name-row">
+ <text class="product-name">{{ item.productName }}</text>
+ <text class="product-unit">{{ item.unit }}</text>
+ </view>
+ <view class="product-model">鍨嬪彿锛歿{ item.model }}</view>
+ </view>
+ <view v-if="!productLoading && productList.length === 0" class="no-data">
+ 鏆傛棤鏁版嵁
+ </view>
+ </scroll-view>
+ </view>
+ </up-popup>
+
+ <!-- 杩囩鏃ユ湡閫夋嫨鍣� -->
+ <up-popup :show="showWeighingDatePicker" mode="bottom" @close="showWeighingDatePicker = false">
+ <up-datetime-picker
+ :show="true"
+ v-model="weighingDateValue"
+ mode="datetime"
+ @confirm="onWeighingDateConfirm"
+ @cancel="showWeighingDatePicker = false"
+ />
+ </up-popup>
+ </view>
+</template>
+
+<script setup>
+import { ref, reactive, computed, watch } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import dayjs from 'dayjs'
+import PageHeader from '@/components/PageHeader.vue'
+import { createStockInventory } from '@/api/inventoryManagement/stockInventory.js'
+import { createStockUnInventory } from '@/api/inventoryManagement/stockUninventory.js'
+import { productModelList } from '@/api/basicData/productModel.js'
+
+const form = reactive({
+ productId: undefined,
+ productModelId: undefined,
+ productName: '',
+ productModelName: '',
+ unit: '',
+ productType: undefined,
+ licensePlateNo: '',
+ grossWeight: '',
+ tareWeight: '',
+ netWeight: '',
+ weighingDate: '',
+ weighingOperator: '',
+ qualitity: '',
+ remark: ''
+})
+
+const type = ref('0') // 0 鍚堟牸搴撳瓨锛�1 涓嶅悎鏍煎簱瀛�
+const isQualified = computed(() => type.value === '0')
+
+const showProductPopup = ref(false)
+const productQuery = reactive({
+ productName: '',
+ model: ''
+})
+const productList = ref([])
+const productLoading = ref(false)
+
+const showWeighingDatePicker = ref(false)
+const weighingDateValue = ref(Date.now())
+
+onLoad((options) => {
+ if (options && options.type != null) {
+ type.value = options.type
+ }
+})
+
+const openProductSelector = () => {
+ showProductPopup.value = true
+ if (productList.value.length === 0) {
+ loadProductList()
+ }
+}
+
+const loadProductList = () => {
+ productLoading.value = true
+ productModelList({
+ productName: productQuery.productName || '',
+ model: productQuery.model || '',
+ current: 1,
+ size: 20
+ })
+ .then(res => {
+ const data = res?.records || res?.data?.records || []
+ productList.value = Array.isArray(data) ? data : []
+ })
+ .finally(() => {
+ productLoading.value = false
+ })
+}
+
+const selectProduct = (item) => {
+ form.productId = item.productId || item.id
+ form.productModelId = item.id
+ form.productName = item.productName
+ form.productModelName = item.model
+ form.unit = item.unit
+ form.productType = item.productType
+ showProductPopup.value = false
+}
+
+// 鍑�閲� = 姣涢噸 - 鐨噸
+const computeNetWeight = () => {
+ const gross = Number(form.grossWeight)
+ const tare = Number(form.tareWeight)
+ if (!isNaN(gross) && !isNaN(tare)) {
+ const net = Number((gross - tare).toFixed(2))
+ form.netWeight = net > 0 ? net : 0
+ } else {
+ form.netWeight = ''
+ }
+}
+
+// 鐩戝惉姣涢噸銆佺毊閲嶅彉鍖栵紝鑷姩璁$畻鍑�閲�
+watch(
+ () => [form.grossWeight, form.tareWeight],
+ () => {
+ computeNetWeight()
+ }
+)
+
+const openWeighingDatePicker = () => {
+ weighingDateValue.value = form.weighingDate
+ ? dayjs(form.weighingDate, 'YYYY-MM-DD HH:mm:ss').valueOf()
+ : Date.now()
+ showWeighingDatePicker.value = true
+}
+
+const onWeighingDateConfirm = (e) => {
+ const ts = e?.value ?? weighingDateValue.value
+ form.weighingDate = dayjs(ts).format('YYYY-MM-DD HH:mm:ss')
+ showWeighingDatePicker.value = false
+}
+
+const handleSubmit = () => {
+ if (!form.productName || !form.productModelId) {
+ uni.showToast({ title: '璇烽�夋嫨浜у搧', icon: 'none' })
+ return
+ }
+ // if (!form.qualitity || Number(form.qualitity) <= 0) {
+ // uni.showToast({ title: '璇疯緭鍏ユ暟閲�', icon: 'none' })
+ // return
+ // }
+ const payload = {
+ productId: form.productId,
+ productModelId: form.productModelId,
+ productName: form.productName,
+ productModelName: form.productModelName,
+ unit: form.unit,
+ productType: form.productType,
+ licensePlateNo: form.licensePlateNo,
+ grossWeight: form.grossWeight,
+ tareWeight: form.tareWeight,
+ netWeight: form.netWeight,
+ weighingDate: form.weighingDate,
+ weighingOperator: form.weighingOperator,
+ remark: form.remark
+ }
+ const api = isQualified.value ? createStockInventory : createStockUnInventory
+ api(payload)
+ .then(() => {
+ uni.showToast({ title: '鏂板鎴愬姛', icon: 'success' })
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 400)
+ })
+ .catch(() => {
+ uni.showToast({ title: '鏂板澶辫触', icon: 'none' })
+ })
+}
+
+const goBack = () => uni.navigateBack()
+</script>
+
+<style lang="scss" scoped>
+.add-stock-page {
+ min-height: 100vh;
+ background: #f5f5f5;
+ padding-bottom: 100rpx;
+}
+.content-scroll {
+ height: calc(100vh - 100rpx);
+}
+.form-section {
+ background: #fff;
+ margin: 24rpx;
+ padding: 24rpx;
+ border-radius: 16rpx;
+}
+.section-title {
+ font-size: 28rpx;
+ font-weight: 500;
+ color: #333;
+ margin-bottom: 12rpx;
+}
+.form-row {
+ margin-bottom: 24rpx;
+}
+.form-label {
+ display: block;
+ font-size: 26rpx;
+ color: #666;
+ margin-bottom: 12rpx;
+}
+.form-label.required::after {
+ content: '*';
+ color: #f56c6c;
+ margin-left: 6rpx;
+}
+.selector-trigger {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20rpx 24rpx;
+ background: #f5f5f5;
+ border-radius: 12rpx;
+}
+.selector-text {
+ font-size: 28rpx;
+ color: #333;
+}
+.selector-text.placeholder {
+ color: #999;
+}
+.bottom-bar {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: #fff;
+ box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.04);
+}
+.btn-submit {
+ height: 88rpx;
+ border-radius: 999rpx;
+ background: #2979ff;
+ color: #fff;
+ font-size: 30rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.product-popup {
+ background: #fff;
+ border-radius: 24rpx 24rpx 0 0;
+ padding-bottom: env(safe-area-inset-bottom);
+}
+.popup-header {
+ padding: 24rpx;
+ border-bottom: 1rpx solid #eee;
+}
+.popup-title {
+ font-size: 30rpx;
+ font-weight: 500;
+ color: #333;
+}
+.popup-search {
+ padding: 16rpx 24rpx;
+ display: flex;
+ flex-direction: column;
+ gap: 12rpx;
+}
+.popup-search-btn {
+ margin-top: 8rpx;
+ align-self: flex-end;
+ padding: 12rpx 32rpx;
+ border-radius: 999rpx;
+ background: #2979ff;
+ color: #fff;
+ font-size: 26rpx;
+}
+.product-list {
+ max-height: 600rpx;
+ padding: 0 24rpx 24rpx;
+}
+.product-item {
+ padding: 20rpx 0;
+ border-bottom: 1rpx solid #f0f0f0;
+}
+.product-name-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8rpx;
+}
+.product-name {
+ font-size: 28rpx;
+ color: #333;
+}
+.product-unit {
+ font-size: 24rpx;
+ color: #999;
+}
+.product-model {
+ font-size: 24rpx;
+ color: #666;
+}
+.no-data {
+ text-align: center;
+ padding: 40rpx 0;
+ color: #999;
+ font-size: 26rpx;
+}
+</style>
+
--
Gitblit v1.9.3