647556386
2 天以前 2f8fc989f339a936b01092caebd4c46e6109da1b
代码提交
已添加5个文件
已修改22个文件
1772 ■■■■ 文件已修改
WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/板材仓/ConveyorLineJob_BC.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/板材仓/RGVJob_BC.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/methods.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/views/Home.vue 388 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseModels/WebResponseContent.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_DTO/Basic/LocationArea.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockViewDTO.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockViewService.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_ISystemRepository/ISys_RoleDataPermissionRepository.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_InboundService/Base/InboundOrderService.cs 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_InboundService/Base/TakeStockOrderService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/System/Sys_RoleDataPermission.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/Service/OutboundOrderDetailService.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockViewService.cs 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockInfoService.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_SystemRepository/Sys_RoleDataPermissionRepository.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/PartialTaskService_Inbound.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 348 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/LocationInfoRowController.cs 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockViewController.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
吉安PDA/pages/stash/TakeStockOrder.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/°å²Ä²Ö/ConveyorLineJob_BC.cs
@@ -148,7 +148,7 @@
                                    }
                                    else
                                    {
                                        Dt_Task task = _taskRepository.QueryFirst(x => x.SourceAddress == item.StationCode && x.DeviceCode == item.StationDeviceCode && x.TaskState == TaskStatusEnum.RGV_Finish.ObjToInt());
                                        Dt_Task task = _taskRepository.QueryFirst(x => x.SourceAddress == item.StationCode && x.DeviceCode == item.StationDeviceCode && x.TaskState == TaskStatusEnum.RGV_Finish.ObjToInt() && x.TaskNum == conveyorLineInfoRead.TaskNo);
                                        if (task != null)
                                        {
                                            _taskService.UpdateTask(task, TaskStatusEnum.SC_Execute, deviceCode: task.Roadway, sourceAddress: item.StackerCraneStationCode);
@@ -212,12 +212,20 @@
                                            if (!conveyorLineSignalRead3.STB && !conveyorLineSignalRead3.ACK && conveyorLineStatus3.Online && conveyorLineStatus3.Free && !conveyorLineStatus3.Goods && !conveyorLineStatus3.Alarm && !STB && !ACK)//判断出库口是否空闲
                                            {
                                                Dt_Task task = _taskRepository.QueryFirst(x => x.CurrentAddress == item.StationCode && x.DeviceCode == device.DeviceCode && x.TaskState == TaskStatusEnum.Line_Execute.ObjToInt());
                                                if (task != null)
                                                Dt_Task outTask = _taskRepository.QueryFirst(x => x.TaskType >= TaskTypeEnum.Outbound.ObjToInt() && x.TaskType <= TaskTypeEnum.Inbound.ObjToInt() && (x.TaskState == TaskStatusEnum.RGV_Executing.ObjToInt()|| x.TaskState == TaskStatusEnum.RGV_Execute.ObjToInt()));
                                                if (outTask == null)
                                                {
                                                    _taskService.UpdateTask(task, TaskStatusEnum.RGV_Execute, sourceAddress: item.StationCode, targetAddress: routers.NextPosi, nextAddress: routers.NextPosi);
                                                    Thread.Sleep(100);
                                                    device.SetValue(W_ConveyorLineDB.ACK, true, item.StationCode);
                                                    Dt_Task task = _taskRepository.QueryFirst(x => x.CurrentAddress == item.StationCode && x.DeviceCode == device.DeviceCode && x.TaskState == TaskStatusEnum.Line_Execute.ObjToInt());
                                                    if (task != null)
                                                    {
                                                        _taskService.UpdateTask(task, TaskStatusEnum.RGV_Execute, sourceAddress: item.StationCode, targetAddress: routers.NextPosi, nextAddress: routers.NextPosi);
                                                        Thread.Sleep(100);
                                                        for (int i = 0; i < 3; i++)
                                                        {
                                                            device.SetValue(W_ConveyorLineDB.ACK, true, item.StationCode);
                                                        }
                                                        WriteDebug("板材输送出库口", $"出库输送线ACK信号{item.StationCode}已写入,任务号{task.TaskNum}");
                                                    }
                                                }
                                            }
                                        }
WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/°å²Ä²Ö/RGVJob_BC.cs
@@ -100,37 +100,52 @@
                                    _taskService.TaskCompleted(task.TaskNum);
                                }
                                device.SetValue(W_ConveyorLineDB.ACK, true, item.StationCode);
                                for (int i = 0; i < 3; i++)
                                {
                                    device.SetValue(W_ConveyorLineDB.ACK, true, item.StationCode);
                                    Thread.Sleep(100);
                                }
                            }
                        }
                        WriteDebug("RGV状态读取日志", $"联机?:{device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Online)},空闲?{device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Free)},无货?{!device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Goods)},任务号为0?{device.GetValue<R_ConveyorLineDB, int>(R_ConveyorLineDB.TaskNum) == 0},无故障{!device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Alarm)}");
                        if (device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Online) && device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Free) && !device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Goods) && device.GetValue<R_ConveyorLineDB, int>(R_ConveyorLineDB.TaskNum) == 0 && !device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.Alarm))
                        {
                            Dt_Task task = _taskRepository.QueryFirst(x => x.TaskType >= TaskTypeEnum.Inbound.ObjToInt() && x.TaskState == TaskStatusEnum.RGV_NEW.ObjToInt());
                            if (task != null)
                            {
                                //写入RGV任务
                                device.SetValue(W_ConveyorLineDB.TaskNo, task.TaskNum, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.StartPos, task.SourceAddress, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.TaskType, 2, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.EndPos, task.NextAddress, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.STB, true, item.StationCode);
                                _taskService.UpdateTask(task, TaskStatusEnum.RGV_Executing);
                                //写入RGV入库任务
                                for (int i = 0; i < 3; i++)
                                {
                                    device.SetValue(W_ConveyorLineDB.TaskNo, task.TaskNum, item.StationCode);
                                    device.SetValue(W_ConveyorLineDB.StartPos, task.SourceAddress, item.StationCode);
                                    device.SetValue(W_ConveyorLineDB.TaskType, 2, item.StationCode);
                                    device.SetValue(W_ConveyorLineDB.EndPos, task.NextAddress, item.StationCode);
                                    device.SetValue(W_ConveyorLineDB.STB, true, item.StationCode);
                                    _taskService.UpdateTask(task, TaskStatusEnum.RGV_Executing);
                                }
                                WriteDebug(device.DeviceName, $"入库RGV任务号{task.TaskNum}已写入");
                            }
                            Dt_Task task1 = _taskRepository.QueryFirst(x => x.TaskType >= TaskTypeEnum.Outbound.ObjToInt()&&  x.TaskType <= TaskTypeEnum.Inbound.ObjToInt() && x.TaskState == TaskStatusEnum.RGV_Execute.ObjToInt());
                            if (task1 != null)
                            else
                            {
                                //写入RGV任务
                                device.SetValue(W_ConveyorLineDB.TaskNo, task1.TaskNum, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.StartPos, task1.SourceAddress, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.TaskType, 2, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.EndPos, task1.NextAddress, item.StationCode);
                                device.SetValue(W_ConveyorLineDB.STB, true, item.StationCode);
                                _taskService.UpdateTask(task1, TaskStatusEnum.RGV_Executing);
                                WriteDebug(device.DeviceName, $"出库RGV任务号{task1.TaskNum}已写入");
                                Dt_Task task1 = _taskRepository.QueryFirst(x => x.TaskType >= TaskTypeEnum.Outbound.ObjToInt() && x.TaskType <= TaskTypeEnum.Inbound.ObjToInt() && x.TaskState == TaskStatusEnum.RGV_Execute.ObjToInt());
                                //写入RGV出库任务
                                if (task1 != null)
                                {
                                    for (int i = 0; i < 3; i++)
                                    {
                                        device.SetValue(W_ConveyorLineDB.TaskNo, task1.TaskNum, item.StationCode);
                                        device.SetValue(W_ConveyorLineDB.StartPos, task1.SourceAddress, item.StationCode);
                                        device.SetValue(W_ConveyorLineDB.TaskType, 2, item.StationCode);
                                        device.SetValue(W_ConveyorLineDB.EndPos, task1.NextAddress, item.StationCode);
                                        device.SetValue(W_ConveyorLineDB.STB, true, item.StationCode);
                                    }
                                    _taskService.UpdateTask(task1, TaskStatusEnum.RGV_Executing);
                                    WriteDebug(device.DeviceName, $"出库RGV任务号{task1.TaskNum}已写入");
                                }
                            }
                        }
                        if (device.GetValue<R_ConveyorLineDB, bool>(R_ConveyorLineDB.ACK))
