| | |
| | | </view> |
| | | |
| | | <!-- 搜索框 --> |
| | | <view class="search-bar"> |
| | | <!-- <view class="search-bar"> |
| | | <uni-search-bar v-model="condition" placeholder=" 扫码 / 输入物料" bgColor="#F5F5F5" @confirm="search" @cancel="onCancelSearch" /> |
| | | </view> |
| | | </view> --> |
| | | |
| | | <!-- 明细列表 --> |
| | | <view class="detl-list"> |
| | | <view class="detl-card" v-for="(item, index) in filterList" :key="index" @click="chose(item)"> |
| | | <!-- 卡片头部 --> |
| | | <view class="card-header"> |
| | | <view class="mat-info"> |
| | | <text class="mat-code">{{item.matnrCode}}</text> |
| | | <text class="mat-name">{{item.maktx || '-'}}</text> |
| | | </view> |
| | | <view class="qty-badge" :class="item.enableQty > 0 ? 'badge-active' : 'badge-done'"> |
| | | <text class="qty-text">剩余 {{item.enableQty}}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 卡片内容 --> |
| | | <view class="card-body"> |
| | | <view class="info-grid"> |
| | | <view class="info-item"> |
| | | <text class="info-label">规格</text> |
| | | <text class="info-value">{{item.specs || '-'}}</text> |
| | | <view class="padding-lr margin-top-sm"> |
| | | <block v-for="(item, index) in filterList" :key="index"> |
| | | <view class="cu-list menu sm-border margin-bottom-sm" @click="chose(item)"> |
| | | <view class="cu-bar bg-white solid-bottom"> |
| | | <view class="action"> |
| | | <view class="index">{{index+1}}</view> |
| | | <view class="text-blue"> |
| | | 编码: {{item.matnrCode}} |
| | | </view> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">批次</text> |
| | | <text class="info-value">{{item.splrBatch || '-'}}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">订单数量</text> |
| | | <text class="info-value highlight">{{item.anfme}}</text> |
| | | </view> |
| | | <view class="info-item"> |
| | | <text class="info-label">已完成</text> |
| | | <text class="info-value">{{item.qty}}</text> |
| | | <view class="action"> |
| | | <text :class="getRemaining(item) > 0 ? 'text-blue' : 'text-green'"> |
| | | {{getRemaining(item) > 0 ? '剩余 ' + getRemaining(item) : '已完成'}} |
| | | </text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 进度条 --> |
| | | <view class="progress-wrap"> |
| | | <view class="progress-bar"> |
| | | <view class="progress-fill" :style="{width: getProgress(item) + '%'}"></view> |
| | | <view class="cu-item"> |
| | | <view class="content"> |
| | | <text class="text-black">物料名称:</text> |
| | | <text class="text-grey text-sm margin-left-xs">{{item.maktx || '-'}}</text> |
| | | </view> |
| | | <text class="progress-text">{{getProgress(item)}}%</text> |
| | | </view> |
| | | <view class="cu-item"> |
| | | <view class="content"> |
| | | <text class="text-black">规格:</text> |
| | | <text class="text-grey margin-left-xs">{{item.specs || '-'}}</text> |
| | | </view> |
| | | <view class="action"> |
| | | <text class="text-black">批次:</text> |
| | | <text class="text-grey margin-left-xs">{{item.splrBatch || '-'}}</text> |
| | | </view> |
| | | </view> |
| | | <view class="cu-item"> |
| | | <view class="content"> |
| | | <text class="text-black">订单数量:</text> |
| | | <text class="text-blue margin-left-xs">{{item.anfme}}</text> |
| | | </view> |
| | | <view class="action"> |
| | | <text class="text-black">已完成:</text> |
| | | <text class="text-green margin-left-xs">{{item.qty}}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 卡片底部 --> |
| | | <view class="card-footer" v-if="item.ableQty > 0"> |
| | | <text class="action-text">点击出库</text> |
| | | <uni-icons type="right" size="14" color="#0081ff"></uni-icons> |
| | | </view> |
| | | <view class="card-footer card-footer-done" v-else> |
| | | <text class="done-text">已完成</text> |
| | | <uni-icons type="checkmarkempty" size="14" color="#28a745"></uni-icons> |
| | | </view> |
| | | </view> |
| | | </block> |
| | | </view> |
| | | |
| | | <!-- 空状态 --> |
| | |
| | | if (!this.condition.trim()) { |
| | | // 排序:有剩余数量的排前面 |
| | | return [...this.menuList].sort((a, b) => { |
| | | if (a.enableQty > 0 && b.enableQty <= 0) return -1; |
| | | if (a.enableQty <= 0 && b.enableQty > 0) return 1; |
| | | if (a.ableQty > 0 && b.ableQty <= 0) return -1; |
| | | if (a.ableQty <= 0 && b.ableQty > 0) return 1; |
| | | return 0; |
| | | }); |
| | | } |
| | |
| | | } |
| | | }, |
| | | methods: { |
| | | // 计算进度 |
| | | getProgress(item) { |
| | | if (!item.qty || item.qty === 0) return 0; |
| | | const progress = (item.qty / item.anfme * 100).toFixed(0); |
| | | return Math.min(100, Math.max(0, progress)); |
| | | }, |
| | | // 获取剩余数量 |
| | | getRemaining(item) { |
| | | if (item.ableQty !== undefined && item.ableQty !== null) { |
| | | return Number(item.ableQty); |
| | | } |
| | | // 降级逻辑:订单数量 - 已完成数量 |
| | | return Number(item.anfme || 0) - Number(item.qty || 0); |
| | | }, |
| | | // 搜索 |
| | | async search() { |
| | | if (!this.condition.trim()) { |
| | |
| | | }, 'POST', true); |
| | | |
| | | if (res.code === 200) { |
| | | this.menuList = res.data || []; |
| | | let list = res.data || []; |
| | | list.forEach(item => { |
| | | if (item.enableQty === undefined || item.enableQty === null) { |
| | | item.enableQty = Number(item.anfme || 0) - Number(item.qty || 0); |
| | | } |
| | | }); |
| | | this.menuList = list; |
| | | } else if (res.code === 403) { |
| | | uni.showToast({ title: res.msg, icon: "none", position: 'top' }); |
| | | setTimeout(() => { |
| | |
| | | }, 'GET', true); |
| | | |
| | | if (res.code === 200) { |
| | | this.menuList = res.data || []; |
| | | let list = res.data || []; |
| | | list.forEach(item => { |
| | | if (item.enableQty === undefined || item.enableQty === null) { |
| | | item.enableQty = Number(item.anfme || 0) - Number(item.qty || 0); |
| | | } |
| | | }); |
| | | this.menuList = list; |
| | | } else { |
| | | this.menuList = res.data || []; |
| | | } |
| | |
| | | background: #ffffff; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 129, 255, 0.08); |
| | | } |
| | | |
| | | /* 明细列表 */ |
| | | .detl-list { |
| | | padding: 0 20rpx; |
| | | } |
| | | |
| | | .detl-card { |
| | | background: #ffffff; |
| | | border-radius: 12rpx; |
| | | margin-top: 12rpx; |
| | | box-shadow: 0 2rpx 12rpx rgba(0, 129, 255, 0.08); |
| | | overflow: hidden; |
| | | transition: transform 0.2s ease; |
| | | border: 1rpx solid #e4e7ed; |
| | | } |
| | | |
| | | .detl-card:active { |
| | | transform: scale(0.98); |
| | | } |
| | | |
| | | /* 卡片头部 */ |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | padding: 14rpx 16rpx; |
| | | border-bottom: 1rpx solid #f0f0f0; |
| | | } |
| | | |
| | | .mat-info { |
| | | flex: 1; |
| | | padding-right: 12rpx; |
| | | } |
| | | |
| | | .mat-code { |
| | | font-size: 26rpx; |
| | | color: #303133; |
| | | font-weight: 600; |
| | | |
| | | /* 列表样式迁移 from rece/other.vue */ |
| | | .index { |
| | | border: 1px solid #e54d42; |
| | | color: #e54d42; |
| | | border-radius: 50%; |
| | | display: block; |
| | | width: 50rpx; |
| | | height: 50rpx; |
| | | line-height: 48rpx; |
| | | text-align: center; |
| | | margin-right: 20rpx; |
| | | font-size: 30rpx; |
| | | } |
| | | |
| | | .act { |
| | | border: 1px solid #e54d42; |
| | | } |
| | | |
| | | .text-blue { |
| | | color: #0081ff !important; |
| | | } |
| | | |
| | | .mat-name { |
| | | font-size: 22rpx; |
| | | color: #909399; |
| | | margin-top: 4rpx; |
| | | display: block; |
| | | } |
| | | |
| | | .qty-badge { |
| | | padding: 4rpx 12rpx; |
| | | border-radius: 16rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .badge-active { |
| | | background: linear-gradient(135deg, #0081ff 0%, #1890ff 100%); |
| | | } |
| | | |
| | | .badge-done { |
| | | background: #e8f5e9; |
| | | } |
| | | |
| | | .qty-text { |
| | | font-size: 20rpx; |
| | | font-weight: 500; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .badge-done .qty-text { |
| | | color: #28a745; |
| | | } |
| | | |
| | | /* 卡片内容 */ |
| | | .card-body { |
| | | padding: 12rpx 16rpx; |
| | | } |
| | | |
| | | .info-grid { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .info-item { |
| | | width: 50%; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .info-label { |
| | | font-size: 20rpx; |
| | | color: #909399; |
| | | display: block; |
| | | } |
| | | |
| | | .info-value { |
| | | font-size: 24rpx; |
| | | color: #303133; |
| | | font-weight: 500; |
| | | display: block; |
| | | margin-top: 2rpx; |
| | | } |
| | | |
| | | .info-value.highlight { |
| | | color: #0081ff; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | /* 进度条 */ |
| | | .progress-wrap { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 8rpx; |
| | | } |
| | | |
| | | .progress-bar { |
| | | flex: 1; |
| | | height: 8rpx; |
| | | background: #e8e8e8; |
| | | border-radius: 4rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .progress-fill { |
| | | height: 100%; |
| | | background: linear-gradient(90deg, #0081ff 0%, #1890ff 100%); |
| | | border-radius: 4rpx; |
| | | transition: width 0.3s ease; |
| | | } |
| | | |
| | | .progress-text { |
| | | font-size: 20rpx; |
| | | color: #909399; |
| | | margin-left: 12rpx; |
| | | min-width: 50rpx; |
| | | text-align: right; |
| | | } |
| | | |
| | | /* 卡片底部 */ |
| | | .card-footer { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | padding: 12rpx 16rpx; |
| | | border-top: 1rpx solid #f0f0f0; |
| | | background: #fafafa; |
| | | } |
| | | |
| | | .card-footer-done { |
| | | background: #f0fff4; |
| | | } |
| | | |
| | | .action-text { |
| | | font-size: 24rpx; |
| | | color: #0081ff; |
| | | margin-right: 6rpx; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .done-text { |
| | | font-size: 24rpx; |
| | | color: #28a745; |
| | | margin-right: 6rpx; |
| | | .text-green { |
| | | color: #39b54a !important; |
| | | } |
| | | |
| | | /* 空状态 */ |