#
zhou zhou
14 小时以前 cbc99e27f63ad2da0369187a8b6f58ad37dd2be3
#
2个文件已修改
598 ■■■■■ 已修改文件
pages/outbound/orderOut/orderDetlList.vue 303 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/outbound/orderOut/outLocView.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/outbound/orderOut/orderDetlList.vue
@@ -15,64 +15,55 @@
        </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>
        
        <!-- 空状态 -->
@@ -119,8 +110,8 @@
                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;
                    });
                }
@@ -156,12 +147,14 @@
            }
        },
        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()) {
@@ -176,7 +169,13 @@
                    }, '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(() => {
@@ -206,7 +205,13 @@
                    }, '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 || [];
                    }
@@ -285,167 +290,31 @@
        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;
    }
    
    /* 空状态 */
pages/outbound/orderOut/outLocView.vue
@@ -14,50 +14,90 @@
                <view class="header-row">
                    <text class="header-label">总出库数量</text>
                    <text class="header-value highlight-white">{{orderItem.anfme || 0}}</text>
                </view>
                <view class="header-row">
                    <text class="header-label">已完成数量</text>
                    <text class="header-value highlight-white">{{orderItem.qty || 0}}</text>
                </view>
                </view>
            </view>
        </view>
        
        <!-- 库位视图列表 -->
        <view class="loc-list">
            <view class="loc-card" v-for="(item, index) in locList" :key="index">
                <!-- 卡片头部 -->
                <view class="card-header">
                    <view class="loc-info">
                        <text class="loc-code">{{item.locNo || '-'}}</text>
                        <text class="loc-name">{{item.locName || '库位'}}</text>
        <view class="padding-lr margin-top-sm">
            <block v-for="(item, index) in locList" :key="index">
                <view class="cu-list menu sm-border margin-bottom-sm">
                    <view class="cu-bar bg-white solid-bottom">
                        <view class="action">
                            <view class="index">{{index+1}}</view>
                            <view class="text-blue">
                                库位: {{item.locCode || '-'}}
                            </view>
                        </view>
                        <view class="action">
                            <text class="text-black">库存:</text>
                            <text class="text-blue margin-left-xs">{{item.anfme || 0}}</text>
                        </view>
                    </view>
                    <view class="qty-badge">
                        <text class="qty-text">{{item.anfme || 0}}</text>
                    <view class="cu-item">
                        <view class="content">
                            <text class="text-black">计划跟踪号:</text>
                            <text class="text-grey margin-left-xs">{{item.platWorkCode || '-'}}</text>
                        </view>
                    </view>
                    <view class="cu-item">
                        <view class="content">
                            <text class="text-black">批次:</text>
                            <text class="text-grey margin-left-xs">{{item.batch || '-'}}</text>
                        </view>
                    </view>
                    <view class="cu-item">
                        <view class="content">
                            <text class="text-black">托盘:</text>
                            <text class="text-grey margin-left-xs">{{item.barcode || '-'}}</text>
                        </view>
                    </view>
                    <view class="cu-item">
                        <view class="content">
                            <text class="text-black">区域:</text>
                            <text class="text-grey margin-left-xs">{{item.wareArea || '-'}}</text>
                        </view>
                    </view>
                    <view class="cu-item" v-if="item.anfme">
                        <view class="content">
                            <text class="text-blue">出库数量:</text>
                        </view>
                        <view class="action">
                            <uni-number-box
                                :min="0"
                                :max="item.anfme"
                                :decimal="2"
                                :step="0.01"
                                v-model="item.outQty"
                            ></uni-number-box>
                        </view>
                    </view>
                    <view class="cu-item" v-if="item.anfme">
                        <view class="content">
                            <text class="text-blue">出库站:</text>
                        </view>
                        <view class="action">
                            <input placeholder="请输入出库站点" v-model="item.outStaInput" @input="checkAgvStation(item)"></input>
                        </view>
                    </view>
                    <view class="cu-item" v-if="item.anfme">
                        <view class="content">
                            <button
                                style="width: 100%;"
                                class="cu-btn bg-orange shadow-blur"
                                :disabled="repeatClick"
                                @click="confirmOut(item)"
                            >
                                确定出库
                            </button>
                        </view>
                    </view>
                </view>
                <!-- 卡片内容 -->
                <view class="card-body">
                    <view class="info-grid">
                        <view class="info-item">
                            <text class="info-label">批次</text>
                            <text class="info-value">{{item.batch || '-'}}</text>
                        </view>
                        <view class="info-item">
                            <text class="info-label">库存数量</text>
                            <text class="info-value highlight">{{item.qty || 0}}</text>
                        </view>
                        <view class="info-item">
                            <text class="info-label">托盘号</text>
                            <text class="info-value">{{item.zpallet || '-'}}</text>
                        </view>
                        <view class="info-item">
                            <text class="info-label">货架</text>
                            <text class="info-value">{{item.shelfNo || '-'}}</text>
                        </view>
                    </view>
                </view>
            </view>
            </block>
        </view>
        
        <!-- 空状态 -->