WMS/WIDESEA_WMSClient/src/components/basic/ViewGrid/methods.js
@@ -867,6 +867,7 @@
    this.modelOpenProcess(row);
  },
  setContinueAdd(isAdd) {
    console.log(this.boxButtons)
    if (!this.continueAdd) return;
    var _button = this.boxButtons.find((x) => {
      return x.value == 'save';
WMS/WIDESEA_WMSClient/src/views/Home.vue
@@ -1,24 +1,392 @@
<template>
  <div class="title"></div>
  <div class="container">
    <div class="header">
      <h2 class="title">货位排图</h2>
    </div>
    <div class="content-wrapper">
      <!-- æŽ§åˆ¶é¢æ¿åŒºåŸŸ -->
      <div class="control-panel">
        <div class="form-group">
          <label>区域:</label>
          <el-select
            size="mini"
            filterable
            v-model="Area.shelf_code"
            placeholder="请选择"
            class="full-width"
          >
            <el-option
              v-for="item in slectData"
              :value="item.shelf_code"
              :label="item.house_name"
              :key="item.house_name"
            ></el-option>
          </el-select>
        </div>
        <div class="form-group">
          <label>排:</label>
          <el-select
            size="mini"
            clearable
            filterable
            @change="SCChange"
            v-model="Area.tunnel"
            placeholder="请选择"
            class="full-width"
          >
            <el-option
              v-for="item in scList"
              :value="item"
              :label="item"
              :key="item"
            ></el-option>
          </el-select>
        </div>
        <el-button type="success" class="refresh-btn" @click="GetViewData">
          åˆ·æ–°
        </el-button>
        <div class="legend-section">
          <h4>说明</h4>
          <div class="legend-grid">
            <div
              class="legend-item"
              v-for="item in infoMsg"
              :key="item.bgcolor"
            >
              <span
                class="color-box"
                :style="{ 'background-color': item.bgcolor }"
              ></span>
              <span class="legend-label">{{ item.msg }}</span>
            </div>
          </div>
        </div>
      </div>
      <!-- è´§ä½å±•示区域 -->
      <div class="location-view">
        <div
          class="layer-container"
          v-for="layer in locationData"
          :key="layer.index"
        >
          <h3 class="layer-title">第{{ layer.index }}层</h3>
          <div class="row" v-for="row in layer.rows" :key="row.index">
            <div
              class="location-cell"
              :style="{ 'background-color': GetBgColor(col) }"
              v-for="col in row.cols"
              :key="col.index"
              @mouseenter="showTooltip(col, $event)"
              @mouseleave="hideTooltip"
            >
              {{ row.index }}-{{ col.index }}-{{ layer.index }}
            </div>
          </div>
        </div>
      </div>
      <!-- æ‚¬æµ®æç¤ºæ¡† -->
      <div
        v-if="showTooltipFlag"
        class="location-tooltip"
        :style="{
          left: tooltipPosition.x + 'px',
          top: tooltipPosition.y + 'px',
        }"
      >
        <div v-if="currentLocation">
          <p><strong>货位号:</strong>{{ currentLocation.locationCode }}</p>
          <p>
            <strong>货位排列层:</strong> {{ currentLocation.row }}排{{
              currentLocation.index
            }}列{{ currentLocation.layer }}层
          </p>
          <p><strong>状态:</strong> {{ getStatusText(currentLocation) }}</p>
          <p>
            <strong>禁用:</strong>
            {{ currentLocation.location_lock == 3 ? "是" : "否" }}
          </p>
          <!-- æ¢å¤ç‰©æ–™ä¿¡æ¯æ˜¾ç¤ºï¼Œé€‚配有货状态 -->
          <p v-if="currentLocation.location_state === 2">
            <strong>物料编码:</strong>
            {{ currentLocation.material_code || "无" }}
          </p>
          <p v-if="currentLocation.location_state === 2">
            <strong>数量:</strong> {{ currentLocation.quantity || "无" }}
          </p>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { ref, reactive } from 'vue'
import { ElButton } from "element-plus";
export default {
  setup() {
  data() {
    return {
      slectData: [],
      scList: [],
      Area: { house_name: "", tunnel: "", shelf_code: "" },
      mian_height: "",
      infoMsg: [
        { bgcolor: "lightgreen", msg: "空货位", state: 0 },
        { bgcolor: "orange", msg: "有货", state: 2 }, // å…³é”®æ”¹ï¼šstate从100→2
        { bgcolor: "#2BB3D5", msg: "锁定", state: "InAssigned" },
        { bgcolor: "#ccc", msg: "禁用", state: 3 },
        { bgcolor: "#b7ba6b", msg: "其它", state: "else" },
      ],
      locationData: [],
      showTooltipFlag: false,
      currentLocation: null,
      tooltipPosition: { x: 0, y: 0 },
    };
  },
  computed: {
    GetBgColor() {
      return (col) => {
        var bgColor = "#b7ba6b";
        //优先显示禁用状态
        if (col.location_lock == 3) {
          this.infoMsg.forEach((el) => {
            if (el.state == col.location_lock) {
              bgColor = el.bgcolor;
            }
          });
        } else {
          this.infoMsg.forEach((el) => {
            // å…³é”®æ”¹ï¼šåŒ¹é…æœ‰è´§çŠ¶æ€ï¼ˆ2),而非100
            if (col.location_state === 2) {
              bgColor = this.infoMsg.find(item => item.state === 2).bgcolor;
            }
            // é”å®šçŠ¶æ€ï¼ˆ1/10/20/99)逻辑保持不变
            else if (col.location_state > 0 && col.location_state < 100) {
              if (el.state == "InAssigned") {
                bgColor = el.bgcolor;
              }
            }
            // ç©ºè´§ä½ï¼ˆ0)逻辑保持不变
            else if (el.state == col.location_state) {
              bgColor = el.bgcolor;
            }
          });
        }
        return bgColor;
      };
    },
  },
  watch: {
    //切换库区
    "Area.shelf_code"(newValue, oldValue) {
      this.scList = [];
      this.slectData.forEach((e) => {
        if (e.shelf_code == newValue) {
          this.Area.tunnel = e.tunnel[0];
          this.scList = e.tunnel;
        }
      });
      this.GetViewData();
    },
  },
  methods: {
    GetViewData() {
      var _this = this;
      this.http
        .post("/api/LocationInfoRow/GetLocationStatu", _this.Area, "查询中")
        .then((x) => {
          _this.locationData = x;
          console.log("后端返回:", x);
        });
    },
    // åˆ‡æ¢æŽ’
    SCChange() {
      this.GetViewData();
    },
    showTooltip(location, event) {
      this.currentLocation = location;
      this.showTooltipFlag = true;
    }
  }
}
      // è®¾ç½®æç¤ºæ¡†ä½ç½®ï¼Œç¨å¾®åç§»é¿å…é®æŒ¡é¼ æ ‡
      this.tooltipPosition = {
        x: event.clientX + 10,
        y: event.clientY + 10,
      };
    },
    hideTooltip() {
      this.showTooltipFlag = false;
      this.currentLocation = null;
    },
    getStatusText(location) {
      // å…³é”®æ”¹ï¼šæ˜Žç¡®åŒ¹é…æœ‰è´§çŠ¶æ€ï¼ˆ2)
      if (location.location_state === 2) return "有货";
      if (location.location_state === 0) return "空货位";
      if (location.location_state === 1) return "锁定";
      if (location.location_state === 10) return "有货锁定";
      if (location.location_state === 20) return "空闲锁定";
      if (location.location_state === 99) return "大托盘锁定";
      return "其他";
    },
  },
  mounted() {
    var mainHeight = document.getElementById("vol-main");
    this.mian_height = mainHeight.offsetHeight - 40 + "px";
    var _this = this;
    //加载下拉选项
    this.http.get("/api/LocationInfoRow/GetArea", {}, "查询中").then((x) => {
      _this.slectData = x;
      //加载第一个区域,第一排
      _this.Area.shelf_code = _this.slectData[0].shelf_code;
      _this.scList = _this.slectData[0].tunnel;
    });
  },
  components: { ElButton },
};
</script>
<style scoped>
.title {
  line-height: 70vh;
/* æ ·å¼éƒ¨åˆ†æ— ä¿®æ”¹ï¼Œä¿æŒåŽŸé€»è¾‘ */
.container {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 10px;
}
.header {
  text-align: center;
  font-size: 28px;
  color: orange;
  margin-bottom: 20px;
}
.title {
  font-size: 20px;
  font-weight: bold;
  margin: 0;
}
.content-wrapper {
  display: flex;
  flex: 1;
  min-height: 0;
}
.control-panel {
  width: 220px;
  padding: 15px;
  background-color: #f5f7fa;
  border-radius: 4px;
  margin-right: 15px;
  display: flex;
  flex-direction: column;
}
.form-group {
  margin-bottom: 15px;
}
.full-width {
  width: 100%;
}
.refresh-btn {
  margin-top: 10px;
  width: 100%;
}
.legend-section {
  margin-top: 30px;
}
.legend-section h4 {
  margin-bottom: 10px;
}
.legend-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.legend-item {
  display: flex;
  align-items: center;
}
.color-box {
  display: inline-block;
  width: 20px;
  height: 20px;
  margin-right: 8px;
  border-radius: 3px;
}
.legend-label {
  font-size: 13px;
}
.location-view {
  flex: 1;
  overflow: auto;
  padding: 10px;
  background-color: white;
  border-radius: 4px;
}
.layer-container {
  margin-bottom: 25px;
}
.layer-title {
  margin: 0 0 10px 0;
  font-size: 16px;
  color: #333;
}
.row {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 8px;
  cursor: pointer;
}
.location-cell {
  width: 66px;
  height: 38px;
  margin: 3px;
  text-align: center;
  font-size: 14px;
  border-radius: 3px;
  line-height: 38px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.location-tooltip {
  position: fixed;
  z-index: 9999;
  background-color: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  pointer-events: none;
  max-width: 250px;
}
.location-tooltip p {
  margin: 5px 0;
  font-size: 13px;
  line-height: 1.4;
}
.location-tooltip strong {
  display: inline-block;
  width: 70px;
  color: #666;
}
</style>
WMS/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue
@@ -28,7 +28,7 @@
    });
    const editFormFields = ref({
      orderType: "",
      orderNo:"",
      orderNo: "",
      upperOrderNo: "",
      remark: "",
    });
@@ -46,16 +46,16 @@
          field: "warehouseId",
          title: "仓库ID",
          type: "select",
          dataKey:"warehouses",
          data:[]
          dataKey: "warehouses",
          data: [],
        },
        {
          field: "orderNo",
          title: "单据编号",
          type: "string",
          readonly:true
          readonly: true,
        },
                {
        {
          title: "单据状态",
          field: "orderStatus",
          type: "select",
@@ -66,9 +66,8 @@
          title: "上游单据编号",
          field: "upperOrderNo",
          type: "string",
          readonly:true
          readonly: true,
        },
      ],
      [
        {
@@ -82,6 +81,20 @@
          title: "备注",
          field: "remark",
          type: "textarea",
        },
        {
          field: "inoutType",
          title: "出入库类型",
          type: "select",
          dataKey:"inoutTypeEnum",
          data:[],
          readonly:true
        },
        {
          field: "system",
          title: "单据来源",
          type: "string",
          readonly:true
        },
      ],
    ]);
@@ -158,9 +171,9 @@
        type: "string",
        width: 120,
        align: "left",
        bind:{key:"warehouses",data:[]}
        bind: { key: "warehouses", data: [] },
      },
      {
        field: "orderNo",
        title: "单据编号",
@@ -204,9 +217,16 @@
        field: "createType",
        title: "创建方式",
        type: "string",
        width: 90,
        width: 120,
        align: "left",
        bind: { key: "createType", data: [] },
      },
      {
        field: "system",
        title: "单据来源",
        type: "string",
        width: 90,
        align: "left",
      },
      {
        field: "creater",
@@ -297,8 +317,7 @@
          type: "string",
          width: 130,
          align: "left",
          readonly:true,
          readonly: true,
        },
        {
          field: "orderQuantity",
WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
@@ -98,13 +98,14 @@
          dataKey: "stockStatusEmun",
          data: [],
        },
        { title: "库存编号",
        { title: "关联库存编号",
            field: "id",
            type: "like",
        },
        { title: "创建时间", field: "createDate", type: "datetime" },
        ],
        [
        { title: "创建时间", field: "createDate", type: "datetime" },
        ]
      ]);
      const columns = ref([
@@ -131,7 +132,7 @@
          field: "palletCode",
          title: "托盘编号",
          type: "string",
          width: 90,
          width: 150,
          align: "left",
          //sort:true,
        },
@@ -148,7 +149,7 @@
          field: "locationCode",
          title: "货位编号",
          type: "string",
          width: 150,
          width: 200,
          align: "left",
          //sort:true,
        },
