lsh
10 小时以前 218e046d9339ddf3a729930f6bb7b0b77bbed858
新增并板入库
3个文件已修改
1352 ■■■■■ 已修改文件
pages.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/sockroom/sockroom.vue 1348 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json
@@ -278,7 +278,7 @@
            "path" : "pages/sockroom/sockroom",
            "style" :                                                                                    
            {
                "navigationBarTitleText": "入库",
                "navigationBarTitleText": "1楼入库",
                "enablePullDownRefresh": false
            }
            
pages/home/home.vue
@@ -32,7 +32,7 @@
                        url: '/common/modeSwitch'
                    },
                    {
                        title: '入库',
                        title: '1楼入库',
                        name: 'sockroom',
                        color: 'cyan',
                        cuIcon: 'pullup',
pages/sockroom/sockroom.vue
@@ -1,31 +1,32 @@
<template>
    <view class="sockpage">
        <view class="column">
            <!-- 托盘编码 -->
            <view class="form-card">
                <view class="form-row">
                    <view class="label">
                        <text class="required">*</text>托盘编码:
                    </view>
                    <view class="picker-wrap" hover-class="picker-hover">
                    <view class="picker-wrap">
                        <view class="input-box">
                            <input 
                            id="pdacode"
                            type="text"
                            v-model="barcode"
                            placeholder="请扫码"
                                type="text"
                                v-model="barcode"
                                placeholder="请扫码"
                                placeholder-class="input-placeholder"
                            />
                        </view>
                    </view>
                </view>
            </view>
            
            <!-- 箱型栏(对应后端boxType) -->
            <!-- 箱型选择 -->
            <view class="form-card">
                <view class="form-row">
                    <view class="label">
                        <text class="required">*</text>箱    型:
                        <text class="required">*</text>箱型:
                    </view>
                    <view class="picker-wrap" hover-class="picker-hover">
                    <view class="picker-wrap">
                        <picker @change="modePickerChange" :value="index_mode" :range="mode">
                            <view class="input-box">
                                <text class="input-placeholder" v-if="!mode.length || !mode[index_mode]">请选择箱型</text>
@@ -36,115 +37,236 @@
                </view>
            </view>
            
                <view class="form-card">
                    <view class="form-row">
                        <view class="label">
                            <text class="required">*</text>物料码:
                        </view>
                        <view class="picker-wrap" hover-class="picker-hover">
                            <view class="textareainput">
                                <textarea
                                style="max-height: 15px;overflow: hidden;"
                                id="pdacode"
            <!-- 物料码扫码(隐藏但可用) -->
            <!-- <view class="form-card" style="height: 0; overflow: hidden; padding: 0; margin: 0;"> -->
            <view class="form-card" style=" overflow: hidden; padding: 0; margin: 0;">
                <view class="form-row">
                    <view class="label">
                        <text class="required">*</text>物料码:
                    </view>
                    <view class="picker-wrap">
                        <view class="input-box">
                            <input
                                type="text"
                                v-model="thingCode"
                                v-model="scanBuffer"
                                placeholder="请扫码"
                                @input="handleBarcodeInput"
                                @input="handleMaterialScan"
                                ref="scanInput"
                            />
                        </view>
                    </view>
                </view>
            </view>
            <!-- 物料信息 -->
            <view class="form-card material-card">
                <view class="card-title">物料信息</view>
                <!-- 多物料列表 -->
                <view class="material-list" v-if="matList.length > 0">
                    <view class="material-item" v-for="(mat, index) in matList" :key="mat.id">
                        <view class="material-header">
                            <text class="material-title">物料 {{ index + 1 }}</text>
                            <view class="material-actions">
                                <view class="action-btn" @click="removeMaterial(index)">删除</view>
                            </view>
                        </view>
                        <view class="material-grid">
                            <view class="material-item">
                                <text class="material-label"><text class="required">*</text>位置:</text>
                                <input
                                    class="material-input"
                                    type="text"
                                    v-model="mat.position"
                                    placeholder="请选择位置"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label"><text class="required">*</text>箱号:</text>
                                <input
                                    class="material-input"
                                    type="text"
                                    v-model="mat.batch"
                                    placeholder="请扫码或输入箱号"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label"><text class="required">*</text>卷号:</text>
                                <input
                                    class="material-input"
                                    type="text"
                                    v-model="mat.model"
                                    placeholder="请扫码或输入卷号"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label">规格:</text>
                                <input
                                    class="material-input"
                                    type="text"
                                    v-model="mat.matnr"
                                    placeholder="请输入规格"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label">长度:</text>
                                <input
                                    class="material-input"
                                    type="number"
                                    v-model="mat.rollExtent"
                                    placeholder="请输入长度"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label">净重:</text>
                                <input
                                    class="material-input"
                                    type="number"
                                    v-model="mat.weight"
                                    placeholder="请输入净重"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label">毛重:</text>
                                <input
                                    class="material-input"
                                    type="number"
                                    v-model="mat.roughWeight"
                                    placeholder="请输入毛重"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                            <view class="material-item">
                                <text class="material-label">接头:</text>
                                <input
                                    class="material-input"
                                    type="number"
                                    v-model="mat.joint"
                                    placeholder="请输入接头数"
                                    placeholder-class="input-placeholder"
                                />
                            </view>
                        </view>
                    </view>
                </view>
            <!-- 物料信息输入栏(对应后端MatList) -->
            <view class="form-card material-card">
                <view class="card-title">物料信息</view>
                <view class="material-grid">
                    <view class="material-item">
                        <text class="material-label"><text class="required">*</text>卷号:</text>
                        <input
                            class="material-input"
                            type="text"
                            v-model="matList.model"
                            placeholder="请扫码或输入卷号"
                            placeholder-class="input-placeholder"
                            ref="modelInput"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label"><text class="required">*</text>箱号:</text>
                        <input
                            class="material-input"
                            type="text"
                            v-model="matList.batch"
                            placeholder="请扫码或输入箱号"
                            placeholder-class="input-placeholder"
                            ref="batchInput"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label">规格:</text>
                        <input
                            class="material-input"
                            type="text"
                            v-model="matList.matnr"
                            placeholder="请输入规格"
                            placeholder-class="input-placeholder"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label">长度:</text>
                        <input
                            class="material-input"
                            type="number"
                            v-model="matList.rollExtent"
                            placeholder="请输入长度"
                            placeholder-class="input-placeholder"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label">净重:</text>
                        <input
                            class="material-input"
                            type="number"
                            v-model="matList.weight"
                            placeholder="请输入净重"
                            placeholder-class="input-placeholder"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label">毛重:</text>
                        <input
                            class="material-input"
                            type="number"
                            v-model="matList.roughWeight"
                            placeholder="请输入毛重"
                            placeholder-class="input-placeholder"
                        />
                    </view>
                    <view class="material-item">
                        <text class="material-label">接头:</text>
                        <input
                            class="material-input"
                            type="number"
                            v-model="matList.joint"
                            placeholder="请输入接头数"
                            placeholder-class="input-placeholder"
                        />
                    </view>
                <!-- 空状态提示 -->
                <view class="empty-state" v-else>
                    <view class="empty-icon">📦</view>
                    <text class="empty-text">暂无物料信息</text>
                    <text class="empty-tip">请扫描物料码添加物料</text>
                </view>
                <!-- 扫码按钮 -->
                <view class="scan-btn" @click="focusScanInput">
                    <text class="scan-icon">+</text>
                    <text class="scan-text">扫码添加物料</text>
                </view>
            </view>
            <!-- 操作按钮组 -->
            <view class="btn-group">
                <button class="operate-btn submit-btn" @click="submit">成品入库</button>
                <button class="operate-btn submit-btn" @click="submit">组托</button>
            </view>
        </view>
        <!-- 扫码确认弹窗 -->
        <view class="modal-mask" v-if="showScanModal" @click="closeModal">
            <view class="modal-content" @click.stop>
                <view class="modal-header">
                    <text class="modal-title">扫码确认</text>
                </view>
                <view class="modal-body">
                    <view class="scan-preview">
                        <text class="scan-label">扫描到物料:</text>
                        <text class="scan-code">{{ tempMaterial.model || '未知物料' }}</text>
                    </view>
                    <view class="preview-grid">
                        <view class="preview-item">
                            <text class="preview-label">箱号:</text>
                            <text class="preview-value">{{ tempMaterial.batch || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">卷号:</text>
                            <text class="preview-value">{{ tempMaterial.model || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">规格:</text>
                            <text class="preview-value">{{ tempMaterial.matnr || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">长度:</text>
                            <text class="preview-value">{{ tempMaterial.rollExtent || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">净重:</text>
                            <text class="preview-value">{{ tempMaterial.weight || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">毛重:</text>
                            <text class="preview-value">{{ tempMaterial.roughWeight || '未识别' }}</text>
                        </view>
                        <view class="preview-item">
                            <text class="preview-label">接头:</text>
                            <text class="preview-value">{{ tempMaterial.joint || '未识别' }}</text>
                        </view>
                        <view class="preview-item full-width">
                            <text class="preview-label">物料位置:</text>
                            <view class="position-selector" @click.stop="togglePositionPicker">
                                <view class="position-display">
                                    <text v-if="positionIndex >= 0">{{ positionOptions[positionIndex].label }}</text>
                                    <text v-else class="placeholder">请选择位置</text>
                                    <text class="position-arrow">▼</text>
                                </view>
                            </view>
                        </view>
                        <!-- 新增:自定义选择器弹出层 -->
                        <view v-if="showPositionPicker" class="custom-picker-overlay" @click.stop="closePositionPicker">
                            <view class="custom-picker-content" @click.stop>
                                <view class="custom-picker-header">
                                    <text class="custom-picker-title">选择物料位置</text>
                                    <view class="custom-picker-close" @click="closePositionPicker">×</view>
                                </view>
                                <view class="custom-picker-list">
                                    <view
                                        v-for="(item, index) in positionOptions"
                                        :key="index"
                                        class="custom-picker-item"
                                        :class="{'selected': positionIndex === index}"
                                        @click="selectPosition(index)"
                                    >
                                        <text class="custom-picker-text">{{ item.label }}</text>
                                        <text v-if="positionIndex === index" class="custom-picker-check">✓</text>
                                    </view>
                                </view>
                            </view>
                        </view>
                    </view>
                </view>
                <view class="modal-footer">
                    <button class="modal-btn cancel" @click="cancelAddMaterial">取消</button>
                    <button class="modal-btn confirm" @click="confirmAddMaterial">确定添加</button>
                </view>
            </view>
        </view>
    </view>
</template>
<script>
export default {
    onLoad(options){
    onLoad(options) {
        this.checkLoginStatus();
        this.POSTinfo();
        this.POSTinfo();
    },
    onShow() {
@@ -158,41 +280,292 @@
        }
    },
    onReady() {
        // 在页面准备就绪后初始化扫码监听
        setTimeout(() => {
            this.initScanListener();
        }, 500);
    },
    data() {
        return {
            thingCode:'',
            focusState: false,
            baseUrl: '',
            token: '',
            barcode: '',
            palletizingNo: '1',
            boxType: '',
            matList: {
                matnr: '',
                maktx: '',
                batch: '',
                model: '',
                position: '1',
                weight: '',
                roughWeight: '',
                anfme: 1.0,
                rollExtent: '',
                joint: 0,
                cutting: 2,
                qualified: 0,
                modelFront: '',
                batchFront: ''
            },
            mode: [],
            mode: [],
            index_mode: 0,
            submitData: {},
            // 扫码相关
            scanBuffer: '',
            scanTimeout: null,
            lastScanTime: 0,
            isProcessingScan: false
            // 物料列表
            matList: [],
            materialId: 1,
            // 弹窗相关
            showScanModal: false,
            tempMaterial: {
                model: '',
                batch: '',
                matnr: '',
                rollExtent: '',
                weight: '',
                roughWeight: '',
                joint: 0,
                position: '1' // 新增:物料位置,默认值为"1"(左)
            },
            // 新增:物料位置下拉框相关数据
            positionIndex: 0, // 默认选中第一个(左)
            // 新增:控制自定义选择器显示
            showPositionPicker: false,
            positionOptions: [
                { label: '1', value: '1' },
                { label: '2', value: '2' }
            ]
        }
    },
    methods: {
        // 新增:切换位置选择器显示
        togglePositionPicker() {
            this.showPositionPicker = !this.showPositionPicker;
        },
        // 新增:关闭位置选择器
        closePositionPicker() {
            this.showPositionPicker = false;
        },
        // 新增:选择位置
        selectPosition(index) {
            this.positionIndex = index;
            this.tempMaterial.position = this.positionOptions[index].value;
            this.closePositionPicker();
        },
        // 初始化扫码监听
        initScanListener() {
            // 在uni-app中,可以通过ref获取DOM节点,但要注意平台差异
            // 这里我们通过一个安全的方法来聚焦输入框
            this.$nextTick(() => {
                const input = this.$refs.scanInput;
                if (input && typeof input.focus === 'function') {
                    input.focus();
                }
            });
        },
        // 聚焦扫码输入框
        focusScanInput() {
            // 使用uni-app的安全方法
            this.$nextTick(() => {
                const input = this.$refs.scanInput;
                if (input) {
                    // 在uni-app中,input可能是一个组件实例
                    // 我们需要获取其DOM节点或使用平台特定的方法
                    // 这里我们尝试调用focus,如果不可用则跳过
                    try {
                        if (typeof input.focus === 'function') {
                            input.focus();
                        } else if (input.$el && typeof input.$el.focus === 'function') {
                            // 如果是Vue组件实例
                            input.$el.focus();
                        }
                    } catch (error) {
                        console.log('聚焦失败,但不影响功能:', error);
                    }
                }
            });
        },
        // 处理扫码输入
        handleMaterialScan(e) {
            const value = e.detail ? e.detail.value : e.target.value;
            // 防抖处理
            if (this.scanTimeout) {
                clearTimeout(this.scanTimeout);
            }
            this.scanTimeout = setTimeout(() => {
                if (value && value.trim()) {
                    this.parseBarcodeContent(value.trim());
                    this.showScanModal = true;
                    this.scanBuffer = ''; // 清空缓冲区
                    // 每次打开弹窗时重置位置选择为默认值
                    this.positionIndex = 0;
                    this.tempMaterial.position = '1';
                }
            }, 300);
        },
        // 解析条码内容
        parseBarcodeContent(content) {
            // const lines = content.split(/\\n/).filter(line => line.trim() !== '');
            const lines = content.split(' ').filter(line => line.trim().length > 0);
            // 清空临时数据
            this.tempMaterial = {
                model: '',
                batch: '',
                matnr: '',
                rollExtent: '',
                weight: '',
                roughWeight: '',
                joint: 0,
                position: '1' // 重置位置为默认值
            };
            // 使用正则表达式提取键值对[6,7](@ref)
            const extractKeyValue = (line) => {
                const match = line.match(/([^:]+):(.+)/);
                if (match && match.length === 3) {
                    return {
                        key: match[1].trim(),
                        value: match[2].trim()
                    };
                }
                return null;
            };
            // 提取数字(包括小数)[6,7](@ref)
            const extractNumber = (str) => {
                const match = str.match(/[\d.]+/);
                return match ? match[0] : '';
            };
            // 遍历每一行,解析键值对
            lines.forEach(line => {
                const keyValue = extractKeyValue(line);
                if (keyValue) {
                    const { key, value } = keyValue;
                    switch (key) {
                        case '卷号':
                            this.tempMaterial.model = value;
                            break;
                        case '箱号':
                            this.tempMaterial.batch = value;
                            break;
                        case '规格':
                            this.tempMaterial.matnr = value;
                            break;
                        case '长度':
                            this.tempMaterial.rollExtent = extractNumber(value);
                            break;
                        case '净重':
                            this.tempMaterial.weight = extractNumber(value);
                            break;
                        case '毛重':
                            this.tempMaterial.roughWeight = extractNumber(value);
                            break;
                        case '接头':
                            this.tempMaterial.joint = extractNumber(value) || 0;
                            break;
                        default:
                            // 可以处理未知键或忽略
                            break;
                    }
                }
            });
        },
        // 确认添加物料
        confirmAddMaterial() {
            this.closePositionPicker();
            if (!this.tempMaterial.model) {
                uni.showToast({
                    title: '卷号不能为空',
                    icon: 'none'
                });
                return;
            }
            // 检查是否已存在相同物料
            const exists = this.matList.some(item =>
                item.model === this.tempMaterial.model &&
                item.batch === this.tempMaterial.batch
            );
            if (exists) {
                uni.showToast({
                    title: '该物料已存在',
                    icon: 'none'
                });
                this.closeModal();
                return;
            };
            // 添加到物料列表
            const newMaterial = {
                id: this.materialId++,
                ...this.tempMaterial,
                position: (this.matList.length + 1).toString(),
                cutting: 2,
                qualified: 0
            };
            this.matList.push(newMaterial);
            uni.showToast({
                title: '物料添加成功',
                icon: 'success'
            });
            this.closeModal();
        },
        // 取消添加
        cancelAddMaterial() {
            this.closeModal();
        },
        // 关闭弹窗
        closeModal() {
            this.showPositionPicker = false;
            this.showScanModal = false;
            this.tempMaterial = {
                model: '',
                batch: '',
                matnr: '',
                rollExtent: '',
                weight: '',
                roughWeight: '',
                joint: 0,
                position: '1' // 重置位置
            };
            // 重置位置选择
            this.positionIndex = 0;
            // 重新聚焦到扫码输入框
            setTimeout(() => {
                this.focusScanInput();
            }, 100);
        },
        // 删除物料
        removeMaterial(index) {
            uni.showModal({
                title: '确认删除',
                content: '确定要删除这个物料吗?',
                success: (res) => {
                    if (res.confirm) {
                        this.matList.splice(index, 1);
                        uni.showToast({
                            title: '删除成功',
                            icon: 'success'
                        });
                    }
                }
            });
        },
        // 检查登录状态
        checkLoginStatus() {
            this.token = uni.getStorageSync('token');
@@ -217,7 +590,7 @@
        },
        
        // 获取箱型数据
        POSTinfo(){
        POSTinfo() {
            if (!this.checkLoginStatus()) return;
            
            uni.showLoading({
@@ -233,27 +606,14 @@
                },
                success: (res) => {
                    uni.hideLoading();
                    console.log('箱型接口返回:', res.data);
                    
                    if (res.data && res.data.code === 200) {
                        if (Array.isArray(res.data.data)) {
                            // 尝试多种可能的字段名
                            this.mode = res.data.data
                                .map(item => item.boxSpecs || item.boxType || item.typeName || item.name || '')
                                .filter(item => item && item.trim() !== '');
                            console.log('提取的箱型列表:', this.mode);
                            if (this.mode.length === 0) {
                                uni.showToast({
                                    title: '无可用箱型',
                                    icon: 'none'
                                });
                            }
                        } else {
                            console.warn('返回数据格式不符,不是数组:', res.data.data);
                    if (res.data && res.data.code === 200 && Array.isArray(res.data.data)) {
                        this.mode = res.data.data
                            .map(item => item.boxSpecs || item.boxType || item.typeName || item.name || '')
                            .filter(item => item && item.trim() !== '');
                        if (this.mode.length === 0) {
                            uni.showToast({
                                title: '数据格式错误',
                                title: '无可用箱型',
                                icon: 'none'
                            });
                        }
@@ -274,185 +634,63 @@
                }
            });
        },
        modePickerChange(e) {
            this.index_mode = e.detail.value;
            this.boxType = this.mode[this.index_mode];
            console.log('选择的箱型:', this.boxType);
        },
        handleBarcodeInput(e) {
                // 在uni-app中,textarea的input事件可能是e.detail.value
                const value = e.detail ? e.detail.value : e.target.value;
                this.thingCode = value;
                this.parseBarcodeContent(value);
            },
            parseBarcodeContent(content) {
                if (!content) return;
                // 按行分割内容
                const lines = content.split('\n').filter(line => line.trim() !== '');
                console.log('解析的行数据:', lines);
                // 根据你提供的样例格式解析
                // 格式为:
                // 2511080305A22B6  (卷号)
                // Y251113764        (箱号)
                // 5μm×1050mm       (规格)
                // 8700 m           (长度)
                // 418.0 kg         (净重)
                // 441.0 kg         (毛重)
                // 0 个             (接头)
                if (lines.length >= 7) {
                    // 卷号 (第一行)
                    this.matList.model = lines[0].trim();
                    // 箱号 (第二行)
                    this.matList.batch = lines[1].trim();
                    // 规格 (第三行)
                    this.matList.matnr = lines[2].trim();
                    // 长度 (第四行) - 提取数字部分
                    const lengthMatch = lines[3].match(/([\d.]+)/);
                    if (lengthMatch) {
                        this.matList.rollExtent = lengthMatch[1];
                    }
                    // 净重 (第五行) - 提取数字部分
                    const weightMatch = lines[4].match(/([\d.]+)/);
                    if (weightMatch) {
                        this.matList.weight = weightMatch[1];
                    }
                    // 毛重 (第六行) - 提取数字部分
                    const roughWeightMatch = lines[5].match(/([\d.]+)/);
                    if (roughWeightMatch) {
                        this.matList.roughWeight = roughWeightMatch[1];
                    }
                    // 接头 (第七行) - 提取数字部分
                    const jointMatch = lines[6].match(/([\d.]+)/);
                    if (jointMatch) {
                        this.matList.joint = jointMatch[1];
                    }
                    console.log('解析后的数据:', this.matList);
                } else if (lines.length > 0) {
                    // 如果行数不够,也可以尝试智能匹配
                    this.autoMatchFields(lines);
                }
            },
            // 智能匹配方法,用于处理可能的不规则数据
            autoMatchFields(lines) {
                lines.forEach((line, index) => {
                    line = line.trim();
                    // 根据内容特征匹配
                    if (index === 0 && !this.matList.model) {
                        // 假设第一行总是卷号
                        this.matList.model = line;
                    } else if (index === 1 && !this.matList.batch) {
                        // 假设第二行总是箱号
                        this.matList.batch = line;
                    } else if (line.includes('μm') || line.includes('mm') || line.includes('×')) {
                        // 包含规格特征的
                        this.matList.matnr = line;
                    } else if (line.includes('m') && line.match(/[\d.]+ m/)) {
                        // 长度特征
                        const match = line.match(/([\d.]+)/);
                        if (match) this.matList.rollExtent = match[1];
                    } else if (line.includes('kg') && line.match(/[\d.]+ kg/)) {
                        // 重量特征,需要区分净重和毛重
                        const match = line.match(/([\d.]+)/);
                        if (match) {
                            const weightValue = match[1];
                            if (!this.matList.weight) {
                                this.matList.weight = weightValue;
                            } else if (!this.matList.roughWeight) {
                                this.matList.roughWeight = weightValue;
                            }
                        }
                    } else if (line.includes('个') && line.match(/[\d.]+ 个/)) {
                        // 接头特征
                        const match = line.match(/([\d.]+)/);
                        if (match) this.matList.joint = match[1];
                    }
                });
            },
        // 重置表单
        resetForm() {
            this.barcode = '';
            this.boxType = '';
            this.index_mode = 0;
            this.matList = {
                matnr: '',
                maktx: '',
                batch: '',
                model: '',
                position: '1',
                weight: '',
                roughWeight: '',
                anfme: 1.0,
                rollExtent: '',
                joint: 0,
                cutting: 2,
                qualified: 0,
                modelFront: '',
                batchFront: ''
            };
            this.scanBuffer = '';
            this.focusState = false;
        },
        
        // 提交数据
        submit() {
            // 1. 验证登录
            if (!this.checkLoginStatus()) return;
            
            // 2. 验证必填项
            // 验证必填项
            if (!this.barcode) {
                uni.showToast({title: '请扫描托盘编码', icon: 'none'});
                return;
            }
            this.boxType = 999;
            if (!this.boxType) {
                uni.showToast({title: '请选择箱型', icon: 'none'});
                return;
            }
            
            if (!this.matList.model) {
                uni.showToast({title: '请填写卷号', icon: 'none'});
            if (this.matList.length === 0) {
                uni.showToast({title: '请至少添加一个物料', icon: 'none'});
                return;
            }
            
            if (!this.matList.batch) {
                uni.showToast({title: '请填写箱号', icon: 'none'});
                return;
            // 验证每个物料的必填字段
            for (let i = 0; i < this.matList.length; i++) {
                const mat = this.matList[i];
                if (!mat.model) {
                    uni.showToast({title: `物料${i+1}卷号不能为空`, icon: 'none'});
                    return;
                }
                if (!mat.batch) {
                    uni.showToast({title: `物料${i+1}箱号不能为空`, icon: 'none'});
                    return;
                }
            }
            
            // 3. 准备数据
            const matItem = {
                ...this.matList,
                weight: this.matList.weight ? Number(this.matList.weight) : null,
                roughWeight: this.matList.roughWeight ? Number(this.matList.roughWeight) : null,
                rollExtent: this.matList.rollExtent ? Number(this.matList.rollExtent) : null,
                joint: this.matList.joint ? Number(this.matList.joint) : 0
            };
            // 准备提交数据
            const submitData = {
                barcode: this.barcode,
                palletizingNo: this.palletizingNo,
                boxType: this.boxType,
                matList: [matItem]
                matList: this.matList.map(mat => ({
                    ...mat,
                    weight: mat.weight ? Number(mat.weight) : null,
                    roughWeight: mat.roughWeight ? Number(mat.roughWeight) : null,
                    rollExtent: mat.rollExtent ? Number(mat.rollExtent) : null,
                    joint: mat.joint ? Number(mat.joint) : 0,
                    position: mat.position // 包含位置信息
                }))
            };
            
            console.log('提交数据:', submitData);
            
            // 4. 发送请求
            // 发送请求
            uni.showLoading({
                title: '提交中...',
                mask: true
@@ -468,7 +706,6 @@
                data: submitData,
                success: (res) => {
                    uni.hideLoading();
                    console.log('提交返回:', res.data);
                    
                    if (res.data.code === 200) {
                        uni.showToast({
@@ -477,12 +714,13 @@
                            duration: 2000
                        });
                        
                        // 清空表单
                        setTimeout(() => {
                            this.resetForm();
                        }, 1500);
                    } else {
                        uni.showToast({
                            title: res.data.message || '提交失败',
                            title: res.data.msg || '提交失败',
                            icon: 'none'
                        });
                    }
@@ -497,212 +735,510 @@
                }
            });
        },
        // 重置表单
        resetForm() {
            this.barcode = '';
            this.boxType = '';
            this.index_mode = 0;
            this.matList = [];
            this.materialId = 1;
        }
    }
}
</script>
<style scoped>
/* 全局样式 */
/* 物料位置选择器样式 */
.full-width {
    grid-column: 1 / -1; /* 占满整行 */
    margin-top: 8rpx;
    position: relative;
    z-index: 100; /* 确保在弹窗内部层级正常 */
}
.position-selector {
    width: 200rpx;
    display: flex;
    justify-content: flex-end;
}
.position-picker {
    width: 200rpx;
}
.position-display {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8rpx 16rpx;
    border: 1rpx solid #e5e7eb;
    border-radius: 6rpx;
    background-color: #ffffff;
    color: #333;
    font-size: 28rpx;
    min-height: 40rpx;
    width: 100%;
    box-sizing: border-box;
}
.placeholder {
    color: #999;
}
.position-arrow {
    font-size: 20rpx;
    color: #666;
    margin-left: 8rpx;
}
/* 全局样式 - 保持原有风格 */
.sockpage {
    background-color: #f5f7fa;
    padding: 24rpx;
    padding: 20rpx;
    min-height: 100vh;
}
/* 表单列容器 */
.column {
    display: flex;
    flex-direction: column;
    gap: 24rpx;
    gap: 20rpx;
}
/* 表单卡片 */
.form-card {
    background: #ffffff;
    border-radius: 12rpx;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
    padding: 24rpx;
    transition: all 0.2s ease;
}
.textareainput{
    width: 60%;
    height: 15px;
    font-size: 28rpx;
    padding: 16rpx 12rpx;
    border: 1rpx solid #e5e7eb;
    border-radius: 8rpx;
    transition: border-color 0.2s ease;
}
/* 物料信息卡片特殊样式 */
.material-card {
    padding: 0;
}
.card-title {
    font-size: 30rpx;
    font-weight: 500;
    color: #1f2937;
    padding: 24rpx 24rpx 16rpx;
    border-bottom: 1rpx solid #f0f0f0;
    padding: 20rpx;
    box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
}
/* 表单行 */
.form-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 16rpx;
    gap: 20rpx;
}
/* 标签样式 */
.label {
    font-size: 28rpx;
    color: #374151;
    color: #333;
    font-weight: 500;
    min-width: 140rpx;
}
/* 必填项标红 */
.required {
    color: #ef4444;
    color: #e64340;
    margin-right: 4rpx;
}
/* 选择器容器 */
.picker-wrap {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
/* 选择器hover态 */
.picker-hover {
    background-color: #f9fafb;
    border-radius: 8rpx;
}
/* 输入框容器 */
.input-box {
    flex: 1;
    font-size: 28rpx;
    padding: 16rpx 12rpx;
    border: 1rpx solid #e5e7eb;
    border-radius: 8rpx;
    transition: border-color 0.2s ease;
    border-radius: 6rpx;
    padding: 16rpx 20rpx;
    background: #fff;
}
.input-box:focus-within {
    border-color: #f97316;
.input-placeholder {
    color: #999;
    font-size: 28rpx;
}
/* 输入值样式 */
.input-value {
    color: #1f2937;
    color: #333;
    font-size: 28rpx;
}
/* 扫码图标 */
.scan-icon {
/* 物料信息卡片 */
.material-card {
    padding: 0;
}
.card-title {
    font-size: 30rpx;
    font-weight: 500;
    color: #333;
    padding: 20rpx 20rpx 16rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
/* 物料列表 */
.material-list {
    padding: 0 20rpx;
}
.material-item {
    margin-bottom: 20rpx;
}
.material-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16rpx;
    padding-bottom: 12rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
.material-title {
    font-size: 28rpx;
    font-weight: 500;
    color: #333;
}
.material-actions {
    display: flex;
    gap: 20rpx;
}
.action-btn {
    font-size: 24rpx;
    margin-left: 8rpx;
    color: #6b7280;
    color: #e64340;
    padding: 6rpx 12rpx;
    border-radius: 4rpx;
    background: #fff0f0;
}
/* 物料信息网格布局 */
/* 物料网格 */
.material-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20rpx;
    padding: 24rpx;
    gap: 16rpx;
}
/* 物料信息项 */
.material-item {
    display: flex;
    flex-direction: column;
    gap: 8rpx;
}
/* 物料标签 */
.material-label {
    font-size: 26rpx;
    color: #4b5563;
    color: #666;
}
/* 物料输入框 */
.material-input {
    width: 45%;
    font-size: 28rpx;
    color: #1f2937;
    padding: 16rpx 12rpx;
    color: #333;
    padding: 12rpx;
    border: 1rpx solid #e5e7eb;
    border-radius: 8rpx;
    border-radius: 6rpx;
    background-color: #ffffff;
    transition: border-color 0.2s ease;
}
.material-input:focus {
    border-color: #f97316;
    outline: none;
/* 空状态 */
.empty-state {
    text-align: center;
    padding: 40rpx 20rpx;
}
/* 按钮组 */
.btn-group {
    display: flex;
    gap: 20rpx;
    justify-content: center;
    margin-top: 16rpx;
    padding: 8rpx 0;
.empty-icon {
    font-size: 60rpx;
    display: block;
    margin-bottom: 20rpx;
    opacity: 0.5;
}
/* 操作按钮通用样式 */
.operate-btn {
    flex: 1;
    max-width: 200rpx;
    height: 80rpx;
    line-height: 80rpx;
.empty-text {
    display: block;
    font-size: 28rpx;
    font-weight: 500;
    border-radius: 12rpx;
    border: none;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #999;
    margin-bottom: 10rpx;
}
.empty-tip {
    display: block;
    font-size: 24rpx;
    color: #ccc;
}
/* 扫码按钮 */
.scan-btn {
    background-color: #3b82f6;
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10rpx;
    padding: 20rpx;
    margin: 20rpx 20rpx 20rpx;
    background: #f0f7ff;
    border: 1rpx dashed #1989fa;
    border-radius: 8rpx;
    color: #1989fa;
    font-size: 28rpx;
}
.scan-btn:active {
    background-color: #2563eb;
    transform: scale(0.98);
.scan-icon {
    font-size: 36rpx;
    font-weight: bold;
}
/* 提交按钮 */
.submit-btn {
    background-color: #f97316;
    color: #ffffff;
/* 按钮组 */
.btn-group {
    margin-top: 20rpx;
    padding: 8rpx 0;
    text-align: center;
}
.submit-btn:active {
    background-color: #ea580c;
    transform: scale(0.98);
.operate-btn {
    width: 200rpx;
    height: 80rpx;
    line-height: 80rpx;
    font-size: 30rpx;
    font-weight: 500;
    border-radius: 8rpx;
    border: none;
    background: #333;
    color: #fff;
}
/* 适配小屏幕 */
@media (max-width: 375px) {
/* 弹窗样式 */
.modal-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}
.modal-content {
    background: #fff;
    border-radius: 12rpx;
    width: 600rpx;
    max-width: 90%;
    overflow: hidden;
}
.modal-header {
    padding: 30rpx 30rpx 20rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
.modal-title {
    font-size: 32rpx;
    font-weight: 500;
    color: #333;
}
.modal-body {
    padding: 30rpx;
}
.scan-preview {
    margin-bottom: 20rpx;
    padding-bottom: 20rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
.scan-label {
    font-size: 28rpx;
    color: #666;
    display: block;
    margin-bottom: 10rpx;
}
.scan-code {
    font-size: 32rpx;
    color: #333;
    font-weight: bold;
    word-break: break-all;
}
.preview-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 15rpx;
}
.preview-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.preview-label {
    font-size: 28rpx;
    color: #666;
}
.preview-value {
    font-size: 28rpx;
    color: #333;
    font-weight: 500;
}
.modal-footer {
    display: flex;
    border-top: 1rpx solid #f0f0f0;
}
.modal-btn {
    flex: 1;
    height: 90rpx;
    line-height: 90rpx;
    font-size: 30rpx;
    border: none;
    background: transparent;
    border-radius: 0;
}
.modal-btn.cancel {
    color: #999;
    border-right: 1rpx solid #f0f0f0;
}
.modal-btn.confirm {
    color: #1989fa;
    font-weight: 500;
}
/* 自定义选择器样式 */
.custom-picker-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999; /* 确保在最上层 */
}
.custom-picker-content {
    background-color: #ffffff;
    border-radius: 12rpx;
    width: 600rpx;
    max-width: 80%;
    max-height: 70vh;
    overflow: hidden;
    box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
    animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20rpx);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
.custom-picker-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 30rpx;
    border-bottom: 1rpx solid #f0f0f0;
}
.custom-picker-title {
    font-size: 32rpx;
    font-weight: 500;
    color: #333;
}
.custom-picker-close {
    font-size: 40rpx;
    color: #999;
    line-height: 1;
    padding: 0 10rpx;
    cursor: pointer;
}
.custom-picker-list {
    max-height: 50vh;
    overflow-y: auto;
    padding: 0;
}
.custom-picker-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 25rpx 30rpx;
    border-bottom: 1rpx solid #f5f5f5;
    cursor: pointer;
    transition: background-color 0.2s;
}
.custom-picker-item:last-child {
    border-bottom: none;
}
.custom-picker-item:hover {
    background-color: #f8f9fa;
}
.custom-picker-item.selected {
    background-color: #f0f7ff;
    color: #1989fa;
}
.custom-picker-text {
    font-size: 30rpx;
}
.custom-picker-check {
    font-size: 28rpx;
    color: #1989fa;
    font-weight: bold;
}
/* 弹窗样式调整,确保层级关系 */
.modal-mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000; /* 弹窗基础层级 */
}
.modal-content {
    position: relative; /* 确保子元素相对定位 */
    z-index: 1001; /* 比蒙版高一级 */
    background: #fff;
    border-radius: 12rpx;
    width: 600rpx;
    max-width: 90%;
    overflow: visible; /* 改为 visible 允许选择器弹出 */
}
/* 响应式适配 */
@media (max-width: 750rpx) {
    .material-grid {
        grid-template-columns: 1fr;
    }
    
    .operate-btn {
        max-width: 160rpx;
        height: 72rpx;
        line-height: 72rpx;
        font-size: 26rpx;
    .preview-grid {
        grid-template-columns: 1fr;
    }
    .modal-content {
        width: 90%;
    }
    .custom-picker-content {
        width: 90%;
        max-width: 90%;
    }
    .custom-picker-item {
        padding: 20rpx 25rpx;
    }
}
</style>