Files
FT541-WMS/RuoYi-App-master/pages/in/inorder.vue

437 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<view class="search-box">
<uni-easyinput
v-model="stockinId"
placeholder="请输入或扫码输入单据号"
:clearable="true"
@clear="handleClear"
@confirm="handleSearch"
@input="handleSearch"
ref="detailIdInput">
<template #right>
<text class="scan-icon" @click="handleScan">📷</text>
</template>
</uni-easyinput>
</view>
<view class="card-list">
<view v-if="orderList && orderList.length > 0">
<view v-for="(order, index) in orderList" :key="index" class="order-card">
<uni-card>
<view class="card-content">
<view class="order-header" @click="handleOrderClick(order)">
<view class="info-row">
<text class="label">单据编号:</text>
<text class="value">{{ order.stockinId }}</text>
</view>
<view class="info-row">
<text class="label">创建时间:</text>
<text class="value">{{ order.createDate }}</text>
</view>
<view class="info-row">
<text class="label">供应商</text>
<text class="value">{{ order.supplierName }}</text>
</view>
</view>
<!-- 展开时显示物料信息 -->
<view v-if="order.expanded && order.goodsList" class="goods-list" @click.stop>
<view class="goods-title">物品信息</view>
<view class="goods-table">
<view class="table-header">
<text class="header-cell" style="display: none;">物品编码</text>
<text class="header-cell">物品名称</text>
<text class="header-cell">计划数量</text>
<text class="header-cell">入库数量</text>
</view>
<view v-for="(goods, goodsIndex) in order.goodsList" :key="goodsIndex" class="table-row">
<text class="table-cell" style="display: none;">{{ goods.productId }}</text>
<text class="table-cell material-name">{{ goods.extraField.materialDesc }}</text>
<text class="table-cell">{{ goods.quantity }}</text>
<view class="table-cell">
<uni-easyinput
v-model="goods.inQuantity"
type="number"
:maxlength="String(goods.quantity-goods.assignNum).length"
:max="goods.quantity-goods.assignNum"
@input="handleInQuantityChange(goods)"
:min="0"
style="width: 180rpx; display: inline-block;"
/>
</view>
<view class="table-cell">
<button class="operate-btn" @click.stop="handleInStock(goods)" :class="{'operate-btn-disabled': !isValidQuantity(goods)}">
入库
</button>
</view>
</view>
</view>
</view>
</view>
</uni-card>
</view>
</view>
<view v-else class="no-data">暂无入库单信息</view>
</view>
</view>
</template>
<script>
import { getInOrderList, getInOrderDetail, pkIn } from '@/api/in/order'
export default {
data() {
return {
stockinId: "",
orderList: [],
needRefresh: false
}
},
onReady() {
setTimeout(() => {
this.$nextTick(() => {
this.$refs.detailIdInput.onFocus()
})
}, 100)
},
onLoad() {
this.getOrderList()
},
onShow() {
if (this.needRefresh) {
this.getOrderList()
this.needRefresh = false
}
},
methods: {
// 获取入库单列表
async getOrderList() {
try {
const response = await getInOrderList({"stockinId":this.stockinId})
this.orderList = response.map(order => ({
...order,
expanded: false,
goodsList: null
}))
} catch (error) {
console.error('获取入库单列表失败:', error)
uni.showToast({
title: '获取入库单列表失败',
icon: 'none'
})
}
},
// 获取物品列表
async getGoodsList(order) {
try {
const goodsResponse = await getInOrderDetail({
stockinId: order.stockinId,
pageSize:100,
pageNum:1,
status:1
})
order.goodsList = goodsResponse.rows.map(item => ({
...item,
inQuantity: item.quantity-item.assignNum
}))
} catch (error) {
console.error('获取物品信息失败:', error)
uni.showToast({
title: '获取物品信息失败',
icon: 'none'
})
}
},
// 处理入库单点击
async handleOrderClick(order) {
// 切换展开状态
order.expanded = !order.expanded
// 如果展开且还没有加载物品列表,则加载物品列表
if (order.expanded && !order.goodsList) {
await this.getGoodsList(order)
}
},
// 处理搜索
handleSearch(value) {
if (value !== undefined) {
this.stockinId = value
}
this.getOrderList()
},
// 处理清除
handleClear() {
this.stockinId = ""
this.getOrderList()
},
// 处理扫码
handleScan() {
uni.scanCode({
success: (res) => {
this.stockinId = res.result
this.getOrderList()
}
})
},
// 验证入库数量是否有效
isValidQuantity(goods) {
const inQuantity = Number(goods.inQuantity);
return inQuantity > 0 && inQuantity <= (goods.quantity - goods.assignNum);
},
// 处理入库数量变化
handleInQuantityChange(goods) {
const maxQuantity = goods.quantity - goods.assignNum;
if (Number(goods.inQuantity) > maxQuantity) {
goods.inQuantity = maxQuantity;
uni.showToast({
title: '超出可入库数量',
icon: 'none'
});
}
},
// 处理入库操作
async handleInStock(goods) {
if (!this.isValidQuantity(goods)) {
uni.showToast({
title: '请输入有效的入库数量',
icon: 'none'
})
return
}
try {
await pkIn({
stockinDetailId: goods.stockinDetailId,
inQuantity: goods.inQuantity
})
uni.showToast({
title: '入库成功',
icon: 'success'
})
// 刷新列表
this.getOrderList()
} catch (error) {
console.error('入库操作失败:', error)
uni.showToast({
title: '入库失败',
icon: 'none'
})
}
}
}
}
</script>
<style lang="scss">
.container {
padding: 20rpx;
background-color: #f8f9fc;
}
.search-box {
margin-bottom: 20rpx;
position: relative;
background-color: #fff;
border-radius: 8rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
padding: 20rpx;
:deep(.uni-easyinput__content) {
background-color: #f8f9fc;
border-radius: 6rpx;
border: 2rpx solid #e8e8e8;
transition: all 0.3s ease;
&:hover, &:focus-within {
border-color: #409eff;
}
}
.scan-icon {
padding: 0 20rpx;
font-size: 40rpx;
line-height: 70rpx;
color: #409eff;
cursor: pointer;
transition: opacity 0.3s ease;
&:hover {
opacity: 0.8;
}
}
}
.card-list {
.order-card {
margin-bottom: 20rpx;
transition: all 0.3s ease;
:deep(.uni-card) {
background-color: #fff;
border-radius: 8rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
border: none;
overflow: hidden;
}
&:hover {
transform: translateY(-2rpx);
:deep(.uni-card) {
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
}
}
}
.card-content {
.info-row {
display: flex;
margin-bottom: 16rpx;
align-items: center;
&:last-child {
margin-bottom: 0;
}
.label {
color: #909399;
width: 160rpx;
font-size: 28rpx;
}
.value {
color: #303133;
flex: 1;
font-size: 28rpx;
}
}
}
.goods-list {
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 2rpx solid #ebeef5;
.goods-title {
font-size: 28rpx;
color: #606266;
margin-bottom: 16rpx;
font-weight: bold;
}
.goods-table {
width: 100%;
border-radius: 6rpx;
overflow: hidden;
background-color: #f8f9fc;
.table-header {
display: flex;
background-color: #f2f3f5;
padding: 16rpx;
.header-cell {
flex: 1;
color: #606266;
font-size: 26rpx;
font-weight: bold;
text-align: center;
&:nth-child(1) {
flex: 2;
}
&:nth-child(2), &:nth-child(3) {
flex: 0.8;
}
&:nth-child(4) {
flex: 1.2;
}
}
}
.table-row {
display: flex;
padding: 16rpx;
border-bottom: 2rpx solid #ebeef5;
&:last-child {
border-bottom: none;
}
.table-cell {
flex: 1;
color: #303133;
font-size: 26rpx;
text-align: center;
padding: 0 8rpx;
display: flex;
align-items: center;
justify-content: center;
&:nth-child(1) {
flex: 2;
}
&:nth-child(2), &:nth-child(3) {
flex: 0.8;
}
&:nth-child(4) {
flex: 1.2;
}
&.material-name {
overflow: visible;
white-space: normal;
word-break: break-word;
justify-content: flex-start;
}
.operate-btn {
background-color: #409eff;
color: #fff;
border: none;
padding: 4rpx 20rpx;
border-radius: 4rpx;
font-size: 24rpx;
cursor: pointer;
&:hover {
background-color: #66b1ff;
}
&:active {
background-color: #3a8ee6;
}
}
}
}
}
.no-goods {
text-align: center;
color: #909399;
font-size: 26rpx;
padding: 30rpx 0;
}
}
.operate-btn-disabled {
background-color: #c0c4cc !important;
cursor: not-allowed !important;
opacity: 0.6 !important;
&:hover {
background-color: #c0c4cc !important;
}
}
</style>