<template>
|
<view class="page-container">
|
<!-- 头部导航 -->
|
<u-navbar
|
:title="$t('container.orderCombDetl') || '订单明细'"
|
:fixed="true"
|
:placeholder="true"
|
bgColor="#ffffff"
|
titleStyle="font-weight: 600; color: #303133; font-size: 32rpx;"
|
autoBack
|
>
|
<template slot="right">
|
<view
|
class="navbar-right"
|
@click="toggleMultiSelect"
|
style="padding: 10rpx"
|
>
|
<text
|
:style="{
|
color: isMultiSelect ? '#409eff' : '#303133',
|
fontSize: '28rpx'
|
}"
|
>
|
{{
|
isMultiSelect
|
? $t('common.cancel') || '取消'
|
: $t('common.multiSelect') || '多选'
|
}}
|
</text>
|
</view>
|
</template>
|
</u-navbar>
|
|
<!-- 订单信息头部 -->
|
<view
|
class="order-header"
|
v-if="order"
|
>
|
<view class="header-content">
|
<view class="header-row">
|
<text class="header-label">
|
{{ $t('container.orderNo') || '单据号' }}
|
</text>
|
<text class="header-value">{{ order.orderNo }}</text>
|
</view>
|
<view class="header-row">
|
<text class="header-label">
|
{{ $t('container.orderType') || '单据类型' }}
|
</text>
|
<text class="header-value">
|
{{ order.docType$ || '-' }}
|
</text>
|
</view>
|
</view>
|
</view>
|
|
<!-- 搜索框 -->
|
<!-- <view class="search-bar">
|
<u-search
|
v-model="condition"
|
:placeholder="$t('common.scanInputMat') || '扫码 / 输入物料'"
|
@search="search"
|
@custom="search"
|
@clear="onCancelSearch"
|
:showAction="true"
|
:actionText="$t('common.search') || '搜索'"
|
bgColor="#F5F5F5"
|
shape="round"
|
></u-search>
|
</view> -->
|
|
<!-- 明细列表 -->
|
<view class="detl-list">
|
<view
|
class="detl-card"
|
:class="{ 'card-selected': selectedItems.includes(item) }"
|
v-for="(item, index) in filterList"
|
:key="index"
|
@click="handleItemClick(item)"
|
>
|
<view
|
class="check-box"
|
v-if="isMultiSelect && item.enableQty > 0"
|
>
|
<uni-icons
|
:type="
|
selectedItems.includes(item)
|
? 'checkbox-filled'
|
: 'circle'
|
"
|
size="24"
|
:color="
|
selectedItems.includes(item) ? '#409eff' : '#dcdfe6'
|
"
|
></uni-icons>
|
</view>
|
<view class="card-main">
|
<!-- 卡片头部 -->
|
<view class="card-header">
|
<view class="mat-info">
|
<text class="mat-code">{{ item.matnr }}</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">
|
{{ $t('container.remain') || '剩余' }}
|
{{ item.enableQty }}
|
</text>
|
</view>
|
</view>
|
|
<!-- 卡片内容 -->
|
<view class="card-body">
|
<view class="info-grid">
|
<view class="info-item">
|
<text class="info-label">
|
{{ $t('container.specs') || '规格' }}
|
</text>
|
<text class="info-value">
|
{{ item.specs || '-' }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">
|
{{ $t('container.batch') || '批次' }}
|
</text>
|
<text class="info-value">
|
{{ item.batch || '-' }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">
|
{{ $t('container.orderQty') || '订单数量' }}
|
</text>
|
<text class="info-value highlight">
|
{{ item.anfme }}
|
</text>
|
</view>
|
<view class="info-item">
|
<text class="info-label">
|
{{
|
$t('container.completedQty') || '已完成'
|
}}
|
</text>
|
<text class="info-value">
|
{{ item.anfme - item.enableQty }}
|
</text>
|
</view>
|
</view>
|
|
<!-- 进度条 -->
|
<view class="progress-wrap">
|
<view class="progress-bar">
|
<view
|
class="progress-fill"
|
:style="{ width: getProgress(item) + '%' }"
|
></view>
|
</view>
|
<text class="progress-text">
|
{{ getProgress(item) }}%
|
</text>
|
</view>
|
</view>
|
|
<!-- 卡片底部 -->
|
<view
|
class="card-footer"
|
v-if="item.enableQty > 0"
|
>
|
<text class="action-text">
|
{{ $t('container.clickToComb') || '点击组托入库' }}
|
</text>
|
<uni-icons
|
type="right"
|
size="14"
|
color="#667eea"
|
></uni-icons>
|
</view>
|
<view
|
class="card-footer card-footer-done"
|
v-else
|
>
|
<text class="done-text">
|
{{ $t('container.completed') || '已完成' }}
|
</text>
|
<uni-icons
|
type="checkmarkempty"
|
size="14"
|
color="#28a745"
|
></uni-icons>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 空状态 -->
|
<view
|
class="empty-state"
|
v-if="filterList.length === 0 && !loading"
|
>
|
<u-empty
|
mode="list"
|
:text="$t('container.emptyDetl') || '暂无明细数据'"
|
marginTop="40"
|
></u-empty>
|
</view>
|
|
<!-- 统计信息 -->
|
<view
|
class="stats-bar"
|
v-if="menuList.length > 0 && !isMultiSelect"
|
>
|
<view class="stats-item">
|
<text class="stats-value">{{ menuList.length }}</text>
|
<text class="stats-label">
|
{{ $t('container.totalDetl') || '总明细' }}
|
</text>
|
</view>
|
<view class="stats-divider"></view>
|
<view class="stats-item">
|
<text class="stats-value">{{ pendingCount }}</text>
|
<text class="stats-label">
|
{{ $t('container.pending') || '待处理' }}
|
</text>
|
</view>
|
<view class="stats-divider"></view>
|
<view class="stats-item">
|
<text class="stats-value">{{ completedCount }}</text>
|
<text class="stats-label">
|
{{ $t('container.completed') || '已完成' }}
|
</text>
|
</view>
|
</view>
|
|
<!-- 多选操作底部 -->
|
<view
|
class="multi-action-bar"
|
v-if="isMultiSelect"
|
>
|
<view
|
class="select-all"
|
@click="toggleSelectAll"
|
>
|
<uni-icons
|
:type="isAllSelected ? 'checkbox-filled' : 'circle'"
|
size="24"
|
:color="isAllSelected ? '#409eff' : '#909399'"
|
></uni-icons>
|
<text class="select-all-text">
|
{{ $t('common.selectAll') || '全选' }}
|
</text>
|
</view>
|
<view class="selected-count">
|
<text>{{ $t('common.selected') || '已选' }}</text>
|
<text class="count-num">{{ selectedItems.length }}</text>
|
</view>
|
<u-button
|
type="primary"
|
:disabled="selectedItems.length === 0"
|
:text="$t('container.clickToComb') || '点击组托入库'"
|
@click="submitMultiSelected"
|
customStyle="width: 240rpx; margin: 0; height: 72rpx;"
|
></u-button>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { fetchOrderDetlList, searchOrderDetl } from './api.js'
|
|
export default {
|
data() {
|
return {
|
data: '',
|
condition: '',
|
menuList: [],
|
order: '',
|
loading: false,
|
isMultiSelect: false,
|
selectedItems: []
|
}
|
},
|
computed: {
|
// 过滤后的列表(优先显示有剩余数量的)
|
filterList() {
|
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
|
return 0
|
})
|
}
|
const keyword = this.condition.toLowerCase()
|
return this.menuList.filter((item) => {
|
return (
|
(item.matnr &&
|
item.matnr.toLowerCase().includes(keyword)) ||
|
(item.maktx &&
|
item.maktx.toLowerCase().includes(keyword)) ||
|
(item.batch && item.batch.toLowerCase().includes(keyword))
|
)
|
})
|
},
|
// 待处理数量
|
pendingCount() {
|
return this.menuList.filter((item) => item.enableQty > 0).length
|
},
|
// 已完成数量
|
completedCount() {
|
return this.menuList.filter((item) => item.enableQty <= 0).length
|
},
|
// 是否全选了可选的明细
|
isAllSelected() {
|
const availableItems = this.filterList.filter(
|
(item) => item.enableQty > 0
|
)
|
if (availableItems.length === 0) return false
|
return availableItems.length === this.selectedItems.length
|
}
|
},
|
onLoad() {
|
let that = this
|
const eventChannel = this.getOpenerEventChannel()
|
if (eventChannel) {
|
eventChannel.on('data', function (data) {
|
that.order = data.data
|
that.getOrderNoList(that.order)
|
})
|
}
|
},
|
onShow() {
|
if (this.order) {
|
this.getOrderNoList(this.order)
|
}
|
// 获取开多选设置
|
let settings = uni.getStorageSync('appSettings')
|
if (settings && settings.orderDetlMultiSelect) {
|
this.isMultiSelect = true
|
} else {
|
this.isMultiSelect = false
|
}
|
|
// 重置多选状态
|
this.selectedItems = []
|
},
|
methods: {
|
// 计算进度
|
getProgress(item) {
|
if (!item.anfme || item.anfme === 0) return 0
|
const progress = (
|
((item.anfme - item.enableQty) / item.anfme) *
|
100
|
).toFixed(0)
|
return Math.min(100, Math.max(0, progress))
|
},
|
// 搜索
|
async search() {
|
if (!this.condition.trim()) {
|
this.getOrderNoList(this.order)
|
return
|
}
|
let that = this
|
that.loading = true
|
try {
|
const { code, data, msg } = await searchOrderDetl({
|
condition: this.condition,
|
order: this.order.orderNo
|
})
|
if (code === 200) {
|
that.menuList = data || []
|
} else if (code === 403) {
|
uni.showToast({ title: msg, icon: 'none', position: 'top' })
|
setTimeout(() => {
|
uni.reLaunch({ url: '/pages/login/login' })
|
}, 1000)
|
} else {
|
uni.showToast({ title: msg, icon: 'none', position: 'top' })
|
}
|
} catch (err) {
|
console.error(err)
|
uni.showToast({
|
title: this.$t('toast.searchFail') || '搜索请求失败',
|
icon: 'none',
|
position: 'top'
|
})
|
} finally {
|
that.loading = false
|
}
|
},
|
// 取消搜索
|
onCancelSearch() {
|
this.condition = ''
|
this.getOrderNoList(this.order)
|
},
|
// 获取订单明细列表
|
async getOrderNoList(order) {
|
if (!order || !order.orderNo) return
|
let that = this
|
that.loading = true
|
try {
|
const { code, data, msg } = await fetchOrderDetlList({
|
orderNo: order.orderNo
|
})
|
if (code === 200) {
|
that.menuList = data || []
|
} else if (code === 403) {
|
uni.showToast({ title: msg, icon: 'none', position: 'top' })
|
setTimeout(() => {
|
uni.reLaunch({ url: '/pages/login/login' })
|
}, 1000)
|
} else {
|
uni.showToast({
|
title:
|
msg ||
|
this.$t('toast.fetchDetailFail') ||
|
'获取明细失败',
|
icon: 'none',
|
position: 'top'
|
})
|
that.menuList = data || []
|
}
|
} catch (err) {
|
console.error(err)
|
uni.showToast({
|
title: this.$t('toast.fetchDetailFail') || '获取明细失败',
|
icon: 'none',
|
position: 'top'
|
})
|
} finally {
|
that.loading = false
|
}
|
},
|
// 切换多选模式
|
toggleMultiSelect() {
|
this.isMultiSelect = !this.isMultiSelect
|
if (!this.isMultiSelect) {
|
this.selectedItems = []
|
}
|
},
|
// 全选/取消全选
|
toggleSelectAll() {
|
const availableItems = this.filterList.filter(
|
(item) => item.enableQty > 0
|
)
|
if (this.isAllSelected) {
|
this.selectedItems = []
|
} else {
|
this.selectedItems = [...availableItems]
|
}
|
},
|
// 处理列表项点击
|
handleItemClick(item) {
|
if (this.isMultiSelect) {
|
if (item.enableQty <= 0) {
|
uni.showToast({
|
title:
|
this.$t('toast.detailCompleted') || '该明细已完成',
|
icon: 'none',
|
position: 'top'
|
})
|
return
|
}
|
const index = this.selectedItems.findIndex(
|
(selected) => selected === item
|
)
|
if (index > -1) {
|
this.selectedItems.splice(index, 1)
|
} else {
|
this.selectedItems.push(item)
|
}
|
} else {
|
this.chose(item)
|
}
|
},
|
// 选择明细进行组托(单选)
|
chose(item) {
|
if (item.enableQty <= 0) {
|
uni.showToast({
|
title: this.$t('toast.detailCompleted') || '该明细已完成',
|
icon: 'none',
|
position: 'top'
|
})
|
return
|
}
|
uni.navigateTo({
|
url: '/pages/InManagement/OrderContainerBinding/Main/Order_Container_Binding',
|
success: function (res) {
|
res.eventChannel.emit('orderItem', {
|
item: item
|
})
|
}
|
})
|
},
|
// 多选提交
|
submitMultiSelected() {
|
if (this.selectedItems.length === 0) return
|
let that = this
|
uni.navigateTo({
|
url: '/pages/InManagement/OrderContainerBinding/Main/Order_Container_Binding',
|
success: function (res) {
|
// 传递 items 数组,Order_Container_Binding 能够接收
|
res.eventChannel.emit('orderItem', {
|
items: that.selectedItems
|
})
|
that.isMultiSelect = false
|
that.selectedItems = []
|
}
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
/* 引入公共样式 */
|
@import url('@/static/css/common.css');
|
|
.page-container {
|
min-height: 100vh;
|
background-color: #f0f2f5;
|
padding-bottom: 120rpx;
|
}
|
|
/* 订单头部 */
|
.order-header {
|
background-color: #ffffff;
|
padding: 24rpx 28rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
margin-bottom: 16rpx;
|
}
|
|
.header-content {
|
background: #f8f9fa;
|
border-radius: 12rpx;
|
padding: 16rpx 20rpx;
|
border: 1px solid #ebeef5;
|
}
|
|
.header-row {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 6rpx 0;
|
}
|
|
.header-label {
|
font-size: 26rpx;
|
color: #909399;
|
}
|
|
.header-value {
|
font-size: 28rpx;
|
color: #303133;
|
font-weight: 600;
|
}
|
|
/* 搜索栏 */
|
.search-bar {
|
padding: 20rpx 24rpx;
|
background: #ffffff;
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
position: sticky;
|
top: 0;
|
z-index: 100;
|
}
|
|
/* 明细列表 */
|
.detl-list {
|
padding: 0 20rpx;
|
}
|
|
.detl-card {
|
background: #ffffff;
|
border-radius: 16rpx;
|
margin-top: 24rpx;
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
overflow: hidden;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
border: 2rpx solid transparent;
|
display: flex;
|
align-items: center;
|
}
|
|
.detl-card.card-selected {
|
border-color: #409eff;
|
background-color: #f0f7ff;
|
}
|
|
.detl-card.card-selected .card-header {
|
background-color: transparent;
|
}
|
|
.check-box {
|
padding: 0 20rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.card-main {
|
flex: 1;
|
min-width: 0;
|
}
|
|
.detl-card:active {
|
transform: scale(0.98);
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.12);
|
}
|
|
/* 卡片头部 */
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: flex-start;
|
padding: 24rpx 28rpx;
|
background-color: transparent;
|
border-bottom: 1px solid #ebeef5;
|
}
|
|
.mat-info {
|
flex: 1;
|
padding-right: 12rpx;
|
}
|
|
.mat-code {
|
font-size: 28rpx;
|
color: #303133;
|
font-weight: 600;
|
display: block;
|
}
|
|
.mat-name {
|
font-size: 24rpx;
|
color: #909399;
|
margin-top: 6rpx;
|
display: block;
|
}
|
|
.qty-badge {
|
padding: 6rpx 16rpx;
|
border-radius: 20rpx;
|
flex-shrink: 0;
|
}
|
|
.badge-active {
|
background: #409eff;
|
}
|
|
.badge-done {
|
background: #e8f5e9;
|
}
|
|
.qty-text {
|
font-size: 22rpx;
|
font-weight: 500;
|
color: #ffffff;
|
}
|
|
.badge-done .qty-text {
|
color: #28a745;
|
}
|
|
/* 卡片内容 */
|
.card-body {
|
padding: 20rpx 28rpx;
|
}
|
|
.info-grid {
|
display: flex;
|
flex-wrap: wrap;
|
}
|
|
.info-item {
|
width: 50%;
|
margin-bottom: 12rpx;
|
}
|
|
.info-label {
|
font-size: 24rpx;
|
color: #909399;
|
display: block;
|
}
|
|
.info-value {
|
font-size: 26rpx;
|
color: #303133;
|
font-weight: 500;
|
display: block;
|
margin-top: 4rpx;
|
}
|
|
.info-value.highlight {
|
color: #667eea;
|
font-weight: 600;
|
}
|
|
/* 进度条 */
|
.progress-wrap {
|
display: flex;
|
align-items: center;
|
margin-top: 16rpx;
|
}
|
|
.progress-bar {
|
flex: 1;
|
height: 10rpx;
|
background: #e8e8e8;
|
border-radius: 6rpx;
|
overflow: hidden;
|
}
|
|
.progress-fill {
|
height: 100%;
|
background: #409eff;
|
border-radius: 6rpx;
|
transition: width 0.3s ease;
|
}
|
|
.progress-text {
|
font-size: 22rpx;
|
color: #909399;
|
margin-left: 16rpx;
|
min-width: 50rpx;
|
text-align: right;
|
}
|
|
/* 卡片底部 */
|
.card-footer {
|
display: flex;
|
align-items: center;
|
justify-content: flex-end;
|
padding: 20rpx 28rpx;
|
border-top: 1rpx dashed #ebeef5;
|
}
|
|
.card-footer-done {
|
background: #f0fff4;
|
}
|
|
.action-text {
|
font-size: 26rpx;
|
color: #409eff;
|
margin-right: 8rpx;
|
font-weight: 500;
|
}
|
|
.done-text {
|
font-size: 26rpx;
|
color: #28a745;
|
margin-right: 8rpx;
|
}
|
|
/* 空状态 */
|
.empty-state {
|
padding: 60rpx 0;
|
}
|
|
/* 统计栏 */
|
.stats-bar {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
display: flex;
|
align-items: center;
|
justify-content: space-around;
|
background: #ffffff;
|
padding: 24rpx 0;
|
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
}
|
|
.stats-item {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
flex: 1;
|
}
|
|
.stats-value {
|
font-size: 34rpx;
|
color: #303133;
|
font-weight: 600;
|
}
|
|
.stats-label {
|
font-size: 22rpx;
|
color: #909399;
|
margin-top: 6rpx;
|
}
|
|
.stats-divider {
|
width: 2rpx;
|
height: 60rpx;
|
background: #ebeef5;
|
}
|
|
/* 多选操作底部 */
|
.multi-action-bar {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
background: #ffffff;
|
padding: 24rpx 30rpx;
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
z-index: 100;
|
}
|
|
.select-all {
|
display: flex;
|
align-items: center;
|
}
|
|
.select-all-text {
|
font-size: 28rpx;
|
color: #303133;
|
margin-left: 10rpx;
|
}
|
|
.selected-count {
|
flex: 1;
|
text-align: right;
|
margin-right: 30rpx;
|
font-size: 28rpx;
|
color: #606266;
|
}
|
|
.count-num {
|
color: #409eff;
|
font-weight: 600;
|
font-size: 32rpx;
|
}
|
</style>
|