@@ -89,12 +129,13 @@
                orderItem: null,
                locList: [],
                loading: false,
                repeatClick:false
            }
        },
        computed: {
            // 计算总库存数量
            totalQty() {
                return this.locList.reduce((sum, item) => sum + (item.qty || 0), 0);
                return this.locList.reduce((sum, item) => sum + (item.anfme || 0), 0);
            }
        },
        onLoad() {
@@ -108,6 +149,82 @@
            }
        },
        methods: {
            async checkAgvStation(item) {
                const that = this
                if (item.outStaInput === '' || item.outStaInput === null) {
                    uni.showToast({
                        title: '容器码为空',
                        icon: 'none',
                        position: 'top'
                    })
                    return
                }
                const { code, data, msg } = await request('/check/agvStation', {
                    transferStationNo: item.outStaInput
                })
                if (code === 200) {
                    item.agvStationName = data.stationName
                } else {
                    uni.showToast({
                        title: msg,
                        icon: 'none',
                        position: 'top'
                    })
                    setTimeout(function () {
                        item.agvStationName = ''
                        item.outStaInput = ''
                    }, 200)
                }
            },
            confirmOut(item){
                if (item.agvStationName === '' || item.agvStationName === null || item.agvStationName === undefined) {
                    uni.showToast({
                        title: '出库站为空',
                        icon: 'none',
                        position: 'top'
                    })
                    return
                }
                if (item.outQty === 0 || item.outQty === null) {
                    uni.showToast({
                        title: '出库数量不能为0',
                        icon: 'none',
                        position: 'top'
                    })
                    return
                }
                this.submitConfirm(item)
            },
            async submitConfirm(item){
                this.repeatClick = true
                try {
                    const requestData = {
                        itemId: item.id,
                        outQty: item.outQty,
                        outSta: item.agvStationName
                    }
                    const { code, data, msg } = await request(
                        '/orderOut/getOutLocRun',
                        requestData
                    )
                    if (code === 200) {
                        uni.showToast({
                            title: '出库成功'
                        })
                        this.isconfirm = false
                        this.getOutLocView(this.orderItem);
                    } else {
                        uni.showToast({
                            title: msg,
                            icon: 'none',
                            position: 'top'
                        })
                    }
                } finally {
                    // 无论请求成功还是失败,都释放按钮锁定
                    this.repeatClick = false
                }
            },
            // 获取出库库位视图
            async getOutLocView(item) {
                if (!item) return;
@@ -180,95 +297,27 @@
        font-weight: 600;
    }
    
    /* 库位列表 */
    .loc-list {
        padding: 0 20rpx;
    }
    .loc-card {
        background: #ffffff;
        border-radius: 12rpx;
        margin-top: 12rpx;
        box-shadow: 0 2rpx 12rpx rgba(0, 129, 255, 0.08);
        overflow: hidden;
        border: 1rpx solid #e4e7ed;
    }
    /* 卡片头部 */
    .card-header {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        padding: 14rpx 16rpx;
        border-bottom: 1rpx solid #f0f0f0;
    }
    .loc-info {
        flex: 1;
        padding-right: 12rpx;
    }
    .loc-code {
        font-size: 26rpx;
        color: #303133;
        font-weight: 600;
    .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;
    }
    .loc-name {
        font-size: 22rpx;
        color: #909399;
        margin-top: 4rpx;
        display: block;
    .act .index {
        background: #0081ff;
    }
    .qty-badge {
        padding: 4rpx 12rpx;
        border-radius: 16rpx;
        flex-shrink: 0;
        background: linear-gradient(135deg, #0081ff 0%, #1890ff 100%);
    .act {
        box-shadow: 0 0 10upx rgba(0, 129, 255, 0.6);
    }
    .qty-text {
        font-size: 20rpx;
        font-weight: 500;
        color: #ffffff;
    }
    /* 卡片内容 */
    .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;
    }
    /* 空状态 */
    .empty-state {
        display: flex;