huangxiaoqiang
2 天以前 5692e40d092d4ff6b72ddfbd053ea431c8d1d876
添加任务删除功能及相关接口实现

在 `ITaskService.cs` 中添加 `Delete` 方法以支持任务删除,并在 `TaskService.cs` 中实现该方法,处理删除逻辑。更新 `CommonConveyorLine_GWJob.cs`,移除多余注释并优化任务查询。新增对当前托盘任务的检查逻辑,确保在存在任务时进行删除。

更新 `Dt_BillGroupStock_Hty.vue` 和 `Dt_OutTime.vue` 组件,添加元信息和模板结构,调整表格字段。新增路由配置指向 `Dt_BillGroupStock_Hty` 组件。

定义 `IStockInfoHtyRepository.cs` 和 `IStockInfoHtyService.cs` 接口,提供对 `DtStockInfo_Hty` 的基本操作。实现 `StockInfoHtyRepository.cs` 和 `StockInfoHtyService.cs` 中的 CRUD 操作,包括分页查询和批量删除功能。

创建 `StockInfoHtyController.cs` 控制器,提供 API 接口供前端调用。
已修改6个文件
已添加8个文件
776 ■■■■■ 文件已修改
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob_GW/CommonConveyorLine_GWJob.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob_GW/GWTask/RequestInbound.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSClient/src/extension/widesea_wms/stock/Dt_BillGroupStock_Hty.jsx 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSClient/src/extension/widesea_wms/stock/Dt_OutTime.jsx 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSClient/src/router/tables.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSClient/src/views/widesea_wms/stock/Dt_BillGroupStock_Hty.vue 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSClient/src/views/widesea_wms/stock/Dt_OutTime.vue 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_IStorageBasicRepository/Stock/IStockInfoHtyRepository.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_IStorageBasicService/Stock/IStockInfoHtyvice.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_StorageBasicRepository/Stock/StockInfoHtyRepository.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_StorageBasicServices/Stock/StockInfoHtyService.cs 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/StockInfoHtyController.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs
@@ -321,5 +321,7 @@
        /// <param name="deviceNo"></param>
        /// <returns></returns>
        Dt_Task QueryOutFireAlarmTask(string deviceNo);
        WebResponseContent Delete(Dt_Task task);
    }
}
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -960,6 +960,14 @@
            return wcsBasez + address;
        }
        public WebResponseContent Delete(Dt_Task task)
        {
            var taskHty = task.Adapt<Dt_Task_Hty>();
            taskHty.Creater = App.User.UserName != null ? App.User.UserName : "System";
            _taskHtyRepository.AddData(taskHty);
            return base.DeleteData(task);
        }
        #region é‡å†™æ–¹æ³•
        public override WebResponseContent DeleteData(object[] key)
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob_GW/CommonConveyorLine_GWJob.cs
@@ -202,8 +202,6 @@
            try
            {
                var task = _taskService.QueryBarCodeConveyorLineTask(command.ConveyorLineBarcode, childDeviceCode);
                //HandleTaskOut(conveyorLine, command, childDeviceCode, task);
                // && command.ConveyorLineBarcode != "NoRead" && !command.ConveyorLineBarcode.IsNotEmptyOrNull()
                var log = $"【{conveyorLine.DeviceName}】托盘号:【{command.ConveyorLineBarcode}】任务号:【{command.ConveyorLineTaskNum}】设备编码:【{childDeviceCode}】";
                ConsoleHelper.WriteSuccessLine(log);
@@ -216,9 +214,6 @@
                }
                else
                {
                    //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                    //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                    //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)task.TaskNum, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, task.NextAddress, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, childDeviceCode);
@@ -241,7 +236,6 @@
        /// <param name="childDeviceCode">子设备编号</param>
        public void RequestInNextAddress(CommonConveyorLine_GW conveyorLine, ConveyorLineTaskCommand_After command, string childDeviceCode)
        {
            //Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.ConveyorLineTaskNum, childDeviceCode);
            Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.ConveyorLineTaskNum, childDeviceCode, command.ConveyorLineBarcode);
            if (task != null)
            {
@@ -275,8 +269,6 @@
            var task = _taskService.QueryExecutingTaskByBarcode(command.ConveyorLineBarcode, childDeviceCode);
            if (task != null && task.TaskState != (int)TaskInStatusEnum.Line_InFinish)
            {
                //ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                if (content.Status)
@@ -301,10 +293,6 @@
            //var task = _taskService.QueryConveyorLineTask(conveyorLine.DeviceCode, childDeviceCode, command.ConveyorLineBarcode);
            if (task != null)
            {
                //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)task.TaskNum, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, task.NextAddress, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, childDeviceCode);
@@ -362,10 +350,6 @@
                    Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
                    if (newTask != null)
                    {
                        //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(newTask);
                        //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)newTask.TaskNum, childDeviceCode);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, newTask.NextAddress, childDeviceCode);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, newTask.PalletCode, childDeviceCode);
@@ -375,11 +359,6 @@
                }
                else
                {
                    //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                    //taskCommand.ConveyorLineTargetAddress = Convert.ToInt16(stationManager.stationNGChildCode);
                    //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                    //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)task.TaskNum, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, task.NextAddress, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, childDeviceCode);
@@ -484,7 +463,8 @@
                                _needBarcodeRepository.UpdateData(needBarcode);
                            }
                        }
                        content = _taskService.UpdateTaskStatusToNext(task);
                        taskNext.ExceptionMessage = log;
                        content = _taskService.UpdateTaskStatusToNext(taskNext);
                        var proAddress = conveyorLine.DeviceProDTOs
                                        .FirstOrDefault(x => x.DeviceChildCode == childDeviceCode && x.DeviceProParamName == ConveyorLineDBName_After.InteractiveSignal.ToString())
                                        ?.DeviceProAddress;
CodeManagement/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob_GW/GWTask/RequestInbound.cs
@@ -360,7 +360,19 @@
                if (_taskRepository.QueryFirst(x => x.PalletCode == command.ConveyorLineBarcode) != null)
                {
                    WriteInfo(conveyorLine.DeviceName, "当前托盘存在任务");
                    List<string> strings = new List<string>() { "3637", "3633", "3629" };
                    var taskExecuting = _taskRepository.QueryFirst(x => x.PalletCode == command.ConveyorLineBarcode && x.TaskState == (int)TaskOutStatusEnum.Line_OutExecuting && strings.Contains(x.TargetAddress));
                    if (taskExecuting != null)
                    {
                        taskExecuting.ExceptionMessage = "未接收到线体完成信号系统内部自动完成";
                        _taskService.Delete(taskExecuting);
                    }
                    ConsoleHelper.WriteErrorLine($"当前托盘存在任务:【{command.ConveyorLineBarcode}】");
                    WriteInfo(conveyorLine.DeviceName, $"当前托盘存在任务{command.ConveyorLineBarcode}");
                    return;
                }
@@ -371,15 +383,9 @@
                var content = CreateAndSendTask(taskDTO);
                if (content.Status)
                {
                    //var task = _taskService.QueryConveyorLineTask(conveyorLine.DeviceCode, childDeviceCode);
                    var task = _taskService.QueryConveyorLineTask(conveyorLine.DeviceCode, childDeviceCode, command.ConveyorLineBarcode);
                    if (task != null)
                    {
                        //var taskCommand = MapTaskCommand(task, command);
                        //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                        //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)task.TaskNum, childDeviceCode);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, task.NextAddress, childDeviceCode);
                        conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, childDeviceCode);
@@ -430,10 +436,6 @@
            var Hastask = _taskService.QueryBarCodeConveyorLineTask(command.ConveyorLineBarcode, childDeviceCode);
            if (Hastask != null)
            {
                //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(Hastask);
                //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)Hastask.TaskNum, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, Hastask.NextAddress, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, Hastask.PalletCode, childDeviceCode);
@@ -447,11 +449,6 @@
                var task = _taskService.QueryBarCodeConveyorLineTask(command.ConveyorLineBarcode, childDeviceCode);
                if (task != null)
                {
                    //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                    //conveyorLine.SendCommand(taskCommand, childDeviceCode);
                    //conveyorLine.SetValue(ConveyorLineDBName_After.ResponState, 1, childDeviceCode);
                    //ConveyorLineTaskCommand_After taskCommand = _mapper.Map<ConveyorLineTaskCommand_After>(task);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTaskNum, (long)task.TaskNum, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, task.NextAddress, childDeviceCode);
                    conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, childDeviceCode);
CodeManagement/WMS/WIDESEA_WMSClient/src/extension/widesea_wms/stock/Dt_BillGroupStock_Hty.jsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
/*****************************************************************************************
 **  Author:jxx 2022
 **  QQ:283591387
 **完整文档见:http://v2.volcore.xyz/document/api ã€ä»£ç ç”Ÿæˆé¡µé¢ViewGrid】
 **常用示例见:http://v2.volcore.xyz/document/vueDev
 **后台操作见:http://v2.volcore.xyz/document/netCoreDev
 *****************************************************************************************/
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
// import gridHeader from "./demo_Product/Dt_BillGroupStockDetail.vue";
import gridBody from "./extend/SupplementationData.vue"
let extension = {
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridBody: gridBody,
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: '',
    modelBody: '',
    modelFooter: ''
  },
  tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
  buttons: { view: [], box: [], detail: [] }, //扩展的按钮
  methods: {
    //下面这些方法可以保留也可以删除
    onInit() {
      //框架初始化配置前,
      let OutBoundBtn = this.buttons.find((x) => x.value == 'OutBound')
      if (OutBoundBtn) {
        OutBoundBtn.onClick = function () {
          // this.$Message.success('点击了按钮')
          let row = this.$refs.table.getSelected() //获取选中的行
          if (row <= 0) {
            //如果没有选中行
            this.$Message.error('请选择一行数据')
            return
          }
          let locationCode = row[0].locationCode
          let palletCode = row[0].palletCode
          this.http
            .get(
              `/api/Task/CreateAndSendOutboundTask?locationCode=${locationCode}&palletCode=${palletCode}`,
              {},
              '正在创建任务'
            )
            .then((res) => {
              //示例:调用后台接口
              if (res.status) {
                this.$Message.success('创建任务成功')
                console.log(res)
                this.refresh() //刷新表格
              } else {
                this.$Message.error(res.message) //错误提示
              }
            })
        }
      }
      var btnSupplementationData = this.buttons.find(x => x.value == "SupplementationData");
            if (btnSupplementationData != null) {
                btnSupplementationData.onClick = () => {
                    let rows = this.$refs.table.getSelected();
                        if (rows.length == 0) {
                            return this.$error("请选择数据!");
                        } else if (rows.length > 1) {
                            return this.$error("只能选择单条数据");
                        }
                        this.$refs.gridBody.open(rows[0].palletCode);
                        this.refresh();
                    }
                }
      //示例:在按钮的最前面添加一个按钮
      // this.buttons.unshift({
      //   //也可以用push或者splice方法来修改buttons数组
      //   name: '直接出库', //按钮名称
      //   icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档)
      //   type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button
      //   onClick: function () {
      //     this.$Message.success('点击了按钮')
      //     let row = this.$refs.table.getSelected() //获取选中的行
      //     if (row <= 0) {
      //       //如果没有选中行
      //       this.$Message.error('请选择一行数据')
      //       return
      //     }
      //     let locationCode = row[0].locationCode
      //     let palletCode = row[0].palletCode
      //     this.http.get(`/api/Task/CreateAndSendOutboundTask?locationCode=${locationCode}&palletCode=${palletCode}`, {}, "正在创建任务").then((res) => {
      //       //示例:调用后台接口
      //       if (res.status) {
      //         this.$Message.success('创建任务成功')
      //       } else {
      //         this.$Message.error(res.message) //错误提示
      //       }
      //     })
      //   }
      // })
      //示例:设置修改新建、编辑弹出框字段标签的长度
      this.boxOptions.labelWidth = 150
      // this.columns.push({
      //   title: "操作",
      //   field: "操作",
      //   width: 150,
      //   align: "left", // 'center',
      //   render: (h, { row, column, index }) => {
      //     return (
      //       <div>
      //         <el-button
      //           onClick={($e) => {
      //             this.$refs.gridHeader.openModel1(row);
      //           }}
      //           type="primary"
      //           plain
      //           style="height:26px; padding: 10px !important;"
      //         >
      //           æŸ¥çœ‹åº“存明细
      //         </el-button>
      //       </div>
      //     );
      //   },
      // });
      this.columns.forEach((column) => {
        //修改颜色
        if (column.field == 'roadwayNo') {
          column.formatter = (row) => {
            // return '<span style="color: #2d8cf0;">' + row?.locationInfo?.roadwayNo + '</span>'
            return  row?.locationInfo?.roadwayNo
          }
        }
        if (column.field == 'materielCode') {
          column.formatter = (row) => {
            // return '<span style="color: #2d8cf0;">' + row?.locationInfo?.roadwayNo + '</span>'
            return  row?.stockInfoDetails[0]?.materielCode
          }
        }
        //格式化日期
        // æ£€æŸ¥å½“前列的字段是否为 'locationStatus'
        if (column.field == 'locationStatus') {
          // ä½¿ç”¨å¯¹è±¡å­—面量来映射 'locationStatus' çš„值和对应的文本
          const statusMap = {
            '-1': '全部',
            '0': '空闲',
            '1': '锁定',
            '2': '有货',
            '3': '有货禁用',
            '4': '无货禁用'
          };
          // å®šä¹‰ä¸€ä¸ªæ ¼å¼åŒ–函数,根据 'locationStatus' çš„值返回相应的文本
          column.formatter = (row) => {
            // ä½¿ç”¨ statusMap å¯¹è±¡æ¥èŽ·å–å¯¹åº”çš„æ–‡æœ¬ï¼Œå¦‚æžœæ²¡æœ‰åŒ¹é…åˆ™è¿”å›ž '未知状态'
            return statusMap[row?.locationInfo?.locationStatus] || '未知状态';
          }
        }
      })
    },
    onInited() {
      //框架初始化配置后
      //如果要配置明细表,在此方法操作
      this.detailOptions.columns.forEach(column=>{
        console.log(column)
      });
    },
    searchBefore(param) {
      //界面查询前,可以给param.wheres添加查询参数
      //返回false,则不会执行查询
      return true
    },
    searchAfter(result) {
     console.log(result)
      return true
    },
    addBefore(formData) {
      //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
      return true
    },
    updateBefore(formData) {
      //编辑保存前formData为对象,包括明细表、删除行的Id
      return true
    },
    rowClick({ row, column, event }) {
      //查询界面点击行事件
      // this.$refs.table.$refs.table.toggleRowSelection(row) //单击行时选中当前行;
    },
    modelOpenAfter(row) {
      //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
      //(1)判断是编辑还是新建操作: this.currentAction=='Add';
      //(2)给弹出框设置默认值
      //(3)this.editFormFields.字段='xxx';
      //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
      //看不懂就把输出看:console.log(this.editFormOptions)
    }
  }
}
export default extension
CodeManagement/WMS/WIDESEA_WMSClient/src/extension/widesea_wms/stock/Dt_OutTime.jsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
/*****************************************************************************************
 **  Author:jxx 2022
 **  QQ:283591387
 **完整文档见:http://v2.volcore.xyz/document/api ã€ä»£ç ç”Ÿæˆé¡µé¢ViewGrid】
 **常用示例见:http://v2.volcore.xyz/document/vueDev
 **后台操作见:http://v2.volcore.xyz/document/netCoreDev
 *****************************************************************************************/
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
// import gridHeader from "./demo_Product/Dt_BillGroupStockDetail.vue";
import gridBody from "./extend/SupplementationData.vue"
let extension = {
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridBody: gridBody,
    gridFooter: '',
    //新建、编辑弹出框扩展组件
    modelHeader: '',
    modelBody: '',
    modelFooter: ''
  },
  tableAction: '', //指定某张表的权限(这里填写表名,默认不用填写)
  buttons: { view: [], box: [], detail: [] }, //扩展的按钮
  methods: {
    //下面这些方法可以保留也可以删除
    onInit() {
      //框架初始化配置前,
      let OutBoundBtn = this.buttons.find((x) => x.value == 'OutBound')
      if (OutBoundBtn) {
        OutBoundBtn.onClick = function () {
          // this.$Message.success('点击了按钮')
          let row = this.$refs.table.getSelected() //获取选中的行
          if (row <= 0) {
            //如果没有选中行
            this.$Message.error('请选择一行数据')
            return
          }
          let locationCode = row[0].locationCode
          let palletCode = row[0].palletCode
          this.http
            .get(
              `/api/Task/CreateAndSendOutboundTask?locationCode=${locationCode}&palletCode=${palletCode}`,
              {},
              '正在创建任务'
            )
            .then((res) => {
              //示例:调用后台接口
              if (res.status) {
                this.$Message.success('创建任务成功')
                console.log(res)
                this.refresh() //刷新表格
              } else {
                this.$Message.error(res.message) //错误提示
              }
            })
        }
      }
      var btnSupplementationData = this.buttons.find(x => x.value == "SupplementationData");
            if (btnSupplementationData != null) {
                btnSupplementationData.onClick = () => {
                    let rows = this.$refs.table.getSelected();
                        if (rows.length == 0) {
                            return this.$error("请选择数据!");
                        } else if (rows.length > 1) {
                            return this.$error("只能选择单条数据");
                        }
                        this.$refs.gridBody.open(rows[0].palletCode);
                        this.refresh();
                    }
                }
      //示例:在按钮的最前面添加一个按钮
      // this.buttons.unshift({
      //   //也可以用push或者splice方法来修改buttons数组
      //   name: '直接出库', //按钮名称
      //   icon: 'el-icon-document', //按钮图标vue2版本见iview文档icon,vue3版本见element ui文档icon(注意不是element puls文档)
      //   type: 'primary', //按钮样式vue2版本见iview文档button,vue3版本见element ui文档button
      //   onClick: function () {
      //     this.$Message.success('点击了按钮')
      //     let row = this.$refs.table.getSelected() //获取选中的行
      //     if (row <= 0) {
      //       //如果没有选中行
      //       this.$Message.error('请选择一行数据')
      //       return
      //     }
      //     let locationCode = row[0].locationCode
      //     let palletCode = row[0].palletCode
      //     this.http.get(`/api/Task/CreateAndSendOutboundTask?locationCode=${locationCode}&palletCode=${palletCode}`, {}, "正在创建任务").then((res) => {
      //       //示例:调用后台接口
      //       if (res.status) {
      //         this.$Message.success('创建任务成功')
      //       } else {
      //         this.$Message.error(res.message) //错误提示
      //       }
      //     })
      //   }
      // })
      //示例:设置修改新建、编辑弹出框字段标签的长度
      this.boxOptions.labelWidth = 150
      // this.columns.push({
      //   title: "操作",
      //   field: "操作",
      //   width: 150,
      //   align: "left", // 'center',
      //   render: (h, { row, column, index }) => {
      //     return (
      //       <div>
      //         <el-button
      //           onClick={($e) => {
      //             this.$refs.gridHeader.openModel1(row);
      //           }}
      //           type="primary"
      //           plain
      //           style="height:26px; padding: 10px !important;"
      //         >
      //           æŸ¥çœ‹åº“存明细
      //         </el-button>
      //       </div>
      //     );
      //   },
      // });
      this.columns.forEach((column) => {
        //修改颜色
        if (column.field == 'roadwayNo') {
          column.formatter = (row) => {
            // return '<span style="color: #2d8cf0;">' + row?.locationInfo?.roadwayNo + '</span>'
            return  row?.locationInfo?.roadwayNo
          }
        }
        if (column.field == 'materielCode') {
          column.formatter = (row) => {
            // return '<span style="color: #2d8cf0;">' + row?.locationInfo?.roadwayNo + '</span>'
            return  row?.stockInfoDetails[0]?.materielCode
          }
        }
        //格式化日期
        // æ£€æŸ¥å½“前列的字段是否为 'locationStatus'
        if (column.field == 'locationStatus') {
          // ä½¿ç”¨å¯¹è±¡å­—面量来映射 'locationStatus' çš„值和对应的文本
          const statusMap = {
            '-1': '全部',
            '0': '空闲',
            '1': '锁定',
            '2': '有货',
            '3': '有货禁用',
            '4': '无货禁用'
          };
          // å®šä¹‰ä¸€ä¸ªæ ¼å¼åŒ–函数,根据 'locationStatus' çš„值返回相应的文本
          column.formatter = (row) => {
            // ä½¿ç”¨ statusMap å¯¹è±¡æ¥èŽ·å–å¯¹åº”çš„æ–‡æœ¬ï¼Œå¦‚æžœæ²¡æœ‰åŒ¹é…åˆ™è¿”å›ž '未知状态'
            return statusMap[row?.locationInfo?.locationStatus] || '未知状态';
          }
        }
      })
    },
    onInited() {
      //框架初始化配置后
      //如果要配置明细表,在此方法操作
      this.detailOptions.columns.forEach(column=>{
        console.log(column)
      });
    },
    searchBefore(param) {
      //界面查询前,可以给param.wheres添加查询参数
      //返回false,则不会执行查询
      return true
    },
    searchAfter(result) {
     console.log(result)
      return true
    },
    addBefore(formData) {
      //新建保存前formData为对象,包括明细表,可以给给表单设置值,自己输出看formData的值
      return true
    },
    updateBefore(formData) {
      //编辑保存前formData为对象,包括明细表、删除行的Id
      return true
    },
    rowClick({ row, column, event }) {
      //查询界面点击行事件
      // this.$refs.table.$refs.table.toggleRowSelection(row) //单击行时选中当前行;
    },
    modelOpenAfter(row) {
      //点击编辑、新建按钮弹出框后,可以在此处写逻辑,如,从后台获取数据
      //(1)判断是编辑还是新建操作: this.currentAction=='Add';
      //(2)给弹出框设置默认值
      //(3)this.editFormFields.字段='xxx';
      //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
      //看不懂就把输出看:console.log(this.editFormOptions)
    }
  }
}
export default extension
CodeManagement/WMS/WIDESEA_WMSClient/src/router/tables.js
@@ -260,6 +260,13 @@
    meta: {
      keepAlive: false
    }
  },{
    path: '/Dt_BillGroupStock_Hty',
    name: 'Dt_BillGroupStock_Hty',
    component: () => import('@/views/widesea_wms/stock/Dt_BillGroupStock_Hty.vue'),
    meta: {
      keepAlive: false
    }
  },
]
export default tables
CodeManagement/WMS/WIDESEA_WMSClient/src/views/widesea_wms/stock/Dt_BillGroupStock_Hty.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
<!--
*Author:jxx
 *Contact:283591387@qq.com
 *代码由框架生成,任何更改都可能导致被代码生成器覆盖
 *业务请在@/extension/widesea_wms/stock/Dt_BillGroupStock.js此处编写
 -->
<template>
    <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
        :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
        :table="table" :extend="extend">
    </view-grid>
</template>
<script>
import extend from "@/extension/widesea_wms/stock/Dt_BillGroupStock_Hty.jsx";
import { ref, defineComponent } from "vue";
export default defineComponent({
    setup() {
        const table = ref({
            key: 'id',
            footer: "Foots",
            cnName: '库存历史信息',
            name: 'stock/Dt_BillGroupStock_Hty',
            url: "/StockInfoHty/",
            sortName: "createDate"
        });
        const editFormFields = ref({
            "palletCode": "",
            "productionLine": "",
            "outboundTime": "",
            // "groupType": ""
        });
        const editFormOptions = ref([
            [
                { "title": "托盘条码", "field": "palletCode", type: "text" },
                { "title": "生产产线", "field": "productionLine", type: "text" },
                { "title": "应出库时间", "field": "outboundTime", type: "datetime" },
                // { "title": "组盘类型", "field": "groupType", type: "select", dataKey: "GroupType", data: [] },
            ]
        ]);
        const searchFormFields = ref({});
        const searchFormOptions = ref([
            [
                { "title": "托盘条码", "field": "palletCode", type: "text" },
                { "title": "生产产线", "field": "productionLine", type: "select", dataKey: "ProductionLine", data: [] },
                { "title": "库区", "field": "areaCode", type: "select", dataKey: "AreaType", data: [] },
                { "title": "库存类型", "field": "isFull", type: "select", dataKey: "isFull", data: [] },
            ], [
                { "title": "库位号", "field": "locationCode", type: "text" },
                { "title": "巷道", "field": "roadwayNo", type: "text" },
                { "title": "物料编码", "field": "materielCode", type: "text"},
            ]
        ]);
        const columns = ref(
            [{ field: 'id', title: '库存ID', type: 'int', width: 110, hidden: true, readonly: true, require: true, align: 'left' },
            { field: 'locationCode', title: '库位', type: 'string', width: 100, align: 'left', },
            { field: 'palletCode', title: '托盘条码', type: 'string', width: 110, align: 'left', },
            { field: 'isFull', title: '库存类型', type: 'bool', width: 60, align: 'left', bind: { key: "isFull", data: [{ key: false, value: '空盘' }, { key: true, value: '实盘' }] }, },
            { field: 'linedProcessFeedbackTime', title: '工艺开始时间', type: 'string', width: 110, align: 'left', },
            { field: 'roadwayNo', title: '巷道', type: 'string', width: 60, align: 'left', sort: true },
            { field: 'materielCode', title: '物料编码', type: 'string', width: 90, align: 'left', sort: true },
            // { field: 'locationStatus', title: '货位状态', type: 'int', width: 60, align: 'left', bind: { key: "LocationState", data: [] } },
            { field: 'specialParameterDuration', title: '工艺时长', type: 'string', width: 60, align: 'left', sort: true },
            { field: 'outboundTime', title: '应出库时间', type: 'string', width: 110, align: 'left', sort: true },
            { field: 'productionLine', title: '生产产线', type: 'string', width: 60, align: 'left', bind: { key: "ProductionLine", data: [] }  },
            { field: 'areaCode', title: '库区', type: 'string', width: 60, align: 'left', bind: { key: "AreaType", data: [] } },
            { field: 'remark', title: '电芯数量', type: 'string', width: 60, align: 'left', },
            { field: 'creater', title: '创建人', type: 'string', sort: true, width: 110, align: 'left', hidden: true },
            { field: 'createDate', title: '创建时间', type: 'datetime', sort: true, width: 150, align: 'left', },
            { field: 'modifier', title: '最后修改人', type: 'string', sort: true, width: 100, hidden: true, align: 'left' },
                // { field: 'modifyDate', title: '最后修改时间', type: 'datetime', sort: true, width: 150, align: 'left', sort: true },
            ]
        );
        const detail = ref({
            cnName: "#detailCnName",
            table: "#detailTable",
            columns: [],
            sortName: "",
            key: ""
        });
        return {
            table,
            extend,
            editFormFields,
            editFormOptions,
            searchFormFields,
            searchFormOptions,
            columns,
            detail,
        };
    },
});
</script>
CodeManagement/WMS/WIDESEA_WMSClient/src/views/widesea_wms/stock/Dt_OutTime.vue
@@ -7,21 +7,21 @@
 <template>
    <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
        :editFormOptions="editFormOptions" :searchFormFields="searchFormFields"
        :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
        :table="table" :extend="extend">
    </view-grid>
</template>
<script>
import extend from "@/extension/widesea_wms/stock/Dt_BillGroupStock.jsx";
import extend from "@/extension/widesea_wms/stock/Dt_OutTime.jsx";
import { ref, defineComponent } from "vue";
export default defineComponent({
    setup() {
        const table = ref({
            key: 'id',
            footer: "Foots",
            cnName: '超时信息',
            name: 'stock/Dt_BillGroupStock',
            url:"/StockInfoTimeout/",
            cnName: '超时库存信息',
            name: 'stock/StockInfoTimeout',
            url: "/StockInfo/",
            sortName: "createDate"
        });
        const editFormFields = ref({
@@ -49,18 +49,18 @@
                { "title": "库位号", "field": "locationCode", type: "text" },
                { "title": "巷道", "field": "roadwayNo", type: "text" },
                { "title": "货位状态", "field": "locationStatus", type: "select", dataKey: "LocationState", data: [] },
                { "title": "出库时间", "field": "outboundTime", type: "datetime"},
                { "title": "物料编码", "field": "materielCode", type: "text"},
            ]
        ]);
        const now = new Date();
        // ç›´æŽ¥å‡åŽ» 3 å°æ—¶ï¼ˆå¯èƒ½è·¨å¤©ï¼ŒDate å¯¹è±¡ä¼šè‡ªåŠ¨å¤„ç†ï¼‰
        now.setHours(now.getHours() - 3);
        const columns = ref(
            [{ field: 'id', title: '库存ID', type: 'int', width: 110, hidden: true, readonly: true, require: true, align: 'left' },
            { field: 'locationCode', title: '库位', type: 'string', width: 100, align: 'left', },
            { field: 'palletCode', title: '托盘条码', type: 'string', width: 110, align: 'left', },
            { field: 'isFull', title: '库存类型', type: 'bool', width: 80, align: 'left', bind: { key: "isFull", data: [{ key: false, value: '空盘' }, { key: true, value: '实盘' }] }, },
            { field: 'isFull', title: '库存类型', type: 'bool', width: 60, align: 'left', bind: { key: "isFull", data: [{ key: false, value: '空盘' }, { key: true, value: '实盘' }] }, },
            { field: 'linedProcessFeedbackTime', title: '工艺开始时间', type: 'string', width: 110, align: 'left', },
            { field: 'roadwayNo', title: '巷道', type: 'string', width: 60, align: 'left', sort: true },
            { field: 'materielCode', title: '物料编码', type: 'string', width: 90, align: 'left', sort: true },
            { field: 'locationStatus', title: '货位状态', type: 'int', width: 60, align: 'left', bind: { key: "LocationState", data: [] } },
            { field: 'specialParameterDuration', title: '工艺时长', type: 'string', width: 60, align: 'left', sort: true },
            { field: 'outboundTime', title: '应出库时间', type: 'string', width: 110, align: 'left', sort: true },
            { field: 'productionLine', title: '生产产线', type: 'string', width: 60, align: 'left', bind: { key: "ProductionLine", data: [] }  },
@@ -72,7 +72,6 @@
                // { field: 'modifyDate', title: '最后修改时间', type: 'datetime', sort: true, width: 150, align: 'left', sort: true },
            ]
        );
        const detail = ref({
            cnName: "#detailCnName",
            table: "#detailTable",
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_IStorageBasicRepository/Stock/IStockInfoHtyRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
namespace WIDESEA_IStorageBasicRepository
{
    public interface IStockInfoHtyRepository : IRepository<DtStockInfo_Hty>
    {
    }
}
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_IStorageBasicService/Stock/IStockInfoHtyvice.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
namespace WIDESEA_IStorageBasicService;
public interface IStockInfoHtyService : IService<DtStockInfo_Hty>
{
}
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_StorageBasicRepository/Stock/StockInfoHtyRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
namespace WIDESEA_StorageBasicRepository
{
    public class StockInfoHtyRepository : RepositoryBase<DtStockInfo_Hty>, IStockInfoHtyRepository
    {
        public StockInfoHtyRepository(IUnitOfWorkManage unitOfWorkManage) : base(unitOfWorkManage)
        {
        }
    }
}
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_StorageBasicServices/Stock/StockInfoHtyService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,158 @@
using AngleSharp.Dom;
using Mapster;
using Masuit.Tools;
using SqlSugar;
using System.Collections;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq.Expressions;
using System.Threading.Tasks;
using WIDESEA_Cache;
using WIDESEA_Common;
using WIDESEA_Core;
namespace WIDESEA_StorageBasicService;
public class StockInfoHtyService : ServiceBase<DtStockInfo_Hty, IStockInfoHtyRepository>, IStockInfoHtyService
{
    private readonly ISimpleCacheService _simpleCacheService;
    private readonly ILocationStatusChangeRecordRepository _locationStatusChangeRecordRepository;
    public StockInfoHtyService(IStockInfoHtyRepository BaseDal, ISimpleCacheService simpleCacheService, ILocationStatusChangeRecordRepository locationStatusChangeRecordRepository) : base(BaseDal)
    {
        _simpleCacheService = simpleCacheService;
        _locationStatusChangeRecordRepository = locationStatusChangeRecordRepository;
    }
    /// <summary>
    /// åˆ†é¡µ
    /// </summary>
    /// <param name="options"></param>
    /// <returns></returns>
    public override PageGridData<DtStockInfo_Hty> GetPageData(PageDataOptions options)
    {
        string wheres = ValidatePageOptions(options);
        //获取排序字段
        Dictionary<string, SqlSugar.OrderByType> orderbyDic = GetPageDataSort(options, TProperties);
        List<OrderByModel> orderByModels = new List<OrderByModel>();
        foreach (var item in orderbyDic)
        {
            OrderByModel orderByModel = new()
            {
                FieldName = item.Key,
                OrderByType = item.Value
            };
            orderByModels.Add(orderByModel);
        }
        int totalCount = 0;
        List<SearchParameters> searchParametersList = new List<SearchParameters>();
        if (!string.IsNullOrEmpty(options.Wheres))
        {
            try
            {
                searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>();
                options.Filter = searchParametersList;
            }
            catch { }
        }
        Expression<Func<DtStockInfo_Hty, bool>> locationStatus = null;
        Expression<Func<DtStockInfo_Hty, bool>> roadwayNo = null;
        Expression<Func<DtStockInfo_Hty, bool>> materielCode = null;
        foreach (var item in searchParametersList)
        {
            if (item.Name.Contains("locationStatus"))
            {
                locationStatus = x => x.LocationInfo.LocationStatus == Convert.ToInt32(item.Value);
            }
            else if (item.Name.Contains("roadwayNo"))
            {
                roadwayNo = x => x.LocationInfo.RoadwayNo.Contains(item.Value);
            }
            else if (item.Name.Contains("materielCode"))
            {
                materielCode = x => x.StockInfoDetails.Any(d => d.MaterielCode.Contains(item.Value));
            }
        }
        //.IncludesAllFirstLayer()
        var data = BaseDal.Db.Queryable<DtStockInfo_Hty>()
            .Includes(x => x.StockInfoDetails)
            .Includes(x => x.LocationInfo)
            .WhereIF(!wheres.IsNullOrEmpty(), wheres)
            .WhereIF(locationStatus != null, locationStatus)
            .WhereIF(roadwayNo != null, roadwayNo)
            .WhereIF(materielCode != null, materielCode)
            .OrderBy(orderByModels)
            .ToPageList(options.Page, options.Rows, ref totalCount);
        return new PageGridData<DtStockInfo_Hty>(totalCount, data);
    }
    /// <summary>
    /// æ‰¹é‡åˆ é™¤
    /// </summary>
    /// <param name="keys"></param>
    /// <returns></returns>
    public override WebResponseContent DeleteData(object[] keys)
    {
        try
        {
            List<DtStockInfo_Hty> stockInfos = new List<DtStockInfo_Hty>();
            List<DtLocationInfo> locationInfos = new List<DtLocationInfo>();
            var stocks = new List<string>();
            foreach (var item in keys)
            {
                var stock = BaseDal.QueryFirstNavAsync(x => x.Id == item.ObjToInt()).Result;
                var stockHty = stock.Adapt<DtStockInfo_Hty>();
                stockInfos.Add(stockHty);
                var location = SqlSugarHelper.DbWMS.Queryable<DtLocationInfo>().FirstAsync(x => x.Id == stock.LocationId).Result;
                var lastStatus = location.LocationStatus;
                location.LocationStatus = (int)LocationEnum.Free;
                locationInfos.Add(location);
                stocks.Add(stock.PalletCode);
                _locationStatusChangeRecordRepository.AddLocationStatusChangeRecord(location, lastStatus, (int)StatusChangeTypeEnum.ManualOperation, 0);
            }
            //_simpleCacheService.HashDel<DtStockInfo>(CacheConst.Cache_DtStockInfo, stocks.ToArray());
            //var hty = BaseDal.Db.InsertNav(stockInfos)
            //    .Include(x => x.StockInfoDetails)
            //    .ExecuteCommand();
            //var locationd = SqlSugarHelper.DbWMS.Updateable(locationInfos).ExecuteCommandHasChange();
            //return base.DeleteData(keys);
            var hty = BaseDal.Db.InsertNav(stockInfos)
                .Include(x => x.StockInfoDetails)
                .ExecuteCommand();
            var locationd = SqlSugarHelper.DbWMS.Updateable(locationInfos).ExecuteCommandHasChange();
            return base.DeleteData(keys);
        }
        catch (Exception ex)
        {
            return WebResponseContent.Instance.Error(ex.Message);
        }
    }
    // æ ¹æ®ä¼ å…¥åº“存类型获取不同巷道的库存
    public async Task<Dictionary<string, int>> GetLocationByStockType(bool stockType, string areaCode)
    {
        var stockInfos = await BaseDal.Db.Queryable<DtStockInfo>().Where(x => x.IsFull == stockType && x.AreaCode == areaCode)
            .Includes(x => x.LocationInfo).ToListAsync();
        var result = stockInfos
            .GroupBy(x => x.LocationInfo.RoadwayNo)
            .ToDictionary(x => x.Key, x => x.Count());
        return result;
    }
    //public override WebResponseContent UpdateData(DtStockInfo entity)
    //{
    //    return base.UpdateData(entity);
    //}
}
CodeManagement/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/StockInfoHtyController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
using WIDESEA_IStorageBasicService;
namespace WIDESEA_WMSServer.Controllers;
[Route("api/StockInfoHty")]
[ApiController]
public class StockInfoHtyController : ApiBaseController<IStockInfoHtyService, DtStockInfo_Hty>
{
    public StockInfoHtyController(IStockInfoHtyService service) : base(service)
    {
    }
}