diff --git a/src/pages/stock/in.vue b/src/pages/stock/in.vue
index eee09c1..a2d25de 100644
--- a/src/pages/stock/in.vue
+++ b/src/pages/stock/in.vue
@@ -1,45 +1,121 @@
-
-
-
- 商品
-
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+ {{ item.spec || '-' }}
+
+
+ +
+
-
-
-
-
- 入库数量
-
-
-
-
- 备注
-
-
+
+
+ 📭
+ 暂无商品
+
+
+
-
+
+
+
+
+
+
+ {{ item.productName }}
+ × {{ item.quantity }}
+
+ ×
+
+
+
+
+
+
+
+ 共 {{ totalQuantity }} 件
+
+
+
+
+
@@ -50,55 +126,131 @@ import productApi from '@/api/product'
export default {
data() {
return {
+ categoryId: '',
+ categories: [],
productList: [],
- selectedProduct: null,
- quantity: '',
- remark: '',
+ page: 1,
+ pageSize: 50,
+ loading: false,
+
+ // 已选择的商品
+ selectedItems: [],
+
+ // 弹窗相关
+ showPopup: false,
+ currentProduct: {},
+ inputQuantity: 1,
+ inputRemark: '',
+
+ // 提交状态
submitting: false
}
},
+ computed: {
+ totalQuantity() {
+ return this.selectedItems.reduce((sum, item) => sum + item.quantity, 0)
+ }
+ },
onLoad() {
+ this.loadCategories()
this.getProducts()
},
methods: {
- async getProducts() {
+ async loadCategories() {
try {
- const res = await productApi.getProducts({ page: 1, pageSize: 100 })
- if (res.code === 0) {
- this.productList = res.data.records || []
- }
+ const categories = await productApi.getCategories()
+ this.categories = categories || []
} catch (e) {
- uni.showToast({ title: '加载商品失败', icon: 'none' })
+ console.error(e)
}
},
- onProductChange(e) {
- this.selectedProduct = this.productList[e.detail.value]
+ async getProducts() {
+ this.loading = true
+ try {
+ const res = await productApi.getProducts({
+ categoryId: this.categoryId,
+ page: this.page,
+ pageSize: this.pageSize
+ })
+ this.productList = res.records || []
+ } catch (e) {
+ uni.showToast({ title: '加载失败', icon: 'none' })
+ } finally {
+ this.loading = false
+ }
},
- async submit() {
- if (!this.selectedProduct) {
- uni.showToast({ title: '请选择商品', icon: 'none' })
+ selectCategory(id) {
+ this.categoryId = id
+ this.page = 1
+ this.getProducts()
+ },
+ openQuantityPopup(product) {
+ this.currentProduct = product
+ this.inputQuantity = 1
+ this.inputRemark = ''
+ this.showPopup = true
+ },
+ closePopup() {
+ this.showPopup = false
+ },
+ qtyMinus() {
+ if (this.inputQuantity > 1) {
+ this.inputQuantity--
+ }
+ },
+ qtyPlus() {
+ this.inputQuantity++
+ },
+ confirmAdd() {
+ if (this.inputQuantity <= 0) {
+ uni.showToast({ title: '请输入有效数量', icon: 'none' })
return
}
- if (!this.quantity || this.quantity <= 0) {
- uni.showToast({ title: '请输入有效数量', icon: 'none' })
+
+ // 检查是否已存在,存在则累加
+ const existsIndex = this.selectedItems.findIndex(
+ item => item.productId === this.currentProduct.productId
+ )
+
+ if (existsIndex > -1) {
+ this.selectedItems[existsIndex].quantity += parseInt(this.inputQuantity)
+ this.selectedItems[existsIndex].remark = this.inputRemark || this.selectedItems[existsIndex].remark
+ } else {
+ this.selectedItems.push({
+ productId: this.currentProduct.productId,
+ productName: this.currentProduct.name,
+ quantity: parseInt(this.inputQuantity),
+ remark: this.inputRemark
+ })
+ }
+
+ this.closePopup()
+ uni.showToast({ title: '已添加', icon: 'success' })
+ },
+ removeItem(index) {
+ this.selectedItems.splice(index, 1)
+ },
+ async submit() {
+ if (this.selectedItems.length === 0) {
+ uni.showToast({ title: '请先添加商品', icon: 'none' })
return
}
this.submitting = true
try {
- const res = await stockApi.stockIn({
- productId: this.selectedProduct.productId,
- quantity: parseInt(this.quantity),
- remark: this.remark
- })
- if (res.code === 0) {
- uni.showToast({ title: '入库成功', icon: 'success' })
- setTimeout(() => {
- uni.navigateBack()
- }, 1500)
- } else {
- uni.showToast({ title: res.message || '入库失败', icon: 'none' })
+ // 逐个入库
+ for (const item of this.selectedItems) {
+ await stockApi.stockIn({
+ productId: item.productId,
+ quantity: item.quantity,
+ remark: item.remark || ''
+ })
}
+
+ uni.showToast({ title: '入库成功', icon: 'success' })
+ setTimeout(() => {
+ uni.navigateBack()
+ }, 1500)
} catch (e) {
uni.showToast({ title: '入库失败', icon: 'none' })
} finally {
@@ -109,54 +261,346 @@ export default {
}
-
+
+.popup-content {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #fff;
+ border-radius: 32rpx 32rpx 0 0;
+ padding: 40rpx 30rpx;
+ padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
+ z-index: 101;
+}
+
+.popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 30rpx;
+}
+
+.popup-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+}
+
+.popup-close {
+ font-size: 48rpx;
+ color: #999;
+ padding: 10rpx;
+}
+
+.popup-spec {
+ font-size: 26rpx;
+ color: #666;
+ margin-bottom: 30rpx;
+}
+
+.popup-qty {
+ display: flex;
+ align-items: center;
+ margin-bottom: 30rpx;
+}
+
+.qty-label {
+ font-size: 28rpx;
+ color: #333;
+ width: 160rpx;
+}
+
+.qty-input-wrapper {
+ display: flex;
+ align-items: center;
+ background: #f5f5f5;
+ border-radius: 12rpx;
+}
+
+.qty-minus, .qty-plus {
+ width: 80rpx;
+ height: 80rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 40rpx;
+ color: #667eea;
+}
+
+.qty-input {
+ width: 120rpx;
+ height: 80rpx;
+ text-align: center;
+ font-size: 32rpx;
+ background: transparent;
+ border-left: 1rpx solid #eee;
+ border-right: 1rpx solid #eee;
+}
+
+.popup-remark {
+ margin-bottom: 30rpx;
+}
+
+.remark-label {
+ font-size: 28rpx;
+ color: #333;
+ display: block;
+ margin-bottom: 16rpx;
+}
+
+.remark-input {
+ width: 100%;
+ height: 80rpx;
+ background: #f5f5f5;
+ border-radius: 12rpx;
+ padding: 0 20rpx;
+ font-size: 28rpx;
+ box-sizing: border-box;
+}
+
+.popup-footer {
+ display: flex;
+ gap: 20rpx;
+}
+
+.popup-btn {
+ flex: 1;
+ height: 88rpx;
+ line-height: 88rpx;
+ border-radius: 44rpx;
+ font-size: 30rpx;
+ font-weight: bold;
+}
+
+.popup-btn.cancel {
+ background: #f5f5f5;
+ color: #666;
+}
+
+.popup-btn.confirm {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: #fff;
+ box-shadow: 0 8rpx 30rpx rgba(102, 126, 234, 0.4);
+}
+
\ No newline at end of file