@@ -193,6 +194,7 @@
          width: 150,
          align: "left",
        //  sort:true,
          hidden:true,
        },{
          field: "remark",
          title: "备注",
WMS/WIDESEA_WMSClient/src/views/stock/stockInfoDetail.vue
@@ -66,10 +66,12 @@
        { title: "物料编号", field: "materielCode",type :"like"},
        { title: "物料名称", field: "materielName",type :"like"},
        { title: "单据编号", field: "orderNo",type :"like"},
        { title: "关联库存编号", field: "stockId",type :"int"},
      ],
      [
        { title: "批次号", field: "batchNo",type :"like"},
        {title: "库存明细状态",field: "status",type: "select",dataKey:"stockStatusEmun", data: []},
        { title: "供应商批次", field: "supplierBatch",type :"like"},
        { title: "创建日期",field: "createDate",type: "datetime"},
      ],
    ]);
@@ -109,14 +111,6 @@
        // sort:true,
      },
      {
        field: "orderNo",
        title: "物料详情",
        type: "decimal",
        width: 90,
        align: "left",
        // sort:true,
      },
      {
        field: "batchNo",
        title: "物料批次",
        type: "string",
@@ -124,29 +118,27 @@
        align: "left",
        // sort:true,
      },
      // {
      //   field: "serialNumber",
      //   title: "包号",
      //   type: "string",
      //   width: 50,
      //   align: "left",
      //   sort:true,
      //   },
      // {
      //   field: "batchNoName",
      //   title: "物料批次详情",
      //   type: "int",
      //   width: 120,
      //   align: "left",
      //   // sort:true,
      // },
      {
        field: "orderNo",
        title: "单据编号",
        type: "string",
        width: 180,
        align: "left",
      },
      {
        field: "supplierBatch",
        title: "供应商批次",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "stockQuantity",
        title: "重量",
        title: "物料数量",
        type: "string",
        width: 80,
        align: "left",
        // sort:true,
      },
      {
        field: "status",
@@ -154,7 +146,6 @@
        type: "string",
        width: 120,
        align: "left",
        // sort:true,
        bind: { key: "stockStatusEmun", data: [] },
      },
      {
WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue
@@ -31,27 +31,43 @@
      locationCode: "",
      locationName: "",
    });
    const editFormOptions = ref([
    ]);
    const editFormOptions = ref([]);
    const searchFormFields = ref({
      palletCode: "",
      // locationCode: "",
      materielCode:"",
      batchNo:""
      materielCode: "",
      batchNo: "",
    });
    const searchFormOptions = ref([
      [
        { title: "托盘编号", field: "palletCode",type: "like" },
        { title: "货位编号", field: "locationCode",type: "like" },
        { title: "货位状态", field: "locationStatus" ,type: "selectList",dataKey: "locationStatusEnum",data: [],},
        { title: "库存状态", field: "stockStatus",type: "select",dataKey: "stockStatusEmun",data: [],},
        { title: "托盘编号", field: "palletCode", type: "like" },
        { title: "货位编号", field: "locationCode", type: "like" },
        {
          title: "货位状态",
          field: "locationStatus",
          type: "selectList",
          dataKey: "locationStatusEnum",
          data: [],
        },
        {
          title: "库存状态",
          field: "stockStatus",
          type: "select",
          dataKey: "stockStatusEmun",
          data: [],
        },
      ],
      [
        { title: "物料编号", field: "materielCode",type: "like"},
        { title: "批次号", field: "batchNo",type: "like"},
        { title: "所属仓库", field: "warehouseId",type: "select",dataKey: "warehouses",data: [],},
        { title: "库存创建时间",field: "createDate",type: "datetime"},
        { title: "物料编号", field: "materielCode", type: "like" },
        { title: "批次号", field: "batchNo", type: "like" },
        {
          title: "所属仓库",
          field: "warehouseId",
          type: "select",
          dataKey: "warehouses",
          data: [],
        },
        { title: "库存创建时间", field: "createDate", type: "datetime" },
      ],
    ]);
    const columns = ref([
@@ -101,7 +117,7 @@
        type: "decimal",
        width: 100,
        align: "left",
        hidden:true
        hidden: true,
      },
      {
        field: "materielCode",
@@ -115,7 +131,7 @@
        title: "所含物料批次",
        type: "string",
        width: 200,
        align: "left"
        align: "left",
      },
      {
        field: "sumStock",
@@ -171,7 +187,7 @@
        type: "string",
        width: 100,
        align: "left",
        bind:{key: "locationTypeEnum", data: []}
        bind: { key: "locationTypeEnum", data: [] },
      },
      {
        field: "locationStatus",
@@ -223,7 +239,7 @@
        type: "string",
        width: 100,
        align: "left",
        hidden:true
        hidden: true,
      },
    ]);
    const detail = ref({
@@ -241,89 +257,48 @@
          align: "left",
        },
        {
          field: "stockId",
          title: "库存信息主键",
          type: "string",
          width: 90,
          align: "left",
          hidden: true
        },
        {
          field: "materielCode",
          title: "物料编号",
          type: "string",
          width: 110,
          width: 150,
          align: "left",
          // sort:true,
        },
        {
          field: "materielName",
          title: "物料名称",
          type: "string",
          width: 130,
          width: 150,
          align: "left",
          // sort:true,
        },
        {
          field: "batchNo",
          title: "物料批次",
          type: "string",
          width: 120,
          align: "left",
          // sort:true,
        },
        {
          field: "orderNo",
          title: "单据编号",
          type: "decimal",
          width: 130,
          align: "left",
        },
        {
          field: "batchNo",
          title: "批次号",
          type: "string",
          width: 180,
          align: "left",
        },
        {
          field: "materielSpec",
          title: "规格型号",
          field: "supplierBatch",
          title: "供应商批次",
          type: "string",
          width: 180,
          width: 150,
          align: "left",
        },
        {
          field: "serialNumber",
          title: "序列号",
          type: "int",
          width: 120,
          align: "left",
          hidden: true,
        },
        {
          field: "stockQuantity",
          title: "库存数量",
          title: "物料数量",
          type: "string",
          width: 80,
          align: "left",
        },
        {
          field: "outboundQuantity",
          title: "出库数量",
          type: "string",
          width: 80,
          align: "left",
        },
        {
          field: "unit",
          title: "单位",
          type: "string",
          width: 50,
          align: "left",
        },
        {
          field: "productionDate",
          title: "生产日期",
          type: "string",
          width: 120,
          align: "left",
        },
        {
          field: "effectiveDate",
          title: "有效日期",
          type: "string",
          width: 120,
          align: "left",
        },
        {
@@ -332,7 +307,7 @@
          type: "string",
          width: 120,
          align: "left",
          bind: { key: "stockStatusEmun", data: [] }
          bind: { key: "stockStatusEmun", data: [] },
        },
        {
          field: "creater",
@@ -340,7 +315,7 @@
          type: "string",
          width: 90,
          align: "left",
          hidden: true
          // sort:true,
        },
        {
          field: "createDate",
@@ -348,7 +323,7 @@
          type: "datetime",
          width: 160,
          align: "left",
          hidden: true
          sort: true,
        },
        {
          field: "modifier",
@@ -356,7 +331,7 @@
          type: "string",
          width: 100,
          align: "left",
          hidden: true
          hidden: true,
        },
        {
          field: "modifyDate",
@@ -364,7 +339,7 @@
          type: "datetime",
          width: 160,
          align: "left",
          hidden: true
          hidden: true,
        },
        {
          field: "remark",
@@ -372,7 +347,7 @@
          type: "string",
          width: 100,
          align: "left",
          hidden: true
          hidden: true,
        },
      ],
      sortName: "id",
WMS/WIDESEA_WMSServer/WIDESEA_Core/BaseModels/WebResponseContent.cs
@@ -19,6 +19,8 @@
        public int Code { get; set; }
        public string msg { get; set; }
        public string Message { get; set; }
        public object Data { get; set; }
