hwh
2024-09-03 c56d28d684cee010f291295dbe851bab64c1b6a6
设备监控绑定plc数据
8个文件已修改
430 ■■■■ 已修改文件
Admin.NET/WCS.Application/Hub/PlcHub.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCUtil.cs 174 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsTask/WcsTaskService.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/deviceMonitor/index.vue 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/wcs/wcsTask/component/editDialog.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/PlcHub.cs
@@ -42,7 +42,13 @@
    {
        //运行状态
        if (context.BoRunningState.HasValue)
        {
            PLCTaskAction.boRunningState = context.BoRunningState.Value;
            if (context.BoRunningState.Value)
                PLCTaskAction.Init();
            else
                PLCTaskAction.Stop();
        }
        //脱机模式
        if (context.BoOffline.HasValue)
            PLCTaskAction.boOffline = context.BoOffline.Value;
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -21,7 +21,7 @@
    private static List<WcsPosition> listPlcStation;
    private static List<PLCUtil> listPlcUtil = new List<PLCUtil>();
    private static CancellationTokenSource cts;//取消线程标识
    private static CancellationTokenSource cts = new CancellationTokenSource();//取消线程标识
    //对外公布连接状态
    public static List<PLCUtil> listPlcConn
    {
@@ -64,6 +64,7 @@
        cts = new CancellationTokenSource();
        boRunningState = true;
        StartRead();
        ConnectionStatus();
    }
    /// <summary>
    /// 开启读取plc线程
@@ -82,8 +83,10 @@
                    {
                        foreach (var modPlcUtil in listPlcUtil)
                        {
                            modPlcUtil.Close();
                            if (modPlcUtil != null && modPlcUtil.Connected)
                                modPlcUtil.Close();
                        }
                        break;
                        throw new OperationCanceledException();
                    }
                    try
@@ -94,7 +97,7 @@
                            modPlcUtil = new PLCUtil(modPlc);
                            listPlcUtil.Add(modPlcUtil);
                        }
                        var listDevice = listPlcDevice.Where(s => s.PlcId == _modplc.Id).ToList();
                        var listDevice = listPlcDevice.Where(s => s.PlcId == _modplc.Id && s.DeviceType == DeviceTypeEnum.Business).ToList();
                        //循环读设备
                        foreach (var modDevice in listDevice.Where(s => s.Level == DeviceLevelEnum.DB))
                        {
@@ -109,9 +112,9 @@
                                dto.Type = _modplc.Type;
                                dto.PLCUtil = modPlcUtil;
                                dto.listStation = listPlcStation.Where(s => s.DeviceId == modDevice.Id).ToList();
                                dto.listDevice = listDevice.Where(s => s.StationNum == modDevice.StationNum).ToList();
                                dto.listDevice = listDevice.Where(s => s.StationNum == modDevice.StationNum && s.Level == DeviceLevelEnum.Station).ToList();
                                //这里触发值变更事件
                                DeviceValueChangeEvent?.Invoke(dto, EventArgs.Empty);
                                //DeviceValueChangeEvent?.Invoke(dto, EventArgs.Empty);
                            }
                            else
                            {
Admin.NET/WCS.Application/PLC/PLCUtil.cs
@@ -13,7 +13,7 @@
    public readonly long PlcId;
    private SiemensClient _client;
    private WcsPlc _modPlc;
    private readonly object OLock = new object();
    public PLCUtil(WcsPlc modPlc)
    {
        PlcId = modPlc.Id;
@@ -42,52 +42,55 @@
    /// <returns></returns>
    public (IoTClient.Result, dynamic value) GetPlcDBValue(PLCDataTypeEnum PosType, string DbNumber, string Pos)
    {
        string address;
        if (DbNumber.StartsWith("DB"))
            address = DbNumber + "." + Pos;
        else
            address = DbNumber + Pos;
        dynamic result = null;
        switch (PosType)
        lock (OLock)
        {
            case PLCDataTypeEnum.Bit:
                result = _client.ReadBoolean(address);
                break;
            case PLCDataTypeEnum.Byte:
                result = _client.ReadByte(address);
                break;
            case PLCDataTypeEnum.Short:
                result = _client.ReadInt16(address);
                break;
            case PLCDataTypeEnum.UShort:
                result = _client.ReadUInt16(address);
                break;
            case PLCDataTypeEnum.Int:
                result = _client.ReadInt32(address);
                break;
            case PLCDataTypeEnum.UInt:
                result = _client.ReadUInt32(address);
                break;
            case PLCDataTypeEnum.Long:
                result = _client.ReadInt64(address);
                break;
            case PLCDataTypeEnum.ULong:
                result = _client.ReadUInt64(address);
                break;
            case PLCDataTypeEnum.Float:
                result = _client.ReadFloat(address);
                break;
            case PLCDataTypeEnum.Double:
                result = _client.ReadDouble(address);
                break;
            case PLCDataTypeEnum.String:
                result = _client.ReadString(address);
                break;
            default:
                result = new IoTClient.Result<object>();
                break;
            string address;
            if (DbNumber.StartsWith("DB"))
                address = DbNumber + "." + Pos;
            else
                address = DbNumber + Pos;
            dynamic result = null;
            switch (PosType)
            {
                case PLCDataTypeEnum.Bit:
                    result = _client.ReadBoolean(address);
                    break;
                case PLCDataTypeEnum.Byte:
                    result = _client.ReadByte(address);
                    break;
                case PLCDataTypeEnum.Short:
                    result = _client.ReadInt16(address);
                    break;
                case PLCDataTypeEnum.UShort:
                    result = _client.ReadUInt16(address);
                    break;
                case PLCDataTypeEnum.Int:
                    result = _client.ReadInt32(address);
                    break;
                case PLCDataTypeEnum.UInt:
                    result = _client.ReadUInt32(address);
                    break;
                case PLCDataTypeEnum.Long:
                    result = _client.ReadInt64(address);
                    break;
                case PLCDataTypeEnum.ULong:
                    result = _client.ReadUInt64(address);
                    break;
                case PLCDataTypeEnum.Float:
                    result = _client.ReadFloat(address);
                    break;
                case PLCDataTypeEnum.Double:
                    result = _client.ReadDouble(address);
                    break;
                case PLCDataTypeEnum.String:
                    result = _client.ReadString(address);
                    break;
                default:
                    result = new IoTClient.Result<object>();
                    break;
            }
            return (result, result.Value);
        }
        return (result, result.Value);
    }
    /// <summary>
    /// 批量读取PLC值
@@ -95,49 +98,52 @@
    /// <returns></returns>
    public Result<Dictionary<string, object>> GetPlcBatchDBValue(Dictionary<string, PLCDataTypeEnum> listaddress)
    {
        Dictionary<string, DataTypeEnum> addresses = new Dictionary<string, DataTypeEnum>();
        foreach (var address in listaddress)
        lock (OLock)
        {
            switch (address.Value)
            Dictionary<string, DataTypeEnum> addresses = new Dictionary<string, DataTypeEnum>();
            foreach (var address in listaddress)
            {
                case PLCDataTypeEnum.Bit:
                    addresses.Add(address.Key, DataTypeEnum.Bool);
                    break;
                case PLCDataTypeEnum.Byte:
                    addresses.Add(address.Key, DataTypeEnum.Byte);
                    break;
                case PLCDataTypeEnum.Short:
                    addresses.Add(address.Key, DataTypeEnum.Int16);
                    break;
                case PLCDataTypeEnum.UShort:
                    addresses.Add(address.Key, DataTypeEnum.UInt16);
                    break;
                case PLCDataTypeEnum.Int:
                    addresses.Add(address.Key, DataTypeEnum.Int32);
                    break;
                case PLCDataTypeEnum.UInt:
                    addresses.Add(address.Key, DataTypeEnum.UInt32);
                    break;
                case PLCDataTypeEnum.Long:
                    addresses.Add(address.Key, DataTypeEnum.Int64);
                    break;
                case PLCDataTypeEnum.ULong:
                    addresses.Add(address.Key, DataTypeEnum.UInt64);
                    break;
                case PLCDataTypeEnum.Float:
                    addresses.Add(address.Key, DataTypeEnum.Float);
                    break;
                case PLCDataTypeEnum.Double:
                    addresses.Add(address.Key, DataTypeEnum.Double);
                    break;
                case PLCDataTypeEnum.String:
                    addresses.Add(address.Key, DataTypeEnum.String);
                    break;
                default:
                    break;
                switch (address.Value)
                {
                    case PLCDataTypeEnum.Bit:
                        addresses.Add(address.Key, DataTypeEnum.Bool);
                        break;
                    case PLCDataTypeEnum.Byte:
                        addresses.Add(address.Key, DataTypeEnum.Byte);
                        break;
                    case PLCDataTypeEnum.Short:
                        addresses.Add(address.Key, DataTypeEnum.Int16);
                        break;
                    case PLCDataTypeEnum.UShort:
                        addresses.Add(address.Key, DataTypeEnum.UInt16);
                        break;
                    case PLCDataTypeEnum.Int:
                        addresses.Add(address.Key, DataTypeEnum.Int32);
                        break;
                    case PLCDataTypeEnum.UInt:
                        addresses.Add(address.Key, DataTypeEnum.UInt32);
                        break;
                    case PLCDataTypeEnum.Long:
                        addresses.Add(address.Key, DataTypeEnum.Int64);
                        break;
                    case PLCDataTypeEnum.ULong:
                        addresses.Add(address.Key, DataTypeEnum.UInt64);
                        break;
                    case PLCDataTypeEnum.Float:
                        addresses.Add(address.Key, DataTypeEnum.Float);
                        break;
                    case PLCDataTypeEnum.Double:
                        addresses.Add(address.Key, DataTypeEnum.Double);
                        break;
                    case PLCDataTypeEnum.String:
                        addresses.Add(address.Key, DataTypeEnum.String);
                        break;
                    default:
                        break;
                }
            }
            return _client.BatchRead(addresses);
        }
        return _client.BatchRead(addresses);
    }
    /// <summary>
    /// 写入PLC值
Admin.NET/WCS.Application/Service/WcsDevice/Dto/WcsDeviceOutput.cs
@@ -124,12 +124,26 @@
    /// 任务类型
    /// </summary>
    public TaskTypeEnum? TaskType { get; set; }
    /// <summary>
    /// 起始工位
    /// </summary>
    public string StartLocatNo { get; set; }
    /// <summary>
    /// 结束工位
    /// </summary>
    public string EndLocatNo { get; set; }
    /// <summary>
    /// 托盘码
    /// </summary>
    public string PalletNo { get; set; }
    public string Plc { get; set; }
    public string Wcs { get; set; }
    /// <summary>
    /// 连接状态
    /// </summary>
    public bool Status { get; set; }
    public bool Status { get; set; } = false;
}
Admin.NET/WCS.Application/Service/WcsDevice/WcsDeviceService.cs
@@ -1,5 +1,6 @@

using Admin.NET.Core.Service;
using Elastic.Clients.Elasticsearch;
namespace WCS.Application;
@@ -203,20 +204,69 @@
    {
        var list = await _wcsDeviceRep.AsQueryable()
                                    .LeftJoin<WcsPlc>((a, b) => a.PlcId == b.Id)
                                    .Where((a, b) => a.DeviceType == DeviceTypeEnum.Business)
                                    .Select<WcsDeviceOutput>((a, b) => new WcsDeviceOutput() { Type = b.Type }, true)
                                    .ToListAsync();
        //获取跺机的状态
        foreach (var modDevice in list)
        {
            if (_sysCacheService.ExistKey("PlcConn" + modDevice.PlcId))
            if (_sysCacheService.ExistKey("PLCCONN" + modDevice.PlcId))
            {
                var cachePlc = _sysCacheService.Get<WcsPlc>("PlcConn" + modDevice.PlcId);
                var cachePlc = _sysCacheService.Get<WcsPlc>("PLCCONN" + modDevice.PlcId);
                modDevice.Status = cachePlc.IsConn;
                if (modDevice.Status)
                {
                    //读取plc的值
                    var modConn = PLCTaskAction.listPlcConn.FirstOrDefault(s => s != null && s.PlcId == modDevice.PlcId);
                    if (modConn == null)
                        break;
                    try
                    {
                        var listPosition = await _wcsDeviceRep.Context.Queryable<WcsPosition>().Where(s => s.DeviceId == modDevice.Id).ToListAsync();
                        (var result, var plc) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.PlcPos);
                        modDevice.Plc = Convert.ToString(plc);
                        (result, var wcs) = modConn.GetPlcDBValue(modDevice.PosType, modDevice.DbNumber, modDevice.WcsPos);
                        modDevice.Wcs = Convert.ToString(wcs);
                        //任务号
                        var modPositionTask = listPosition.FirstOrDefault(s => s.Text == "任务号");
                        (result, var taskNo) = modConn.GetPlcDBValue(modPositionTask.PosType, modDevice.DbNumber, modPositionTask.PlcPos);
                        modDevice.TaskNo = Convert.ToString(taskNo);
                        //任务类型
                        var modPositionTaskType = listPosition.FirstOrDefault(s => s.Text == "任务类型");
                        (result, var taskType) = modConn.GetPlcDBValue(modPositionTaskType.PosType, modDevice.DbNumber, modPositionTaskType.PlcPos);
                        modDevice.TaskType = (TaskTypeEnum)Convert.ToInt32(taskType);
                        //起始工位
                        var modPositionStartLocatNo = listPosition.FirstOrDefault(s => s.Text == "起始工位");
                        (result, var startLocatNo) = modConn.GetPlcDBValue(modPositionStartLocatNo.PosType, modDevice.DbNumber, modPositionStartLocatNo.PlcPos);
                        modDevice.StartLocatNo = Convert.ToString(startLocatNo);
                        //目的工位
                        var modPositionEndLocatNo = listPosition.FirstOrDefault(s => s.Text == "目的工位");
                        (result, var endLocatNo) = modConn.GetPlcDBValue(modPositionEndLocatNo.PosType, modDevice.DbNumber, modPositionEndLocatNo.PlcPos);
                        modDevice.EndLocatNo = Convert.ToString(endLocatNo);
                        //托盘码
                        var modPositionPalletNo = listPosition.FirstOrDefault(s => s.Text == "托盘码");
                        (result, var palletNo) = modConn.GetPlcDBValue(modPositionPalletNo.PosType, modDevice.DbNumber, modPositionPalletNo.PlcPos);
                        modDevice.PalletNo = Convert.ToString(palletNo);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            else
            {
                modDevice.Status = false;
            }
            //modDevice.TaskNo = "TK00001";
            //modDevice.TaskType = TaskTypeEnum.In;
            //modDevice.PalletNo = "2024209032";
            //modDevice.StartLocatNo = "010101";
            //modDevice.EndLocatNo = "020202";
            //modDevice.Wcs = new Random().Next(100).ToString();
            //modDevice.Plc = new Random().Next(100).ToString();
            //modDevice.Status = true;
        }
        return list;
Admin.NET/WCS.Application/Service/WcsTask/WcsTaskService.cs
@@ -52,7 +52,12 @@
    [DisplayName("增加任务表")]
    public async Task<long> Add(AddWcsTaskInput input)
    {
        if(await _wcsTaskRep.AsQueryable().AnyAsync(s => s.TaskNo == input.TaskNo))
        {
            throw Oops.Bah("任务号重复");
        }
        var entity = input.Adapt<WcsTask>();
        entity.Origin = "WCS";
        await _wcsTaskRep.InsertAsync(entity);
        return entity.Id;
    }
Web/src/views/device/deviceMonitor/index.vue
@@ -4,43 +4,49 @@
            <el-card class="box-card">
                <div slot="header" class="linefix">
                    <span>输送线</span>
                    <div class="lineStatus"></div>
                    <div
                        :class="['lineStatus', { 'device-status-0': stationValue.status === true }, { 'device-status-1': stationValue.status === false }]">
                    </div>
                </div>
                <div class="choosefix">
                    <el-select v-model="lineValue" placeholder="请选择">
                    <el-select v-model="lineValue" placeholder="请选择" @change="handleLineChange('item', $event)">
                        <el-option v-for="item in lineOptions" :key="item.value" :label="item.label"
                            :value="item.value"></el-option>
                    </el-select>
                    <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;">
                        <el-option v-for="item in stations" :key="item.id" :label="item.stationNum"
                            :value="item.id"></el-option>
                    <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;"
                        value-key="stationNum">
                        <el-option v-for="item in listStationsData" :key="item.id" :label="item.stationNum"
                            :value="item">
                        </el-option>
                    </el-select>
                </div>
                <div class="lineValuefix">
                    <el-form label-position="left" label-width="80px">
                        <el-form-item label="任务号">
                            <el-input></el-input>
                            <el-input v-model="stationValue.taskNo"></el-input>
                        </el-form-item>
                        <el-form-item label="任务类型">
                            <el-input></el-input>
                            <el-select clearable v-model="stationValue.taskType" placeholder="请选择任务类型">
                                <el-option v-for="(item,index) in dl('TaskTypeEnum')" :key="index" :value="Number(item.value)" :label="`${item.name} [${item.value}]`"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="起始工位">
                            <el-input></el-input>
                            <el-input v-model="stationValue.startLocatNo"></el-input>
                        </el-form-item>
                        <el-form-item label="目的工位">
                            <el-input></el-input>
                            <el-input v-model="stationValue.endLocatNo"></el-input>
                        </el-form-item>
                        <el-form-item label="托盘码">
                            <el-input></el-input>
                            <el-input v-model="stationValue.palletNo"></el-input>
                        </el-form-item>
                        <el-form-item label="PLC">
                            <el-input></el-input>
                            <el-input v-model="stationValue.plc"></el-input>
                        </el-form-item>
                        <el-form-item label="WCS">
                            <el-input></el-input>
                            <el-input v-model="stationValue.wcs"></el-input>
                        </el-form-item>
                        <el-form-item label="状态">
                            <el-input></el-input>
                            <el-input :value="stationValue.status ? '在线' : '离线'" readonly></el-input>
                        </el-form-item>
                    </el-form>
                </div>
@@ -71,8 +77,15 @@
                            <el-form-item label="任务类型">
                                <el-select clearable="" v-model="deviceInfo.taskType" placeholder="请选择状态">
                                    <el-option v-for="(item, index) in dl('TaskTypeEnum')" :key="index"
                                        :value="Number(item.value)" :label="`${item.name} (${item.code}) [${item.value}] `" />
                                        :value="Number(item.value)"
                                        :label="`${item.name} [${item.value}] `" />
                                </el-select>
                            </el-form-item>
                            <el-form-item label="起始工位">
                                <el-input v-model="deviceInfo.startLocatNo"></el-input>
                            </el-form-item>
                            <el-form-item label="目的工位">
                                <el-input v-model="deviceInfo.endLocatNo"></el-input>
                            </el-form-item>
                            <el-form-item label="PLC">
                                <el-input v-model="deviceInfo.plc"></el-input>
@@ -106,10 +119,19 @@
import { getDictLabelByVal as dv } from '/@/utils/dict-utils';
const stations = ref<any>([]);
const listStationsData = ref<any>([]);
const listStackingMachineData = ref<any>([]);
const lineValue = ref('1');
const stationValue = ref();
const lineValue = ref(1);
const stationValue = ref<any>({
    taskNo: '',
    taskType: '',
    startLocatNo:'',
    endLocatNo: '',
    plc: '',
    wcs: '',
    status: false
});
// 查询操作
const handleQuery = async () => {
@@ -117,47 +139,29 @@
    listStackingMachineData.value = res.data.result.filter(s => s.type == 0);
    const listConveyorLineData = res.data.result.filter(s => s.type == 1 || s.type == 4);
    stations.value = {
        '1': listConveyorLineData.filter(s => s.text = '1层托盘输送线'),
        '2': listConveyorLineData.filter(s => s.text = '2层托盘输送线'),
        '3': listConveyorLineData.filter(s => s.text = '3层托盘输送线')
        1: listConveyorLineData.filter(s => s.text == '1层托盘输送线'),
        2: listConveyorLineData.filter(s => s.text == '2层托盘输送线'),
        3: listConveyorLineData.filter(s => s.text == '3层托盘输送线')
    }
    if (stations.value.length > 0)
        stationValue.value = stations.value[0][0].id;
    debugger;
    if (stations.value[1].length > 0) {
        listStationsData.value = stations.value[1];
        stationValue.value = listStationsData.value[0];
    }
};
handleQuery();
const handleLineChange = (field: string, value: number) => {
    listStationsData.value = stations.value[value];
    stationValue.value = {};
};
const lineOptions = [
    { value: '1', label: '一楼输送线' },
    { value: '2', label: '二楼输送线' },
    { value: '3', label: '三楼输送线' }
    { value: 1, label: '一楼输送线' },
    { value: 2, label: '二楼输送线' },
    { value: 3, label: '三楼输送线' }
];
const deviceList = reactive([
    { id: 1, name: '1号码垛机器人', taskNumber: 'T000001', taskType: '', plc: '', wcs: '', status: 0 },
    { id: 2, name: '2号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 1 },
    { id: 3, name: '3号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 },
    { id: 4, name: '4号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 1 },
    { id: 5, name: '5号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 },
    { id: 6, name: '6号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 },
    { id: 7, name: '7号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: '' },
    { id: 8, name: '8号码垛机器人', taskNumber: '', taskType: '', plc: '', wcs: '', status: 0 }
]);
const deviceTypeText = (taskType: number) => {
    switch (taskType) {
        case 0:
            return '入库任务'
        case 1:
            return '出库任务'
        case 2:
            return '移库任务'
        case 3:
            return 'PLC申请入库'
    }
    return ''
};
</script>
<style scoped>
@@ -165,8 +169,8 @@
    font-size: 14px;
}
.item {
    margin-bottom: 18px;
.el-form-item--small {
    margin-bottom: 10px;
}
.linefix {
Web/src/views/wcs/wcsTask/component/editDialog.vue
@@ -30,13 +30,6 @@
                        
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="来源" prop="origin">
                            <el-input v-model="ruleForm.origin" placeholder="请输入来源" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="起始位置" prop="startLocate">
                            <el-input v-model="ruleForm.startLocate" placeholder="请输入起始位置" maxlength="20" show-word-limit clearable />
                            
@@ -67,55 +60,6 @@
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="托盘号" prop="palletNo">
                            <el-input v-model="ruleForm.palletNo" placeholder="请输入托盘号" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="批次号" prop="lotNo">
                            <el-input v-model="ruleForm.lotNo" placeholder="请输入批次号" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="供货批次" prop="supplierLot">
                            <el-input v-model="ruleForm.supplierLot" placeholder="请输入供货批次" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="物料编码" prop="skuNo">
                            <el-input v-model="ruleForm.skuNo" placeholder="请输入物料编码" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="物料名称" prop="skuName">
                            <el-input v-model="ruleForm.skuName" placeholder="请输入物料名称" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="数量" prop="qty">
                            <el-input-number v-model="ruleForm.qty" placeholder="请输入数量" clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="拆垛数量" prop="completeQty">
                            <el-input-number v-model="ruleForm.completeQty" placeholder="请输入拆垛数量" clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="拣货方式" prop="unstackingMode">
                            <el-input v-model="ruleForm.unstackingMode" placeholder="请输入拣货方式" maxlength="10" show-word-limit clearable />
                            
                        </el-form-item>