chen.llin
2 天以前 76df26183884e9aef75b782509a1c60390c88785
增加清空缓存库位功能
1个文件已添加
2个文件已修改
782 ■■■■■ 已修改文件
pages.json 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.vue 166 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/stock/locCacheLock.vue 606 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json
@@ -53,14 +53,14 @@
        {
            "path": "pages/AGV/agv_start",
            "style": {
                "navigationBarTitleText": "AGV容器入库",
                "navigationBarTitleText": "AGV容器入库(实托)",
                "enablePullDownRefresh": false
            }
        },
        {
            "path": "pages/AGV/agv_back",
            "style": {
                "navigationBarTitleText": "AGV容器回库",
                "navigationBarTitleText": "AGV容器回库(拣料)",
                "enablePullDownRefresh": false
            }
        },
@@ -78,6 +78,12 @@
            }
        },
        {
            "path": "pages/stock/locCacheLock",
            "style": {
                "navigationBarTitleText": "缓存库位状态管理"
            }
        },
        {
            "path": "pages/rfid/settings",
            "style": {
                "navigationBarTitleText": "RFID设置"
pages/home/home.vue
@@ -55,7 +55,7 @@
                </view>
                
                <!-- 未分类菜单分隔区域 -->
                <view class="uncategorized-section" v-if="uncategorizedMenus.length > 0">
                <view class="uncategorized-section" v-if="uncategorizedMenus.length > 0 && uncategorizedMenus.filter(item => !excludeFromCategory.includes(item.name)).length > 0">
                    <view class="section-divider">
                        <view class="divider-line"></view>
                        <text class="divider-text">其他</text>
@@ -137,14 +137,14 @@
                        url: '/order/orderList'
                    },
                    {
                        title: 'AGV容器入库',
                        title: 'AGV容器入库(实托)',
                        name: 'agv_start',
                        color: 'blue',
                        cuIcon: '',
                        url: '/AGV/agv_start'
                    },
                    {
                        title: 'AGV容器回库',
                        title: 'AGV容器回库(拣料)',
                        name: 'agv_back',
                        color: 'orange',
                        cuIcon: '',
@@ -188,21 +188,28 @@
                ],
                colorList: ['cyan', 'purple', 'blue', 'pink', 'orange', 'green', 'mauve', 'brown', 'olive', 'red', 'yellow', 'grey'],
                // 图标映射
                iconMap: {
                    'pakin': 'upload',
                    'orderPakin': 'list',
                    'stockQuery': 'search',
                    'logOut': 'redo',
                    'orderPutOn': 'top',
                    'orderPutDown': 'bottom',
                    'restock': 'refresh',
                    'stockCheck': 'checkbox',
                    'agv_start': 'navigate',
                    'agv_back': 'refresh',
                    'agv_empty': 'upload',
                    'rfidSettings': 'scan',
                    'uhftest': 'scan',
                },
            iconMap: {
                'pakin': 'upload',
                '组托': 'upload',
                'orderPakin': 'list',
                '订单入库': 'list',
                'stockQuery': 'search',
                '库存查询': 'search',
                'logOut': 'redo',
                'orderPutOn': 'top',
                'orderPutDown': 'bottom',
                'restock': 'refresh',
                'stockCheck': 'checkbox',
                'agv_start': 'navigate',
                'AGV容器入库(实托)': 'navigate',
                'agv_back': 'refresh',
                'AGV容器回库(拣料)': 'refresh',
                '缓存库位状态管理': 'settings',
                'agv_empty': 'upload',
                'AGV空托入库': 'upload',
                'rfidSettings': 'scan',
                'uhftest': 'scan',
            },
                // 菜单分类配置(仅分类模式使用)
                // key: 分类唯一标识
                // name: 分类显示名称
@@ -215,21 +222,24 @@
                        name: '入库管理',
                        color: 'cyan',
                        icon: 'upload',
                        menuNames: ['pakin', 'orderPakin']
                        menuNames: ['pakin', 'orderPakin', '组托', '订单入库'], // 兼容中英文名称
                        parentName: '入库管理' // 父菜单名称,用于层级结构匹配
                    },
                    {
                        key: 'agv_category',
                        name: 'AGV管理',
                        color: 'blue',
                        icon: 'navigate',
                        menuNames: ['agv_start', 'agv_back', 'agv_empty']
                        menuNames: ['agv_start', 'agv_back', 'agv_empty', 'AGV容器入库(实托)', 'AGV容器回库(拣料)', 'AGV空托入库'], // 兼容中英文名称
                        parentName: 'AGV管理' // 父菜单名称,用于层级结构匹配
                    },
                    {
                        key: 'stock_category',
                        name: '库存管理',
                        color: 'green',
                        icon: 'search',
                        menuNames: ['stockQuery']
                        menuNames: ['stockQuery', '库存查询', '缓存库位状态管理'], // 兼容中英文名称
                        parentName: '库存管理' // 父菜单名称,用于层级结构匹配
                    },
                    {
                        key: 'device_category',
@@ -241,28 +251,48 @@
                ],
                // 不参与分类的菜单项(如退出登录,始终单独显示)
                excludeFromCategory: ['logOut'],
                // 当前展开的分类列表
                // 当前展开的分类列表(默认折叠所有分类)
                expandedCategories: []
            };
        },
        computed: {
            // 分类后的菜单数据(过滤掉空分类)
            categorizedMenus() {
                return this.categoryConfig.map(category => {
                    const items = this.elements.filter(item =>
                        category.menuNames.includes(item.name)
                    );
                const result = this.categoryConfig.map(category => {
                    const items = this.elements.filter(item => {
                        // 优先根据parentName匹配(适用于层级结构)
                        if (category.parentName && item.parentName === category.parentName) {
                            return true;
                        }
                        // 其次根据menuNames匹配(兼容旧数据)
                        if (category.menuNames && category.menuNames.includes(item.name)) {
                            return true;
                        }
                        return false;
                    });
                    return {
                        ...category,
                        items: items
                    };
                }).filter(category => category.items.length > 0);
                }).filter(category => category.items && category.items.length > 0);
                return result;
            },
            // 未分类的菜单(不在任何分类中或在排除列表中)
            uncategorizedMenus() {
                const allCategorizedNames = this.categoryConfig.flatMap(c => c.menuNames);
                // 获取所有已分类的菜单名称(包括通过parentName匹配的)
                const allCategorizedItems = new Set();
                this.categoryConfig.forEach(category => {
                    this.elements.forEach(item => {
                        if (category.parentName && item.parentName === category.parentName) {
                            allCategorizedItems.add(item.name);
                        } else if (category.menuNames && category.menuNames.includes(item.name)) {
                            allCategorizedItems.add(item.name);
                        }
                    });
                });
                return this.elements.filter(item => 
                    !allCategorizedNames.includes(item.name) || this.excludeFromCategory.includes(item.name)
                    !allCategorizedItems.has(item.name) || this.excludeFromCategory.includes(item.name)
                );
            }
        },