WMS/WIDESEA_WMSServer/WIDESEA_DTO/Basic/LocationArea.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_DTO.Basic
{
    public class LocationArea
    {
        /// <summary>
        /// åº“区名称
        /// </summary>
        public string house_name { get; set; }
        /// <summary>
        /// åº“区编号
        /// </summary>
        public int shelf_code { get; set; }
        /// <summary>
        ///
        /// </summary>
        public int tunnel { get; set; }
    }
    public class LocationLayer
    {
        public int index { get; set; }
        public List<LocationRow> rows { get; set; }
    }
    public class LocationRow
    {
        public int index { get; set; }
        public List<LocationCol> cols { get; set; }
    }
    public class LocationCol
    {
        public string locationCode { get; set; }
        public int row { get; set; }
        public int layer { get; set; }
        public int index { get; set; }
        /// <summary>
        /// æ£€æµ‹æŸœçŠ¶æ€
        /// </summary>
        public string remark { get; set; }
        /// <summary>
        /// è´§ä½çŠ¶æ€
        /// </summary>
        public int location_state { get; set; }
        /// <summary>
        /// é”å®šçŠ¶æ€
        /// </summary>
        public int location_lock { get; set; }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_DTO/Stock/StockViewDTO.cs
@@ -118,8 +118,14 @@
        /// <summary>
        /// ç‰©æ–™æ‰¹å·
        /// </summary>
        [ExporterHeader(DisplayName = "物料批号")]
        [ExporterHeader(DisplayName = "物料内部批号")]
        public string BatchNo { get; set; }
        /// <summary>
        ///供应商批号
        /// </summary>
        [ExporterHeader(DisplayName = "供应商批次")]
        public string SupplierBatch { get; set; }
        /// <summary>
        /// åº“存数量
        /// </summary>
WMS/WIDESEA_WMSServer/WIDESEA_IStockService/IStockViewService.cs
@@ -14,5 +14,7 @@
        PageGridData<StockViewDTO> GetPageData(PageDataOptions options);
        object GetDetailPage(PageDataOptions pageData);
        WebResponseContent Export(PageDataOptions options);
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_ISystemRepository/ISys_RoleDataPermissionRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Model.Models;
namespace WIDESEA_ISystemRepository
{
    public interface ISys_RoleDataPermissionRepository : IRepository<Sys_RoleDataPermission>
    {
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -58,7 +58,7 @@
        WebResponseContent IsRelocations(int TaskNum, string SourceAddress);
        WebResponseContent Cancelinventory(int taskNum);
        WebResponseContent InboundTaskCompleted(int taskNum);
        WebResponseContent OutboundTaskCompleted(int taskNum);
        WebResponseContent  OutboundTaskCompleted(int taskNum);
        WebResponseContent AddOutboundOrders(Houseounbound orderAddDTO);
        WebResponseContent InventoryOut(HouseCancelOut houseInventoryOut);
        WebResponseContent InventoryIn(string name, int qty);
WMS/WIDESEA_WMSServer/WIDESEA_InboundService/Base/InboundOrderService.cs
@@ -203,11 +203,11 @@
                }
                else
                {
                    if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt())
                    {
                        return WebResponseContent.Instance.Error($"托盘号重复");
                    }
                    beforeQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                    //if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt())
                    //{
                        return WebResponseContent.Instance.Error($"托盘号重复,该托盘已组过物料");
                    //}
                    //beforeQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                }
                if (warehouse.WarehouseCode == WarehouseEnum.SC01_BC.ToString())
@@ -438,9 +438,10 @@
                    
                    if (inboundOrderOld != null)
                    {
                        if (inboundOrderOld.OrderStatus != OrderDetailStatusEnum.New.ObjToInt())
                        if (inboundOrderOld.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt())
                        {
                            return content.Error($"{model.AsnNo}单据已开始!");
                            inboundOrderOld.OrderStatus = InOrderStatusEnum.入库中.ObjToInt();
                            _inboundRepository.InboundOrderRepository.UpdateData(inboundOrderOld);
                        }
                        Dt_InboundOrderDetail orderDetail1 = BaseDal.Db.Queryable<Dt_InboundOrderDetail>().Where(x => x.OrderId == inboundOrderOld.Id).First();
                        Dt_InboundOrderDetail? inboundOrderDetailOld = inboundOrderOld.Details?.FirstOrDefault(x => x.LinId == item.LinId && x.MaterielCode == item.MaterielCode);
@@ -809,12 +810,23 @@
                        .Db.Queryable<Dt_InboundOrderDetail>()
                        .Where(d => d.OrderId == inboundOrder.Id)
                        .Count();
                    //检查明细完成的个数
                    int overCount  = _inboundRepository.InboundOrderDetailRepository
                        .Db.Queryable<Dt_InboundOrderDetail>()
                        .Where(d => d.OrderId == inboundOrder.Id && d.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt())
                        .Count();
                    // å¦‚果没有剩余明细,再删除主订单
                    if (remainingDetailsCount == 0)
                    {
                        _inboundRepository.InboundOrderRepository.DeleteAndMoveIntoHty(inboundOrder, OperateType.人工取消);
                    }
                    //如果取消以后明细已经全部完成
                    if (remainingDetailsCount == overCount)
                    {
                        inboundOrder.OrderStatus = InOrderStatusEnum.入库完成.ObjToInt();
                        _inboundRepository.InboundOrderRepository.UpdateData(inboundOrder);
                    }
                    _unitOfWorkManage.CommitTran();
                    return WebResponseContent.Instance.OK();
WMS/WIDESEA_WMSServer/WIDESEA_InboundService/Base/TakeStockOrderService.cs
@@ -82,11 +82,11 @@
                List<Dt_TakeStockOrder> takeStockOrders = new List<Dt_TakeStockOrder>();
                if (string.IsNullOrEmpty(orderNo))
                {
                    takeStockOrders = Db.Queryable<Dt_TakeStockOrder>().Where(x => x.TakeStockStatus < TakeStockStatusEnum.盘点完成.ObjToInt() && x.WarehouseId == warehouseId).ToPageList(pageNo, 5);
                    takeStockOrders = Db.Queryable<Dt_TakeStockOrder>().Where(x => x.TakeStockStatus < TakeStockStatusEnum.盘点完成.ObjToInt() && x.WarehouseId == warehouseId).Includes(x=>x.Details).ToPageList(pageNo, 5);
                }
                else
                {
                    takeStockOrders = Db.Queryable<Dt_TakeStockOrder>().Where(x => (x.OrderNo.Contains(orderNo) && x.TakeStockStatus < TakeStockStatusEnum.盘点完成.ObjToInt() && x.WarehouseId == warehouseId)).ToPageList(pageNo, 5);
                    takeStockOrders = Db.Queryable<Dt_TakeStockOrder>().Where(x => (x.OrderNo.Contains(orderNo) && x.TakeStockStatus < TakeStockStatusEnum.盘点完成.ObjToInt() && x.WarehouseId == warehouseId)).Includes(x=>x.Details).ToPageList(pageNo, 5);
                }
                content.OK(data: takeStockOrders);
            }
WMS/WIDESEA_WMSServer/WIDESEA_Model/Models/System/Sys_RoleDataPermission.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.DB.Models;
namespace WIDESEA_Model.Models
{
    [SugarTable(nameof(Sys_RoleDataPermission))]
    public class Sys_RoleDataPermission : BaseEntity
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        public int RoleId { get; set; }
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "角色名称")]
        public string RoleName { get; set; }
        public int WarehouseId { get; set; }
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "")]
        public string WarehouseName { get; set; }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_OutboundService/Service/OutboundOrderDetailService.cs
@@ -498,7 +498,6 @@
            {
                ids = item.LinId;
                var postContent = new MultipartFormDataContent();
                postContent.Headers.Add("ContentType", $"multipart/form-data");
                postContent.Add(new StringContent(ids), "ids");
                string result = string.Empty;
                HttpClient client = null;
@@ -506,13 +505,13 @@
                {
                    using (client = new HttpClient())
                    {
                        HttpResponseMessage response = client.PostAsync(ToCancelOutFeedbackERP, postContent)
                            .ConfigureAwait(false).GetAwaiter().GetResult();
                        // 2. å‘送请求
                        var response = HttpHelper.Post<WebResponseContent>(ToCancelOutFeedbackERP, postContent, "出库明细取消回传ERP");
                        // ç¡®ä¿å“åº”成功
                        response.EnsureSuccessStatusCode();
                        result = response.Content.ReadAsStringAsync()
                            .ConfigureAwait(false).GetAwaiter().GetResult();
                        if (response.Code !=0)
                        {
                            throw new Exception($"操作失败: {response.msg ?? "未提供错误信息"}");
                        }
                    }
                    _unitOfWorkManage.BeginTran();
                    _outboundRepository.OutboundOrderDetailRepository.DeleteAndMoveIntoHty(outboundOrderDetails, OperateType.人工取消);
WMS/WIDESEA_WMSServer/WIDESEA_StockService/Base/StockViewService.cs
@@ -1,4 +1,6 @@

using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using System;
@@ -52,6 +54,13 @@
                            {
                                switch (param.Name)
                                {
                                    case var name when name == nameof(Dt_StockInfo.PalletCode).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x=>x.PalletCode.Contains(param.Value.ToString()));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfoDetail.MaterielCode).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
@@ -71,7 +80,7 @@
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.LocationCode == param.Value.ToString());
                                                .Where(x => x.LocationCode.Contains(param.Value.ToString()));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_LocationInfo.LocationStatus).FirstLetterToLower():
@@ -152,6 +161,7 @@
                {
                    x.MaterielCode = string.Join(",", x.Details.Select(d => d.MaterielCode).Distinct());
                    x.BatchNo = string.Join(",", x.Details.Select(d => d.BatchNo).Distinct());
                    x.SupplierBatch = string.Join(",", x.Details.Select(d => d.SupplierBatch).Distinct());
                    x.MaterielSpec = x.Details.FirstOrDefault()?.MaterieSpec ?? "";
                    x.MaterielName = x.Details.FirstOrDefault()?.MaterielName ?? "";
                });
@@ -186,5 +196,162 @@
            }
            return new PageGridData<object>(total: 0, null);
        }
        public virtual WebResponseContent Export(PageDataOptions options)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Type t = typeof(StockViewDTO);
                string savePath = AppDomain.CurrentDomain.BaseDirectory + $"ExcelExport";
                IExporter exporter = new ExcelExporter();
                options.Page = 1;
                options.Rows = 30;
                options.Order = "desc";
                options.Sort = "stockId";
                ISugarQueryable<Dt_StockInfo> sugarQueryable1 = _dbBase.Queryable<Dt_StockInfo>().Includes(x => x.Details);
                ISugarQueryable<Dt_LocationInfo> sugarQueryable = _dbBase.Queryable<Dt_LocationInfo>();
                ISugarQueryable<Dt_StockInfoDetail> sugarQueryable2 = _dbBase.Queryable<Dt_StockInfoDetail>();
                if (!string.IsNullOrEmpty(options.Wheres))
                {
                    try
                    {
                        List<SearchParameters> searchParametersList = options.Wheres.DeserializeObject<List<SearchParameters>>();
                        if (searchParametersList?.Any() == true)
                        {
                            foreach (var param in searchParametersList)
                            {
                                switch (param.Name)
                                {
                                    case var name when name == nameof(Dt_StockInfo.PalletCode).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.PalletCode.Contains(param.Value.ToString()));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfoDetail.MaterielCode).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.Details.Any(v => v.MaterielCode.Contains(param.Value.ToString())));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfoDetail.BatchNo).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.Details.Any(v => v.BatchNo.Contains(param.Value.ToString())));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfo.LocationCode).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.LocationCode.Contains(param.Value.ToString()));
                                        }
                                        break;
                                    case var name when name == nameof(Dt_LocationInfo.LocationStatus).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable = sugarQueryable
                                                .Where(x => x.LocationStatus == param.Value.ObjToInt());
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfo.StockStatus).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.StockStatus == param.Value.ObjToInt());
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfo.WarehouseId).FirstLetterToLower():
                                        if (!string.IsNullOrEmpty(param.Value?.ToString()))
                                        {
                                            sugarQueryable1 = sugarQueryable1
                                                .Where(x => x.WarehouseId == param.Value.ObjToInt());
                                        }
                                        break;
                                    case var name when name == nameof(Dt_StockInfo.CreateDate).FirstLetterToLower():
                                        if (DateTime.TryParse(param.Value?.ToString(), out DateTime minDate))
                                        {
                                            LinqExpressionType expressionType = param.DisplayType.GetLinqCondition();
                                            if (expressionType == LinqExpressionType.ThanOrEqual)
                                            {
                                                sugarQueryable1 = sugarQueryable1.Where(x => x.CreateDate >= minDate);
                                            }
                                            else if (expressionType == LinqExpressionType.LessThanOrEqual)
                                            {
                                                sugarQueryable1 = sugarQueryable1.Where(x => x.CreateDate <= minDate);
                                            }
                                        }
                                        break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }
                ISugarQueryable<StockViewDTO> list = sugarQueryable1
                    .InnerJoin(sugarQueryable, (b, a) => a.LocationCode == b.LocationCode)
                    .Select((b, a) => new StockViewDTO
                    {
                        LocationCode = b.LocationCode,
                        Column = a.Column,
                        WarehouseId = b.WarehouseId,
                        CreateDate = b.CreateDate,
                        Creater = b.Creater,
                        Depth = a.Depth,
                        EnalbeStatus = a.EnableStatus,
                        Layer = a.Layer,
                        LocationName = a.LocationName,
                        LocationStatus = a.LocationStatus,
                        LocationType = a.LocationType,
                        Modifier = b.Modifier,
                        ModifyDate = b.ModifyDate,
                        PalletCode = b.PalletCode,
                        StockRemark = b.Remark,
                        RoadwayNo = a.RoadwayNo,
                        Row = a.Row,
                        StockId = b.Id,
                        StockStatus = b.StockStatus,
                        Details = b.Details,
                    });
                int totalCount = 0;
                var stockViewDTOs = list.ToPageList(options.Page, options.Rows, ref totalCount);
                stockViewDTOs.ForEach(x =>
                {
                    x.MaterielCode = string.Join(",", x.Details.Select(d => d.MaterielCode).Distinct());
                    x.BatchNo = string.Join(",", x.Details.Select(d => d.BatchNo).Distinct());
                    x.SupplierBatch= string.Join(",", x.Details.Select(d => d.SupplierBatch).Distinct());
                    x.StockCounts = Math.Round(x.Details.Sum(x => x.StockQuantity), 3).ToString();
                    x.MaterielSpec = x.Details.FirstOrDefault()?.MaterieSpec ?? "";
                    x.MaterielName = x.Details.FirstOrDefault()?.MaterielName ?? "";
                });
                byte[] data = exporter.ExportAsByteArray(stockViewDTOs).Result;
                string fileName = "库存视图.xlsx";
                FileHelper.WriteFile(savePath, fileName, data);
                content = WebResponseContent.Instance.OK(data: savePath + "\\" + fileName);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error(ex.Message);
            }
            return content;
        }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_StockService/Service/StockInfoService.cs
@@ -211,19 +211,19 @@
                List<Dt_StockInfodt> stolist= new List<Dt_StockInfodt>();
                for (int i = 0; i < entities.Count; i++)
                {
                    Dt_StockInfoDetail dt_StockIndet = detdata.Where(x => x.StockId == entities[i].Id).FirstOrDefault();
                    List<Dt_StockInfoDetail> dt_StockIndet = detdata.Where(x => x.StockId == entities[i].Id).ToList();
                    string MaterialTypet = "原材料";
                    if (entities[i].MaterialType == (int)InventoryMaterialType.成品)
                    {
                        MaterialTypet = "成品";
                    }
                    else if(entities[i].MaterialType == (int)InventoryMaterialType.空托)
                    else if (entities[i].MaterialType == (int)InventoryMaterialType.空托)
                    {
                        MaterialTypet = "空托";
                    }
                    string Wlstatust = "待检";
                    if (entities[i].Wlstatus== (int)InventoryMaterialStatus.合格)
                    if (entities[i].Wlstatus == (int)InventoryMaterialStatus.合格)
                    {
                        Wlstatust = "合格";
                    }
@@ -254,14 +254,14 @@
                        MaterialType = MaterialTypet,
                        LocationCode = entities[i].LocationCode,
                        Wlstatus = Wlstatust,
                        MaterielCode = dt_StockIndet?.MaterielCode ?? "", // å¦‚æžœ dt_StockIndet ä¸º null,使用空字符串作为默认值
                        MaterielName = dt_StockIndet?.MaterielName ?? "",
                        OrderNo = dt_StockIndet?.OrderNo ?? "",
                        BatchNo = dt_StockIndet?.BatchNo ?? "",
                        SerialNumber = dt_StockIndet?.SerialNumber ?? "",
                        StockQuantity = dt_StockIndet?.StockQuantity ?? 0, // å‡è®¾ StockQuantity æ˜¯æ•°å€¼ç±»åž‹ï¼Œä½¿ç”¨ 0 ä½œä¸ºé»˜è®¤å€¼
                        BatchNoName = dt_StockIndet?.BatchNoName ?? "",
                        CreateDate = dt_StockIndet?.CreateDate ?? DateTime.MinValue, // å‡è®¾ CreateDate æ˜¯æ—¥æœŸç±»åž‹ï¼Œä½¿ç”¨é»˜è®¤æ—¶é—´
                        MaterielCode = dt_StockIndet?.FirstOrDefault()?.MaterielCode ?? "",
                        MaterielName = dt_StockIndet?.FirstOrDefault()?.MaterielName ?? "",
                        OrderNo = dt_StockIndet?.FirstOrDefault()?.OrderNo ?? "",
                        BatchNo = dt_StockIndet?.FirstOrDefault()?.BatchNo ?? "",
                        SerialNumber = dt_StockIndet?.FirstOrDefault()?.SerialNumber ?? "",
                        StockQuantity = dt_StockIndet?.Sum(item => item.StockQuantity) ?? 0,
                        BatchNoName = dt_StockIndet?.FirstOrDefault()?.BatchNoName ?? "",
                        CreateDate = dt_StockIndet?.FirstOrDefault()?.CreateDate ?? DateTime.MinValue,
                        Remark = entities[i].Remark,
                    };
                    stolist.Add(dt_);