@@ -308,19 +338,75 @@
                                that.elements = that.elements2;
                                return;
                            }
                            for (var i = 0; i < res.data.length; i++) {
                                if (res.data.length < 0) {
                                    break;
                            // 检查返回的数据是否是层级结构(包含type字段和children字段)
                            var isHierarchical = res.data.length > 0 && res.data[0].type !== undefined;
                            if (isHierarchical) {
                                // 层级结构:父菜单包含子菜单
                                var colorIndex = 0;
                                for (var i = 0; i < res.data.length; i++) {
                                    var item = res.data[i];
                                    if (item.type === 'parent' && item.children && item.children.length > 0) {
                                        // 父菜单:不直接添加到elements,而是将子菜单添加到elements,并保存父菜单信息
                                        for (var j = 0; j < item.children.length; j++) {
                                            var child = item.children[j];
                                            that.getIcon(child.name);
                                            // 优先从elements2中查找同名菜单的颜色(匹配name或title),如果没有则使用默认颜色
                                            var defaultMenu = that.elements2.find(function(e) {
                                                return e.name === child.name || e.title === child.name;
                                            });
                                            var childColor = defaultMenu ? defaultMenu.color : (that.colorList[colorIndex % that.colorList.length]);
                                            that.elements.push({
                                                title: child.name,
                                                name: child.name,
                                                color: childColor,
                                                cuIcon: that.icon,
                                                url: child.action,
                                                parentName: item.name // 保存父菜单名称,用于分类匹配
                                            });
                                        }
                                        colorIndex++; // 每个父菜单使用不同的颜色
                                    } else if (item.type === 'standalone') {
                                        // 独立菜单(没有父菜单的权限)
                                        that.getIcon(item.name);
                                        // 优先从elements2中查找同名菜单的颜色(匹配name或title),如果没有则使用默认颜色
                                        var defaultMenu = that.elements2.find(function(e) {
                                            return e.name === item.name || e.title === item.name;
                                        });
                                        var standaloneColor = defaultMenu ? defaultMenu.color : (that.colorList[colorIndex % that.colorList.length]);
                                        that.elements.push({
                                            title: item.name,
                                            name: item.name,
                                            color: standaloneColor,
                                            cuIcon: that.icon,
                                            url: item.action
                                        });
                                        colorIndex++;
                                    }
                                }
                                that.getIcon(res.data[i].title);
                                that.elements.unshift({
                                    title: res.data[i].name,
                                    name: res.data[i].title,
                                    color: that.colorList[i % that.colorList.length],
                                    cuIcon: that.icon,
                                    url: res.data[i].action
                                });
                            } else {
                                // 平铺结构(兼容旧逻辑)
                                for (var i = 0; i < res.data.length; i++) {
                                    if (res.data.length < 0) {
                                        break;
                                    }
                                    that.getIcon(res.data[i].name);
                                    // 优先从elements2中查找同名菜单的颜色(匹配name或title),如果没有则使用默认颜色
                                    var defaultMenu = that.elements2.find(function(e) {
                                        return e.name === res.data[i].name || e.title === res.data[i].name;
                                    });
                                    var flatColor = defaultMenu ? defaultMenu.color : (that.colorList[i % that.colorList.length]);
                                    that.elements.unshift({
                                        title: res.data[i].name,  // 权限名称作为显示标题
                                        name: res.data[i].name,    // 权限名称作为内部标识
                                        color: flatColor,
                                        cuIcon: that.icon,
                                        url: res.data[i].action    // 接口地址作为页面路径
                                    });
                                }
                            }
                            that.elements.push({
                                title: '退出登录',
                                name: 'logOut',
pages/stock/locCacheLock.vue
New file
@@ -0,0 +1,606 @@
<template>
    <view class="page-container">
        <!-- 表单区域 -->
        <view class="form-section">
            <view class="form-item">
                <view class="form-label">
                    <uni-icons type="scan" size="18" color="#667eea"></uni-icons>
                    <text class="label-text">缓存库位号</text>
                </view>
                <view class="form-input-wrap">
                    <input class="form-input" type="text" placeholder="扫码 / 输入缓存库位号" v-model="locNo"
                        :focus="locNoFocus" @input="locNoInput()" @focus="onLocNoFocus()" @blur="onLocNoBlur()" />
                    <uni-icons v-if="locNo" type="clear" size="18" color="#c0c4cc" @click="clearLocNo"></uni-icons>
                </view>
            </view>
        </view>
        <!-- 库位信息展示 -->
        <view class="info-section" v-if="locCacheInfo">
            <view class="info-card">
                <view class="info-header">
                    <text class="info-title">库位信息</text>
                </view>
                <view class="info-body">
                    <view class="info-row">
                        <view class="info-col">
                            <text class="info-label">库位号</text>
                            <text class="info-value">{{locCacheInfo.locNo || '-'}}</text>
                        </view>
                    </view>
                    <view class="info-row">
                        <view class="info-col half">
                            <text class="info-label">排</text>
                            <text class="info-value">{{locCacheInfo.row1 || '-'}}</text>
                        </view>
                        <view class="info-col half">
                            <text class="info-label">列</text>
                            <text class="info-value">{{locCacheInfo.bay1 || '-'}}</text>
                        </view>
                    </view>
                    <view class="info-row">
                        <view class="info-col half">
                            <text class="info-label">层</text>
                            <text class="info-value">{{locCacheInfo.lev1 || '-'}}</text>
                        </view>
                        <view class="info-col half">
                            <text class="info-label">库位状态</text>
                            <text class="info-value" :class="{'locked': locCacheInfo.locSts === 'F', 'unlocked': locCacheInfo.locSts === 'O'}">
                                {{getLocStsDesc(locCacheInfo.locSts)}}
                            </text>
                        </view>
                    </view>
                </view>
            </view>
        </view>
        <!-- 底部操作按钮 -->
        <view class="bottom-bar">
            <view class="btn-reset" @click="reset()">
                <uni-icons type="refresh" size="18" color="#909399"></uni-icons>
                <text class="btn-text">重置</text>
            </view>
            <view class="btn-group">
                <view class="btn-unlock" :class="{'btn-disabled': !locCacheInfo || isSubmitting}" @click="unlockLoc()">
                    <uni-icons type="unlocked" size="18" color="#ffffff"></uni-icons>
                    <text class="btn-text">确认已取走当前库位</text>
                </view>
                <view class="btn-lock" :class="{'btn-disabled': !locCacheInfo || isSubmitting}" @click="lockLoc()">
                    <uni-icons type="locked" size="18" color="#ffffff"></uni-icons>
                    <text class="btn-text">标记为在库</text>
                </view>
            </view>
        </view>
        <!-- 列操作按钮 -->
        <view class="row-bar" v-if="locCacheInfo">
            <view class="btn-group-row">
                <view class="btn-unlock-row" :class="{'btn-disabled': isSubmitting}" @click="unlockBay()">
                    <uni-icons type="unlocked" size="18" color="#ffffff"></uni-icons>
                    <text class="btn-text">确认已取走当前列</text>
                </view>
                <view class="btn-lock-row" :class="{'btn-disabled': isSubmitting}" @click="lockBay()">
                    <uni-icons type="locked" size="18" color="#ffffff"></uni-icons>
                    <text class="btn-text">标记当前列在库</text>
                </view>
            </view>
        </view>
        <!-- 排操作按钮 -->
        <view class="row-bar" v-if="locCacheInfo" style="margin-top: 10px;">
            <view class="btn-group-row">
                <view class="btn-unlock-row" :class="{'btn-disabled': isSubmitting}" @click="clearAllColumnsInRow()">
                    <uni-icons type="trash" size="18" color="#ffffff"></uni-icons>
                    <text class="btn-text">确认已取走当前排</text>
                </view>
            </view>
        </view>
        <!-- 提示信息弹窗 -->
        <uni-popup ref="message" type="message">
            <uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
        </uni-popup>
        <!-- 确认弹窗 -->
        <uni-popup ref="confirmDialog" type="dialog">
            <uni-popup-dialog :type="msgType" cancelText="取消" confirmText="确认" :title="title" :content="content"
                @confirm="confirmAction" @close="closeConfirm"></uni-popup-dialog>
        </uni-popup>
        <!-- 选择满托/空托弹窗 -->
        <uni-popup ref="fullPltDialog" type="dialog">
            <view class="popup-card">
                <view class="popup-header">
                    <text class="popup-title">选择托盘类型</text>
                </view>
                <view class="popup-body">
                    <view class="popup-row">
                        <text class="popup-label">请选择托盘类型</text>
                    </view>
                    <view class="plt-options">
                        <view class="plt-option" :class="{'selected': selectedFullPlt === true}" @click="selectFullPlt(true)">
                            <uni-icons type="checkbox-filled" size="20" :color="selectedFullPlt === true ? '#667eea' : '#c0c4cc'"></uni-icons>
                            <text class="plt-text">满托</text>
                        </view>
                        <view class="plt-option" :class="{'selected': selectedFullPlt === false}" @click="selectFullPlt(false)">
                            <uni-icons type="checkbox-filled" size="20" :color="selectedFullPlt === false ? '#667eea' : '#c0c4cc'"></uni-icons>
                            <text class="plt-text">空托</text>
                        </view>
                    </view>
                </view>
                <view class="popup-footer">
                    <view class="popup-btn cancel" @click="closeFullPltDialog">取消</view>
                    <view class="popup-btn confirm" :class="{'disabled': selectedFullPlt === null}" @click="confirmFullPlt">确认</view>
                </view>
            </view>
        </uni-popup>
    </view>
</template>
<script>
    import rfidScanner from '@/common/rfid-scanner.js';
    export default {
        data() {
            return {
                baseUrl: '',
                token: '',
                locNo: '',
                locNoFocus: true,
                locCacheInfo: null,
                msgType: 'success',
                messageText: '',
                title: '',
                content: '',
                isSubmitting: false,
                actionType: '', // 'lock', 'unlock', 'lockBay', 'unlockBay'
                actionLocNo: '',
                selectedFullPlt: null // true-满托, false-空托, null-未选择
            }
        },
        onLoad() {
        },
        onShow() {
            this.baseUrl = uni.getStorageSync('baseUrl');
            this.token = uni.getStorageSync('token');
            // 设置当前页面实例,用于全局扫描时自动填入
            rfidScanner.setCurrentPageInstance(this);
        },
        onHide() {
            // 页面隐藏时停止RFID扫描
        },
        methods: {
            // 库位号输入框获得焦点
            onLocNoFocus() {
                console.log('[locCacheLock] 库位号输入框获得焦点');
                this.locNoFocus = true;
            },
            // 库位号输入框失去焦点
            onLocNoBlur() {
                console.log('[locCacheLock] 库位号输入框失去焦点');
            },
            clearLocNo() {
                this.locNo = '';
                this.locCacheInfo = null;
                this.locNoFocus = false;
                setTimeout(() => {
                    this.locNoFocus = true;
                }, 100);
            },
            // 库位号输入事件
            locNoInput() {
                setTimeout(() => {
                    if (this.locNo && this.locNo.length >= 6) {
                        this.queryLocCache();
                    }
                }, 300);
            },
            // 查询库位信息
            queryLocCache() {
                if (!this.locNo) {
                    return;
                }
                let that = this;
                uni.request({
                    url: that.baseUrl + '/locCache/list/auth',
                    data: {
                        locNo: that.locNo,
                        curr: 1,
                        limit: 1
                    },
                    header: {
                        'token': uni.getStorageSync('token')
                    },
                    success(result) {
                        result = result.data;
                        if (result.code === 200 && result.data && result.data.records && result.data.records.length > 0) {
                            that.locCacheInfo = result.data.records[0];
                            that.messageText = "查询成功";
                            that.msgType = 'success';
                            that.$refs.message.open();
                        } else if (result.code == 403) {
                            that.messageText = result.msg;
                            that.msgType = 'error';
                            that.$refs.message.open();
                            setTimeout(() => {
                                uni.reLaunch({
                                    url: '../login/login'
                                });
                            }, 1000);
                        } else {
                            that.locCacheInfo = null;
                            that.messageText = result.msg || "库位不存在";
                            that.msgType = 'error';
                            that.$refs.message.open();
                        }
                    },
                    fail: () => {
                        that.messageText = "网络请求超时";
                        that.msgType = 'error';
                        that.$refs.message.open();
                    }
                });
            },
            // 标记当前库位为在库
            lockLoc() {
                if (!this.locCacheInfo || this.isSubmitting) return;
                this.actionType = 'lock';
                this.actionLocNo = this.locNo;
                this.selectedFullPlt = null;
                this.$refs.fullPltDialog.open();
            },
            // 确认已取走当前库位
            unlockLoc() {
                if (!this.locCacheInfo || this.isSubmitting) return;
                this.actionType = 'unlock';
                this.actionLocNo = this.locNo;
                this.title = '确认操作';
                this.content = '确认已取走库位:' + this.locNo + '?';
                this.$refs.confirmDialog.open();
            },
            // 标记当前列在库
            lockBay() {
                if (!this.locCacheInfo || this.isSubmitting) return;
                this.actionType = 'lockBay';
                this.actionLocNo = this.locNo;
                this.selectedFullPlt = null;
                this.$refs.fullPltDialog.open();
            },
            // 确认已取走当前列
            unlockBay() {
                if (!this.locCacheInfo || this.isSubmitting) return;
                this.actionType = 'unlockBay';
                this.actionLocNo = this.locNo;
                this.title = '确认操作';
                this.content = '确认已取走第' + this.locCacheInfo.bay1 + '列的所有库位?';
                this.$refs.confirmDialog.open();
            },
            // 确认已取走当前排
            clearAllColumnsInRow() {
                if (!this.locCacheInfo || this.isSubmitting) return;
                this.actionType = 'clearAllColumnsInRow';
                this.actionLocNo = this.locNo;
                this.title = '确认操作';
                this.content = '确认已取走第' + this.locCacheInfo.row1 + '排的所有库位(所有列)?';
                this.$refs.confirmDialog.open();
            },
            // 选择满托/空托
            selectFullPlt(fullPlt) {
                this.selectedFullPlt = fullPlt;
            },
            // 确认满托/空托选择
            confirmFullPlt() {
                if (this.selectedFullPlt === null) return;
                this.$refs.fullPltDialog.close();
                // 显示确认对话框
                if (this.actionType === 'lock') {
                    this.title = '确认标记';
                    this.content = '确认将库位:' + this.actionLocNo + ' 标记为在库(' + (this.selectedFullPlt ? '满托' : '空托') + ')?';
                } else if (this.actionType === 'lockBay') {
                    this.title = '确认标记';
                    this.content = '确认将第' + this.locCacheInfo.bay1 + '列的所有库位标记为在库(' + (this.selectedFullPlt ? '满托' : '空托') + ')?';
                }
                this.$refs.confirmDialog.open();
            },
            // 关闭满托/空托选择弹窗
            closeFullPltDialog() {
                this.$refs.fullPltDialog.close();
                this.selectedFullPlt = null;
            },
            // 确认操作
            confirmAction() {
                if (this.isSubmitting) return;
                this.isSubmitting = true;
                let that = this;
                let url = '';
                let data = {};
                if (this.actionType === 'lock' || this.actionType === 'unlock') {
                    // 锁定/解锁单个库位
                    url = that.baseUrl + '/locCache/lockOrUnlock/auth';
                    data = {
                        locNo: that.actionLocNo,
                        lock: that.actionType === 'lock'
                    };
                    // 如果是锁定操作,需要传递fullPlt参数
                    if (that.actionType === 'lock') {
                        data.fullPlt = that.selectedFullPlt;
                    }
                } else if (this.actionType === 'lockBay' || this.actionType === 'unlockBay') {
                    // 锁定/解锁当前列
                    url = that.baseUrl + '/locCache/lockOrUnlockBay/auth';
                    data = {
                        locNo: that.actionLocNo,
                        lock: that.actionType === 'lockBay'
                    };
                    // 如果是锁定操作,需要传递fullPlt参数
                    if (that.actionType === 'lockBay') {
                        data.fullPlt = that.selectedFullPlt;
                    }
                } else if (this.actionType === 'clearAllColumnsInRow') {
                    // 清空整排(所有列)
                    url = that.baseUrl + '/locCache/clearAllColumnsInRow/auth';
                    data = {
                        locNo: that.actionLocNo,
                        lock: false  // 清空操作,lock=false
                    };
                }
                uni.request({
                    url: url,
                    method: 'POST',
                    data: data,
                    header: {
                        'token': uni.getStorageSync('token')
                    },
                    success(result) {
                        var res = result.data;
                        if (res.code === 200) {
                            let actionDesc = '';
                            if (that.actionType === 'lock') {
                                actionDesc = '标记为在库(' + (that.selectedFullPlt ? '满托' : '空托') + ')';
                            } else if (that.actionType === 'unlock') {
                                actionDesc = '确认已取走当前库位';
                            } else if (that.actionType === 'lockBay') {
                                actionDesc = '标记当前列在库(' + (that.selectedFullPlt ? '满托' : '空托') + ')';
                            } else if (that.actionType === 'unlockBay') {
                                actionDesc = '确认已取走当前列';
                            } else if (that.actionType === 'clearAllColumnsInRow') {
                                actionDesc = '确认已取走当前排';
                            }
                            that.messageText = actionDesc + '成功';
                            that.msgType = 'success';
                            that.$refs.message.open();
                            // 重新查询库位信息
                            setTimeout(() => {
                                that.queryLocCache();
                            }, 500);
                            // 重置选择
                            that.selectedFullPlt = null;
                        } else if (res.code == 403) {
                            that.messageText = res.msg;
                            that.msgType = 'error';
                            that.$refs.message.open();
                            setTimeout(() => {
                                uni.reLaunch({
                                    url: '../login/login'
                                });
                            }, 1000);
                        } else {
                            that.messageText = res.msg || "操作失败";
                            that.msgType = 'error';
                            that.$refs.message.open();
                        }
                    },
                    fail: () => {
                        that.messageText = "网络请求超时";
                        that.msgType = 'error';
                        that.$refs.message.open();
                    },
                    complete: () => {
                        that.isSubmitting = false;
                        that.$refs.confirmDialog.close();
                    }
                });
            },
            // 关闭确认弹窗
            closeConfirm() {
                this.$refs.confirmDialog.close();
            },
            // 重置
            reset() {
                this.locNo = '';
                this.locCacheInfo = null;
                this.selectedFullPlt = null;
                this.locNoFocus = false;
                setTimeout(() => {
                    this.locNoFocus = true;
                }, 100);
            },
            // 获取库位状态描述
            getLocStsDesc(locSts) {
                if (!locSts) return '未知';
                const statusMap = {
                    'D': '空桶/空栈板',
                    'F': '在库',
                    'O': '空库位',
                    'P': '拣料/盘点/并板出库中',
                    'Q': '拣料/盘点/并板再入库',
                    'R': '出库预约',
                    'S': '入库预约',
                    'X': '禁用',
                    'Y': '被合并'
                };
                return statusMap[locSts] || '未知';
            }
        }
    }
</script>
<style>
    /* 引入公共样式 */
    @import url('../../static/css/common.css');
    @import url('../../static/css/wms.css/wms.css');
    .info-section {
        padding: 20rpx;
    }
    .info-card {
        background: #ffffff;
        border-radius: 16rpx;
        box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
        overflow: hidden;
    }
    .info-header {
        padding: 24rpx;
        border-bottom: 1rpx solid #f0f0f0;
    }
    .info-title {
        font-size: 32rpx;
        font-weight: 600;
        color: #333333;
    }
    .info-body {
        padding: 24rpx;
    }
    .info-row {
        display: flex;
        margin-bottom: 24rpx;
    }
    .info-row:last-child {
        margin-bottom: 0;
    }
    .info-col {
        flex: 1;
    }
    .info-col.half {
        flex: 0 0 50%;
    }
    .info-label {
        display: block;
        font-size: 26rpx;
        color: #999999;
        margin-bottom: 8rpx;
    }
    .info-value {
        display: block;
        font-size: 30rpx;
        color: #333333;
        font-weight: 500;
    }
    .info-value.locked {
        color: #f56c6c;
    }
    .info-value.unlocked {
        color: #67c23a;
    }
    .btn-group {
        display: flex;
        flex: 1;
        gap: 20rpx;
    }
    .btn-unlock, .btn-lock {
        flex: 1;
        height: 88rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 12rpx;
        gap: 12rpx;
    }
    .btn-unlock {
        background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
    }
    .btn-lock {
        background: linear-gradient(135deg, #f56c6c 0%, #f78989 100%);
    }
    .btn-disabled {
        opacity: 0.5;
        pointer-events: none;
    }
    .row-bar {
        padding: 20rpx;
        background: #f8f9fa;
        border-top: 1rpx solid #e9ecef;
    }
    .btn-group-row {
        display: flex;
        gap: 20rpx;
    }
    .btn-unlock-row, .btn-lock-row {
        flex: 1;
        height: 88rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 12rpx;
        gap: 12rpx;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    }
    .btn-unlock-row {
        background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
    }
    .btn-lock-row {
        background: linear-gradient(135deg, #f56c6c 0%, #f78989 100%);
    }
    .plt-options {
        display: flex;
        gap: 20rpx;
        margin-top: 20rpx;
    }
    .plt-option {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 12rpx;
        padding: 24rpx;
        border: 2rpx solid #e0e0e0;
        border-radius: 12rpx;
        background: #ffffff;
        transition: all 0.3s;
    }
    .plt-option.selected {
        border-color: #667eea;
        background: #f0f4ff;
    }
    .plt-text {
        font-size: 30rpx;
        color: #333333;
        font-weight: 500;
    }
    .popup-btn.disabled {
        opacity: 0.5;
        pointer-events: none;
    }
</style>