WMS/WIDESEA_WMSServer/WIDESEA_SystemRepository/Sys_RoleDataPermissionRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_ISystemRepository;
using WIDESEA_Model.Models;
namespace WIDESEA_SystemRepository
{
    public class Sys_RoleDataPermissionRepository : RepositoryBase<Sys_RoleDataPermission>, ISys_RoleDataPermissionRepository
    {
        public Sys_RoleDataPermissionRepository(IUnitOfWorkManage unitOfWorkManage) : base(unitOfWorkManage)
        {
        }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/PartialTaskService_Inbound.cs
@@ -39,8 +39,7 @@
                Dt_Task task = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (task != null)
                {
                    PushTasksToWCS(new List<Dt_Task> { task });
                    return WebResponseContent.Instance.OK($"该托盘已生成任务", _mapper.Map<WMSTaskDTO>(task));
                    return WebResponseContent.Instance.Error($"该托盘{palletCode}已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.StockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
@@ -177,7 +176,7 @@
                _unitOfWorkManage.CommitTran();
                WMSTaskDTO wMSTaskDTO = _mapper.Map<WMSTaskDTO>(newTask);
                //PushTasksToWCS(new List<Dt_Task> { newTask });
                PushTasksToWCS(new List<Dt_Task> { newTask });
                return WebResponseContent.Instance.OK(data: wMSTaskDTO);
            }
            catch (Exception ex)
@@ -253,8 +252,7 @@
                Dt_Task task = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (task != null)
                {
                    PushTasksToWCS(new List<Dt_Task> { task });
                    return WebResponseContent.Instance.OK($"该托盘已生成任务", _mapper.Map<WMSTaskDTO>(task));
                    return WebResponseContent.Instance.Error($"该托盘{palletCode}已生成任务");
                }
                // èŽ·å–å…¥åº“å•æ˜Žç»†
                var inboundOrderDet = GetInboundOrderDetail(palletCode);
WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -79,6 +79,7 @@
using WIDESEA_InboundRepository;
using System.Drawing.Printing;
using System;
using WIDESEA_Common.Log;
namespace WIDESEA_TaskInfoService
{
@@ -107,7 +108,8 @@
        private readonly IStockInfoDetailRepository _stockInfoDetailRepository;
        private readonly IReturnOrderRepository _returnOrderRepository;
        private readonly IProductionRepository _productionRepository;
        private readonly IInboundRepository _inboundRepository;
        private readonly IInboundRepository _inboundRepository;
        public ITaskRepository Repository => BaseDal;
        public TaskService(ITaskRepository BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IMaterielInfoService materielInfoService, IInboundOrderDetail_HtyService inboundOrderDetail_HtyService, IOutboundOrder_HtyService outboundOrder_HtyService, IOutboundOrderDetail_HtyService outboundOrderDetail_HtyService, IInboundOrder_HtyService inboundOrder_HtyService, IStockRepository stockRepository, IInboundOrderDetailService inboundOrderDetailService, IBasicService basicService, IOutboundService outboundService, IInboundService inboundService, IRecordService recordService, IStockService stockService, ITask_HtyService taskHtyService, ILocationInfoService locationInfoService, IOutboundOrderDetailRepository outboundOrderDetailRepository, IBasicRepository basicRepository, IStockInfoDetailRepository stockInfoDetailRepository, IPalletTypeInfoRepository palletTypeInfoRepository, IReturnOrderRepository returnOrderRepository, IProductionRepository productionRepository,IInboundRepository inboundRepository) : base(BaseDal)
@@ -144,6 +146,7 @@
        public string ReceiveWMSTaskAllocatein = WIDESEA_Core.Helper.AppSettings.Configuration["ReceiveWMSTaskAllocatein"];
        public string ReceiveERPTaskout = WIDESEA_Core.Helper.AppSettings.Configuration["ReceiveERPTaskout"];
        public string InMaterialWarehousingCallback = WIDESEA_Core.Helper.AppSettings.Configuration["InMaterialWarehousingCallback"];
        /// <summary>
        /// ä»»åŠ¡ä¿¡æ¯æŽ¨é€è‡³WCS
@@ -187,7 +190,7 @@
                {
                    return WebResponseContent.Instance.Error($"未找到WCSApi地址,请检查配置文件");
                }
                string response = HttpHelper.Get($"{url}/api/Task/RecWMSTaskCompleted?taskNum=" + taskNum);
                string response = HttpHelper.Post($"{url}/api/Task/RecWMSTaskCompleted?taskNum=" + taskNum);
                return JsonConvert.DeserializeObject<WebResponseContent>(response) ?? WebResponseContent.Instance.Error("返回错误");
            }
@@ -1205,8 +1208,7 @@
                if (outboundOrderDetails.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt() && inboundOrder.System.Equals("ERP"))
                {
                    FeedBackOutERP(outboundOrder.OrderNo, outboundOrderDetails.LinId);
                    //DownloadReport(path, savePath, outboundOrderDetails.Id);
                    //printTest(savePath);
                    DownloadReport(path, savePath, outboundOrderDetails.Id);
                }
                ///单据完成推送SMOM系统
                if (outboundOrder.OrderStatus == OutboundStatusEnum.出库完成.ObjToInt() && inboundOrder.System.Equals("SMOM"))
@@ -1664,72 +1666,348 @@
                throw new Exception($"操作失败: {response.Message ?? "未提供错误信息"}");
            }
        }
        public string DownloadReport(string path, string savePath, int orderId)
        // æ–¹æ³•声明添加 async å…³é”®å­—,返回值改为 Task<string>
        public async Task<string> DownloadReport(string path, string savePath, int orderId)
        {
            // æž„建完整 URL,(报表传参)
            string reportUrl = path + "&orderId=" + orderId;
            try
            {
                // ç¡®ä¿ä¿å­˜ç›®å½•存在
                string directory = Path.GetDirectoryName(savePath);
                Console.WriteLine($"下载地址: {reportUrl}");
                Console.WriteLine($"保存路径: {savePath}");
                // ç¡®ä¿ç›®å½•存在
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                    Console.WriteLine($"已创建目录: {directory}");
                }
                string[] files = Directory.GetFiles(directory);
                // åˆ é™¤æ¯ä¸ªæ–‡ä»¶
                foreach (string filePath in files)
                // æ¸…理目录下现有文件
                if (File.Exists(savePath))
                {
                    File.Delete(filePath);
                    File.Delete(savePath);
                    Console.WriteLine($"已删除旧文件: {savePath}");
                }
                // ä½¿ç”¨ HttpClient ä¸‹è½½æ–‡ä»¶
                // ä½¿ç”¨ä¸´æ—¶æ–‡ä»¶åä¸‹è½½ï¼Œä¸‹è½½å®ŒæˆåŽå†é‡å‘½å
                string tempFilePath = savePath + ".tmp";
                // å¼‚步下载文件
                using (var httpClient = new HttpClient())
                {
                    // è®¾ç½®è¶…时时间(帆软报表生成可能需要较长时间)
                    httpClient.Timeout = TimeSpan.FromMinutes(5);
                    // å‘送 GET è¯·æ±‚(同步方式)
                    using (var response = httpClient.GetAsync(reportUrl, HttpCompletionOption.ResponseHeadersRead).GetAwaiter().GetResult())
                    using (var response = await httpClient.GetAsync(reportUrl, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
                    {
                        // æ£€æŸ¥å“åº”状态
                        response.EnsureSuccessStatusCode();
                        // èŽ·å–å†…å®¹æµï¼ˆåŒæ­¥æ–¹å¼ï¼‰
                        using (var contentStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult())
                        using (var contentStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                        {
                            // åˆ›å»ºæ–‡ä»¶æµ
                            using (var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))
                            Console.WriteLine($"开始写入临时文件: {tempFilePath}");
                            using (var fileStream = new FileStream(
                                tempFilePath,
                                FileMode.Create,
                                FileAccess.Write,
                                FileShare.None,
                                bufferSize: 4096,
                                useAsync: true
                            ))
                            {
                                // å¤åˆ¶å†…容到文件(同步方式)
                                contentStream.CopyToAsync(fileStream).GetAwaiter().GetResult();
                                await contentStream.CopyToAsync(fileStream).ConfigureAwait(false);
                                await fileStream.FlushAsync().ConfigureAwait(false);
                                Console.WriteLine($"临时文件写入完成: {tempFilePath}");
                            }
                        }
                    }
                }
                return savePath;
                // å…³é”®ä¼˜åŒ–:确保文件完全写入磁盘
                await EnsureFileCompletelyWritten(tempFilePath);
                // é‡å‘½åä¸ºç›®æ ‡æ–‡ä»¶
                File.Move(tempFilePath, savePath, true);
                Console.WriteLine($"文件重命名完成: {savePath}");
                // éªŒè¯æ–‡ä»¶å¯è®¿é—®
                await ValidateFileAccessible(savePath);
                // æ‰“印文件
                PrintTestDirect(savePath);
                return savePath;
            }
            catch (Exception ex)
            {
                throw new ValidationException(ex.Message);
                Console.WriteLine($"下载失败: {ex.Message}");
                throw new InvalidOperationException($"文件下载异常: {ex.Message}", ex);
            }
        }
        public virtual void printTest(string fullPath)
        /// <summary>
        /// ç¡®ä¿æ–‡ä»¶å®Œå…¨å†™å…¥ç£ç›˜
        /// </summary>
        private async Task EnsureFileCompletelyWritten(string filePath)
        {
            Spire.Pdf.PdfDocument pdf = new PdfDocument();
            //文件地址
            pdf.LoadFromFile(fullPath);
            //指定打印机位置
            string url = AppSettings.app("PrinterName");
            pdf.PrintSettings.PrinterName = url;
            //执行打印
            pdf.Print();
            //内存释放
            pdf.Dispose();
            const int maxRetries = 5;
            const int delayMs = 500;
            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    // å°è¯•以读取模式打开文件,确保文件没有被占用
                    using (var fs = new FileStream(filePath,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Read,
                        bufferSize: 4096,
                        useAsync: true))
                    {
                        // éªŒè¯æ–‡ä»¶æœ‰å†…容
                        if (fs.Length > 0)
                        {
                            Console.WriteLine($"文件验证成功: å¤§å°={fs.Length}字节 (尝试 {i + 1}/{maxRetries})");
                            return;
                        }
                        else
                        {
                            Console.WriteLine($"警告: æ–‡ä»¶å¤§å°ä¸º0 (尝试 {i + 1}/{maxRetries})");
                        }
                    }
                }
                catch (IOException ex)
                {
                    Console.WriteLine($"文件可能仍在写入中 (尝试 {i + 1}/{maxRetries}): {ex.Message}");
                }
                if (i < maxRetries - 1)
                {
                    await Task.Delay(delayMs);
                }
            }
            throw new IOException($"文件写入未完成或无法访问: {filePath}");
        }
        /// <summary>
        /// éªŒè¯æ–‡ä»¶å¯è®¿é—®ä¸”不为空
        /// </summary>
        private async Task ValidateFileAccessible(string filePath)
        {
            const int maxRetries = 3;
            const int delayMs = 300;
            for (int i = 0; i < maxRetries; i++)
            {
                try
                {
                    if (!File.Exists(filePath))
                    {
                        throw new FileNotFoundException($"文件不存在: {filePath}");
                    }
                    var fileInfo = new FileInfo(filePath);
                    // éªŒè¯æ–‡ä»¶å¤§å°å¤§äºŽ0
                    if (fileInfo.Length == 0)
                    {
                        throw new InvalidDataException($"文件大小为0: {filePath}");
                    }
                    // éªŒè¯æ–‡ä»¶ä¸æ˜¯å®Œå…¨ç”±ç©ºå­—符组成(可选检查)
                    await ValidateFileContent(filePath);
                    Console.WriteLine($"文件验证通过: {filePath} (大小={fileInfo.Length}字节)");
                    return;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"文件验证失败 (尝试 {i + 1}/{maxRetries}): {ex.Message}");
                    if (i == maxRetries - 1)
                    {
                        throw;
                    }
                    await Task.Delay(delayMs);
                }
            }
        }
        /// <summary>
        /// éªŒè¯æ–‡ä»¶å†…容(可选)
        /// </summary>
        private async Task ValidateFileContent(string filePath)
        {
            try
            {
                // è¯»å–文件前几个字节,确保不是完全由空字符组成
                using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
                {
                    byte[] buffer = new byte[Math.Min(1024, fs.Length)];
                    int bytesRead = await fs.ReadAsync(buffer, 0, buffer.Length);
                    // æ£€æŸ¥æ˜¯å¦éƒ½æ˜¯0(空文件)
                    if (bytesRead > 0 && buffer.All(b => b == 0))
                    {
                        throw new InvalidDataException("文件内容异常: å…¨éƒ¨ä¸º0字节");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"文件内容验证异常: {ex.Message}");
                // å¯ä»¥é€‰æ‹©æ˜¯å¦æŠ›å‡ºå¼‚常
            }
        }
        public virtual void PrintTestDirect(string fullPath)
        {
            const int maxRetryCount = 3;
            const int retryDelayMs = 1000;
            if (!File.Exists(fullPath))
            {
                Console.WriteLine($"打印失败:文件不存在 {fullPath}");
                return;
            }
            // èŽ·å–æ‰“å°æœºåç§°
            string printerName = AppSettings.app("PrinterName");
            // å°è¯•不同的打印方法
            for (int retryCount = 0; retryCount < maxRetryCount; retryCount++)
            {
                try
                {
                    Console.WriteLine($"尝试打印 (方法 {retryCount + 1}/{maxRetryCount}): {fullPath}");
                    switch (retryCount)
                    {
                        case 0:
                            // æ–¹æ³•1: ä½¿ç”¨åŽŸå§‹æ‰“å°å‘½ä»¤
                            PrintUsingRawCommand(fullPath, printerName);
                            break;
                        case 1:
                            // æ–¹æ³•3: ç›´æŽ¥ä½¿ç”¨Spire.PDF但简化设置
                            PrintUsingSpireSimple(fullPath, printerName);
                            break;
                        case 2:
                            // æ–¹æ³•3: ç›´æŽ¥ä½¿ç”¨Spire.PDF但简化设置
                            PrintUsingSpireSimple(fullPath, printerName);
                            break;
                    }
                    Console.WriteLine("打印任务发送成功");
                    return;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"打印方法 {retryCount + 1} å¤±è´¥: {ex.Message}");
                    if (retryCount < maxRetryCount - 1)
                    {
                        Thread.Sleep(retryDelayMs);
                    }
                }
            }
            Console.WriteLine("所有打印方法都失败");
        }
        /// <summary>
        /// ä½¿ç”¨åŽŸå§‹æ‰“å°å‘½ä»¤
        /// </summary>
        private void PrintUsingRawCommand(string filePath, string printerName)
        {
            try
            {
                // æ–¹æ³•1: ä½¿ç”¨Process直接打印
                var process = new System.Diagnostics.Process();
                process.StartInfo.FileName = filePath;
                process.StartInfo.Verb = "print";
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                process.Start();
                // ç­‰å¾…一段时间让打印任务提交
                if (!process.WaitForExit(5000))
                {
                    Console.WriteLine("打印进程未及时退出,但任务可能已提交");
                }
            }
            catch
            {
                // å¦‚果上述方法失败,尝试使用rundll32
                try
                {
                    var args = $@"/c rundll32.exe C:\Windows\System32\shimgvw.dll,ImageView_PrintTo ""{filePath}"" ""{printerName}""";
                    System.Diagnostics.Process.Start("cmd.exe", args);
                }
                catch
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// ä½¿ç”¨Spire.PDF但简化设置
        /// </summary>
        private void PrintUsingSpireSimple(string filePath, string printerName)
        {
            using (Spire.Pdf.PdfDocument pdf = new Spire.Pdf.PdfDocument())
            {
                // ä½¿ç”¨æœ€å°é…ç½®åŠ è½½æ–‡ä»¶
                pdf.LoadFromFile(filePath);
                // è®¾ç½®åŸºæœ¬æ‰“印机信息
                if (!string.IsNullOrEmpty(printerName))
                {
                    pdf.PrintSettings.PrinterName = printerName;
                }
                // ç›´æŽ¥æ‰“印,不检查
                pdf.Print();
            }
        }
        /// <summary>
        /// æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å¯è®¿é—®
        /// </summary>
        private bool IsFileAccessible(string filePath)
        {
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    return fs.Length > 0;
                }
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// å°è¯•强制垃圾回收,释放可能存在的文件句柄
        /// </summary>
        private void TryForceGarbageCollection()
        {
            try
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                Console.WriteLine("已执行垃圾回收");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"垃圾回收失败: {ex.Message}");
            }
        }
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Basic/LocationInfoRowController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_DTO.Basic;
using WIDESEA_IBasicRepository;
using WIDESEA_IBasicService;
using WIDESEA_ISystemRepository;
using WIDESEA_Model.Models;
namespace WIDESEA_WMSServer.Controllers.Basic
{
    /// <summary>
    /// è´§ä½
    /// </summary>
    [Route("api/LocationInfoRow")]
    [ApiController]
    public class LocationInfoRowController : ApiBaseController<ILocationInfoService, Dt_LocationInfo>
    {
        private readonly ILocationInfoRepository _repository;
        private readonly ISys_RoleDataPermissionRepository _permissionRepository;
        private readonly ILocationInfoRepository _locationInfoRepository;
        public LocationInfoRowController(ILocationInfoService service, ILocationInfoRepository repository, ISys_RoleDataPermissionRepository permissionRepository, ILocationInfoRepository locationInfoRepository) : base(service)
        {
            _repository = repository;
            _permissionRepository = permissionRepository;
            _locationInfoRepository = locationInfoRepository;
        }
        /// <summary>
        /// èŽ·å–åº“åŒºæƒé™
        /// </summary>
        /// <returns></returns>
        [HttpGet, HttpPost, Route("GetArea"), AllowAnonymous]
        public object GetArea()
        {
            List<object> list = new List<object>();
            List<Dt_LocationInfo>? locations = null;
            List<Sys_RoleDataPermission> permissions = _permissionRepository.QueryData(x => x.RoleId == App.User.RoleId);
            if (permissions.Count > 0)
                locations = _locationInfoRepository.QueryData(x => permissions.Select(k => k.WarehouseId).ToList().Contains(x.WarehouseId));
            foreach (var permission in permissions)
            {
                var Rows = locations.Where(x => x.WarehouseId == permission.WarehouseId).GroupBy(x => x.Row).Select(x => x.Key).OrderBy(x => x).ToList();
                var obj = new
                {
                    house_name = permission.WarehouseName,
                    shelf_code = permission.WarehouseId,
                    tunnel = Rows
                };
                list.Add(obj);
            }
            return list;
        }
        /// <summary>
        /// èŽ·å–è´§ä½ä¿¡æ¯
        /// </summary>
        /// <param name="area"></param>
        /// <returns></returns>
        [HttpPost, Route("GetLocationStatu"), AllowAnonymous]
        public object GetLocationStatu([FromBody] LocationArea area)
        {
            List<LocationLayer> layers = new List<LocationLayer>();
            var data = _locationInfoRepository.QueryData(x => x.WarehouseId == area.shelf_code && x.Row == area.tunnel);
            foreach (var layer in data.GroupBy(t => t.Layer))
            {
                var rows = new List<LocationRow>();
                var data_rows = layer.GroupBy(t => t.Row);
                foreach (var data_row in data_rows)
                {
                    var cols = new List<LocationCol>();
                    foreach (var data_col in data_row)
                    {
                        cols.Add(new LocationCol()
                        {
                            //列
                            row = data_col.Row,
                            layer = data_col.Layer,
                            index = data_col.Column,
                            locationCode = data_col.LocationCode,
                            location_state = data_col.LocationStatus,
                            location_lock = data_col.EnableStatus,
                            remark = data_col.Remark
                        });
                    }
                    cols = cols.OrderBy(t => t.index).ToList();
                    rows.Add(new LocationRow()
                    {
                        //行
                        index = data_row.Key,
                        cols = cols
                    });
                }
                rows = rows.OrderBy(t => t.index).ToList();
                layers.Add(new LocationLayer()
                {
                    //层
                    index = layer.Key,
                    rows = rows
                });
            }
            layers = layers.OrderBy(t => t.index).ToList();
            return layers;
        }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockViewController.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Reflection;
using WIDESEA_Core;
using WIDESEA_Core.BaseController;
using WIDESEA_DTO.Stock;
@@ -31,5 +32,34 @@
        {
            return _stockViewService.GetDetailPage(pageData);
        }
        /// <summary>
        /// å¯¼å‡ºæ•°æ®
        /// </summary>
        /// <param name="loadData"></param>
        /// <returns></returns>
        [HttpPost, Route("Export")]
        public virtual ActionResult Export([FromBody] PageDataOptions loadData)
        {
            WebResponseContent result = InvokeService("Export", new object[] { loadData }) as WebResponseContent;
            if (result.Status)
                return File(
                       System.IO.File.ReadAllBytes(result.Data.ToString()),
                       System.Net.Mime.MediaTypeNames.Application.Octet,
                       Path.GetFileName(result.Data.ToString())
                   );
            return Json(result);
        }
        private object InvokeService(string methodName, object[] parameters)
        {
            Type t = _stockViewService.GetType();
            List<Type> types = new List<Type>();
            foreach (var param in parameters)
            {
                types.Add(param.GetType());
            }
            MethodInfo method = t.GetMethod(methodName, types.ToArray());
            return method.Invoke(_stockViewService, parameters);
        }
    }
}
WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -1,36 +1,44 @@
{
    "urls": "http://*:9290", //web服务端口,如果用IIS部署,把这个去掉
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
        }
    },
    "dics": "inOrderType,inoutType,outOrderType,inboundState,createType,enableEnum,enableStatusEnum,locationStatusEnum,locationTypeEnum,taskTypeEnum,taskStatusEnum,outboundStatusEnum,orderDetailStatusEnum,stockStatusEmun,stockChangeType,outStockStatus,InventoryMaterialType,InventoryMaterialStatus",
    "AllowedHosts": "*",
  "urls": "http://*:9290", //web服务端口,如果用IIS部署,把这个去掉
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "dics": "inOrderType,inoutType,outOrderType,inboundState,createType,enableEnum,enableStatusEnum,locationStatusEnum,locationTypeEnum,taskTypeEnum,taskStatusEnum,outboundStatusEnum,orderDetailStatusEnum,stockStatusEmun,stockChangeType,outStockStatus,InventoryMaterialType,Inventory,materialStatus,warehouses,inoutTypeEnum,takeStockStatusEnum,takeStockDetailStatusEnum",
  "AllowedHosts": "*",
    "ReceiveTask": "http://192.168.110.172:9291/api/Task/ReceiveTask", //下发出库任务至WCS
    "ReceiveWMSTaskin": "http://10.168.3.36:1041/api/dataportal/invoke", //立库入库数量信息回传WMS
    "ReceiveWMSTaskout": "http://10.168.3.36:1041/api/dataportal/invoke", //立库出库数量信息回传WMS
    "ReceiveWMSTaskAUT": "http://10.168.3.36:1041/api/dataportal/invoke", //立库入库数量信息回传WMS验证
    "ReceiveWMSInventoryIn": "http://10.168.3.36:1041/api/dataportal/invoke", //盘点差异数量回传WMS
    "ReceiveWMSTaskAllocatein": "http://10.168.3.36:1041/api/dataportal/invoke", //调拨任务数量回传WMS
    "ReceiveWMSTask": "http://192.168.110.172:9291/ReceiveWMSTask", //查询库存,确认入库站台
    "ConnectionStringsEncryption": false,
    "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true
    //连接字符串
    //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=",
    "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_JAMK;User ID=sa;Password=sa123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
    //跨域
    "Cors": {
        "PolicyName": "CorsIpAccess", //策略名称
        "EnableAllIPs": true, //当为true时,开放所有IP均可访问。
        // æ”¯æŒå¤šä¸ªåŸŸåç«¯å£ï¼Œæ³¨æ„ç«¯å£å·åŽä¸è¦å¸¦/斜杆:比如localhost:8000/,是错的
        // æ³¨æ„ï¼Œhttp://127.0.0.1:1818 å’Œ http://localhost:1818 æ˜¯ä¸ä¸€æ ·çš„
        "IPs": "http://127.0.0.1:8080,http://localhost:8080"
    },
    "WCS": "http://localhost:9291",
    "ApiName": "WIDESEA",
    "ExpMinutes": 120,
    "QuartzJobAutoStart": true
  "ReceiveTask": "http://192.168.110.172:9291/api/Task/ReceiveTask", //下发出库任务至WCS
  "ReceiveWMSTaskin": "http://172.30.0.192:1031/api/dataportal/invoke", //立库入库数量信息回传WMS
  "ReceiveWMSTaskreturn": "http://172.30.0.192:1031/api/dataportal/invoke", //立库回库数量信息回传WMS
  "ReceiveWMSTaskout": "http://172.30.0.192:1031/api/dataportal/invoke", //立库出库数量信息回传WMS
  "ReceiveWMSTaskAUT": "http://172.30.0.192:1031/api/dataportal/invoke", //立库入库数量信息回传WMS验证
  "ReceiveWMSInventoryIn": "http://172.30.0.192:1031/api/dataportal/invoke", //盘点差异数量回传WMS
  "ReceiveWMSTaskAllocatein": "http://172.30.0.192:1031/api/dataportal/invoke", //调拨任务数量回传WMS
  "ReceiveWMSTask": "http://192.168.110.172:9291/ReceiveWMSTask", //查询库存,确认入库站台
  "ReceiveERPTaskout": "http://172.30.0.192:99/external/asrs/api/OutMaterialWarehousingCallback", //立库出库数量信息回传ERP
  "CancelOutFeedbackERP": "http://172.30.0.192:99/external/asrs/api/CancelOutMaterialWarehousing", //出库单明细取消回传ERP
  "InMaterialWarehousingCallback": "http://172.30.0.184:99/external/asrs/api/InMaterialWarehousingCallback", //入库单完成回传ERP
  "CancelInMaterialWarehousing": "http://172.30.0.184:99/external/asrs/api/CancelInMaterialWarehousing", //入库单取消回传ERP
  "ConnectionStringsEncryption": false,
  "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true
  //连接字符串
  //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=",
  "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_JAMK;User ID=sa;Password=root;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //跨域
  "Cors": {
    "PolicyName": "CorsIpAccess", //策略名称
    "EnableAllIPs": true, //当为true时,开放所有IP均可访问。
    // æ”¯æŒå¤šä¸ªåŸŸåç«¯å£ï¼Œæ³¨æ„ç«¯å£å·åŽä¸è¦å¸¦/斜杆:比如localhost:8000/,是错的
    // æ³¨æ„ï¼Œhttp://127.0.0.1:1818 å’Œ http://localhost:1818 æ˜¯ä¸ä¸€æ ·çš„
    "IPs": "http://127.0.0.1:8080,http://localhost:8080"
  },
  "ERP": "http://172.30.0.192:99",
  "WCS": "http://localhost:9291",
  "PrinterName": "SHARP MX-5148NC PCL6",
  "ApiName": "WIDESEA",
  "ExpMinutes": 120,
  "QuartzJobAutoStart": true
}
¼ª°²PDA/pages/stash/TakeStockOrder.vue
@@ -6,16 +6,34 @@
            </view>
        </u-sticky>
        <uni-list :border="true">
            <uni-list-item direction="column" clickable @click="groupClick(item.orderNo)" link
                :to="page+item.orderNo+'&warehouseId='+warehouseId+'&id='+item.id" v-for="item in allReceivingOrders"
                :key="item.orderNo">
            <uni-list-item
                direction="column"
                clickable
                @click="groupClick(item.orderNo)"
                link
                :to="`${page}${item.orderNo}&warehouseId=${warehouseId}&id=${item.id}`"
                v-for="item in allReceivingOrders"
                :key="item.orderNo"
            >
                <template v-slot:body>
                    <uni-group margin-top="20">
                        <view style="line-height: 17px;color: #596671;font-size: 14px;text-align: center;display: flex;justify-content: space-between;">
                        <view style="line-height: 17px;color: #596671;font-size: 14px;display: flex;justify-content: space-between;">
                            ç›˜ç‚¹å•号&nbsp;&nbsp;{{item.orderNo}} 
                        </view>
                        <view style="line-height: 17px;color: #596671;font-size: 14px;text-align: center;display: flex;justify-content: space-between;">
                        <view style="line-height: 17px;color: #596671;font-size: 14px;display: flex;justify-content: space-between;">
                            åˆ›å»ºæ—¶é—´&nbsp;&nbsp;{{item.createDate}} 
                        </view>
                        <!-- æ‰˜ç›˜ç¼–号展示区域 -->
                        <view style="line-height: 17px;color: #596671;font-size: 14px;margin-top: 10rpx;">
                            éœ€ç›˜ç‚¹ç›˜å·ï¼š
                            <view style="display: inline-flex;flex-wrap: wrap;margin-left: 10rpx;">
                                <text
                                    style="display: inline-block;background-color: #f5f5f5;padding: 2rpx 10rpx;border-radius: 4rpx;margin: 0 5rpx 5rpx 0;"
                                    v-for="(detail, index) in item.details"
                                    :key="index">
                                    {{detail.takePalletCode}} ,料号:{{detail.materielCode}}
                                </text>
                            </view>
                        </view>
                        <view
                            style="margin-top: 10rpx;display: flex;align-items: center; ">
@@ -26,9 +44,13 @@
                    </uni-group>
                </template>
            </uni-list-item>
        </uni-list>
        <uni-load-more :status="status" v-if="loadVisible"></uni-load-more>
        <!-- åŠ è½½æ›´å¤šç»„ä»¶ -->
        <uni-load-more
            :status="status"
            :show-icon="true"
            v-if="allReceivingOrders.length > 0 || status === 'loading'"
        ></uni-load-more>
        <u-back-top :scroll-top="scrollTop" top="400"></u-back-top>
    </view>
@@ -40,95 +62,118 @@
        data() {
            return {
                page: "/pages/stash/TakeStock?orderNo=",
                loadVisible: false,
                searchValue: "",
                warehouseId: "",
                status: "more",
                status: "more", // åŠ è½½çŠ¶æ€ï¼šmore-可加载,loading-加载中,noMore-无更多
                allReceivingOrders: [],
                pageNo: 1,
                pageSize: 5, // å…³é”®ä¿®å¤ï¼šä¸ŽåŽç«¯ä¿æŒä¸€è‡´ï¼ˆæ¯é¡µ5条)
                scrollTop: 0,
                isLoaded:false
                isLoaded: false,
                isLoading: false, // é˜²æ­¢é‡å¤åŠ è½½çš„é”
                hasMore: true // æ˜¯å¦è¿˜æœ‰æ›´å¤šæ•°æ®
            }
        },
        onLoad(res) {
            this.warehouseId = res.warehouseId;
            this.isLoaded = true;
            this.getData();
            this.resetData(); // é‡ç½®æ•°æ®å¹¶åŠ è½½ç¬¬ä¸€é¡µ
        },
        onPageScroll(e) {
            this.scrollTop = e.scrollTop;
        },
        onShow() {
            if (this.isLoaded) {
                // ä»Žå…¶ä»–页面返回时刷新
                this.getData();
                this.resetData();
            }
        },
        onReachBottom() {
            this.pageNo += 1;
            this.getData();
            // ä¸‹æ‹‰åˆ°åº•部时加载更多
            if (this.hasMore && !this.isLoading) {
                this.pageNo += 1;
                this.getData();
            }
        },
        methods: {
            search(res) {
            // æœç´¢æ—¶é‡ç½®æ•°æ®
            search() {
                this.resetData();
            },
            // é‡ç½®æ•°æ®åˆ°åˆå§‹çŠ¶æ€
            resetData() {
                this.pageNo = 1;
                this.allReceivingOrders = [];
                this.hasMore = true;
                this.status = "more";
                this.getData();
            },
            groupClick() {
                // ç‚¹å‡»äº‹ä»¶å¤„理
            },
            // èŽ·å–æ•°æ®
            getData() {
                var postData = {
                if (this.isLoading || !this.hasMore) return;
                this.isLoading = true;
                this.status = "loading";
                const postData = {
                    MainData: {
                        orderNo: this.searchValue,
                        pageNo: this.pageNo,
                        // åŽç«¯å›ºå®šæ¯é¡µ5条,这里可以不传递pageSize,保持与后端一致
                        warehouseId: this.warehouseId,
                    },
                }
                this.$u.post('/api/TakeStockOrder/GetTakeStockOrders', postData).then((res) => {
                    if (res.status) {
                        if (res.data.length > 0) {
                            if (this.searchValue == '') {
                                this.allReceivingOrders =res.data.map(i => ({
                                ...i,
                                takeStockStatus: TakeStockStatus.find(item => item.value == i
                                    .takeStockStatus).label
                                }))
                                // this.allReceivingOrders = res.data;
                                if (this.allReceivingOrders.length > 3) {
                                    this.loadVisible = true;
                this.$u.post('/api/TakeStockOrder/GetTakeStockOrders', postData)
                    .then((res) => {
                        this.isLoading = false;
                        if (res.status) {
                            const processedData = res.data.map(item => ({
                                ...item,
                                takeStockStatus: TakeStockStatus.find(status => status.value === item.takeStockStatus)?.label || ''
                            }));
                            if (processedData.length > 0) {
                                if (this.pageNo === 1) {
                                    this.allReceivingOrders = processedData;
                                } else {
                                    this.loadVisible = false;
                                    this.allReceivingOrders = [...this.allReceivingOrders, ...processedData];
                                }
                                // å…³é”®ä¿®å¤ï¼šæ ¹æ®åŽç«¯å®žé™…返回数量判断是否还有更多
                                // åŽç«¯å›ºå®šæ¯é¡µ5条,所以当返回5条时说明可能还有更多,少于5条则说明没有更多
                                this.hasMore = processedData.length === this.pageSize;
                                this.status = this.hasMore ? "more" : "noMore";
                            } else {
                                // this.allReceivingOrders = res.data;
                                if (postData.MainData.pageNo == 1) {
                                if (this.pageNo === 1) {
                                    this.allReceivingOrders = [];
                                }
                                this.allReceivingOrders =res.data.map(i => ({
                                ...i,
                                takeStockStatus: TakeStockStatus.find(item => item.value == i
                                    .takeStockStatus).label
                                }))
                                if (this.allReceivingOrders.length > 3) {
                                    this.loadVisible = true;
                                } else {
                                    this.loadVisible = false;
                                }
                                this.hasMore = false;
                                this.status = "noMore";
                            }
                        } else {
                            this.status = 'noMore';
                            //this.allReceivingOrders = [];
                            this.loadVisible = true;
                            this.status = this.pageNo > 1 ? "more" : "noMore";
                            this.$u.toast('数据加载失败,请重试');
                        }
                    }
                })
                    })
                    .catch(() => {
                        this.isLoading = false;
                        this.status = this.pageNo > 1 ? "more" : "noMore";
                        this.$u.toast('网络错误,请检查网络');
                    });
            }
        }
    }
</script>
<style lang="scss">
    /* æ ·å¼ä¿æŒä¸å˜ */
    @import '@/common/uni-ui.scss';
    page {