xiazhengtongxue
16 小时以前 56538e602b927c232ac5b991ef84175edd2ce3ce
feat(WMS/WCS): 增加机器人历史信息记录
fix(WMS/WCS): 修复前端bug
已添加8个文件
已修改15个文件
4004 ■■■■■ 文件已修改
Code/WCS/WIDESEAWCS_Client/src/api/http.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotTaskHty.jsx 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js 127 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTaskHty.vue 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Helper/UtilConvert.cs 1125 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotTask_HtyRepository.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTask_HtyService.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask_Hty.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTask_HtyController.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotTaskInfoRepository.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTask_HtyService.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockChat.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/UtilConvert.cs 1980 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Client/src/api/http.js
@@ -12,7 +12,7 @@
let loadingInstance;
let loadingStatus = false;
if (process.env.NODE_ENV == 'development') {
    axios.defaults.baseURL = window.webConfig.webApiProduction;
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
}
else if (process.env.NODE_ENV == 'debug') {
    axios.defaults.baseURL = window.webConfig.webApiBaseUrl;
Code/WCS/WIDESEAWCS_Client/src/extension/taskinfo/robotTaskHty.jsx
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
// è¯¥æ‰©å±•文件用于任务历史页面的业务扩展。
// æ–¹æ³•目的:统一预留列表查询、保存前后和弹窗打开时的扩展入口,保持与项目内 task é¡µé¢ä¸€è‡´çš„æ‰©å±•点。
// å‚数含义:由框架按生命周期传入,包含查询参数、表单数据、行数据等上下文。
// è¿”回值说明:返回 true ä»£è¡¨ç»§ç»­é»˜è®¤è¡Œä¸ºï¼Œè¿”回 false ä»£è¡¨ä¸­æ–­é»˜è®¤è¡Œä¸ºã€‚
// å¼‚常处理说明:当前未引入外部调用;若后续新增接口调用,需在方法内补充 try-catch å¹¶è®°å½•关键业务参数。
let extension = {
  components: {
    gridHeader: "",
    gridBody: "",
    gridFooter: "",
    modelHeader: "",
    modelBody: "",
    modelFooter: "",
  },
  tableAction: "",
  buttons: { view: [], box: [], detail: [] },
  methods: {
    // æ–¹æ³•目的:页面初始化时执行自定义逻辑。
    // å‚数:无。
    // è¿”回值:无。
    onInit() {},
    // æ–¹æ³•目的:页面初始化完成后执行自定义逻辑。
    // å‚数:无。
    // è¿”回值:无。
    onInited() {},
    // æ–¹æ³•目的:查询前处理查询条件。
    // å‚数:param æŸ¥è¯¢å‚数对象。
    // è¿”回值:true ç»§ç»­æŸ¥è¯¢ï¼Œfalse ç»ˆæ­¢æŸ¥è¯¢ã€‚
    searchBefore(param) {
      return true;
    },
    // æ–¹æ³•目的:查询后处理返回结果。
    // å‚数:result åŽç«¯è¿”回数据。
    // è¿”回值:true ç»§ç»­æ¸²æŸ“,false ç»ˆæ­¢åŽç»­å¤„理。
    searchAfter(result) {
      return true;
    },
    // æ–¹æ³•目的:新增前校验或补充提交字段。
    // å‚数:formData è¡¨å•提交对象。
    // è¿”回值:true ç»§ç»­æäº¤ï¼Œfalse ç»ˆæ­¢æäº¤ã€‚
    addBefore(formData) {
      return true;
    },
    // æ–¹æ³•目的:编辑前校验或补充提交字段。
    // å‚数:formData è¡¨å•提交对象。
    // è¿”回值:true ç»§ç»­æäº¤ï¼Œfalse ç»ˆæ­¢æäº¤ã€‚
    updateBefore(formData) {
      return true;
    },
    // æ–¹æ³•目的:点击行时扩展处理。
    // å‚数:row è¡Œæ•°æ®ï¼Œcolumn åˆ—配置,event åŽŸå§‹äº‹ä»¶ã€‚
    // è¿”回值:无。
    rowClick({ row, column, event }) {},
    // æ–¹æ³•目的:编辑弹窗打开后执行扩展逻辑。
    // å‚数:row å½“前行数据。
    // è¿”回值:无。
    modelOpenAfter(row) {},
  },
};
export default extension;
Code/WCS/WIDESEAWCS_Client/src/router/viewGird.js
@@ -1,97 +1,104 @@
let viewgird = [
  {
    path: '/Sys_Log',
    name: 'sys_Log',
    component: () => import('@/views/system/Sys_Log.vue')
    path: "/Sys_Log",
    name: "sys_Log",
    component: () => import("@/views/system/Sys_Log.vue"),
  },
  {
    path: '/Sys_User',
    name: 'Sys_User',
    component: () => import('@/views/system/Sys_User.vue')
    path: "/Sys_User",
    name: "Sys_User",
    component: () => import("@/views/system/Sys_User.vue"),
  },
  {
    path: '/permission',
    name: 'permission',
    component: () => import('@/views/system/Permission.vue')
    path: "/permission",
    name: "permission",
    component: () => import("@/views/system/Permission.vue"),
  },
  {
    path: '/Sys_Dictionary',
    name: 'Sys_Dictionary',
    component: () => import('@/views/system/Sys_Dictionary.vue')
    path: "/Sys_Dictionary",
    name: "Sys_Dictionary",
    component: () => import("@/views/system/Sys_Dictionary.vue"),
  },
  {
    path: '/Sys_Role',
    name: 'Sys_Role',
    component: () => import('@/views/system/Sys_Role.vue')
    path: "/Sys_Role",
    name: "Sys_Role",
    component: () => import("@/views/system/Sys_Role.vue"),
  },
  {
    path: '/Sys_Role1',
    name: 'Sys_Role1',
    component: () => import('@/views/system/Sys_Role1.vue')
    path: "/Sys_Role1",
    name: "Sys_Role1",
    component: () => import("@/views/system/Sys_Role1.vue"),
  },
  {
    path: '/Sys_DictionaryList',
    name: 'Sys_DictionaryList',
    component: () => import('@/views/system/Sys_DictionaryList.vue')
    path: "/Sys_DictionaryList",
    name: "Sys_DictionaryList",
    component: () => import("@/views/system/Sys_DictionaryList.vue"),
  },
  {
    path: '/Sys_Tenant',
    name: 'Sys_Tenant',
    component: () => import('@/views/system/Sys_Tenant.vue')
    path: "/Sys_Tenant",
    name: "Sys_Tenant",
    component: () => import("@/views/system/Sys_Tenant.vue"),
  },
  {
    path: '/deviceInfo',
    name: 'deviceInfo',
    component: () => import('@/views/quartzJob/deviceInfo.vue')
    path: "/deviceInfo",
    name: "deviceInfo",
    component: () => import("@/views/quartzJob/deviceInfo.vue"),
  },
  {
    path: '/deviceProtocol',
    name: 'deviceProtocol',
    component: () => import('@/views/quartzJob/deviceProtocol.vue')
    path: "/deviceProtocol",
    name: "deviceProtocol",
    component: () => import("@/views/quartzJob/deviceProtocol.vue"),
  },
  {
    path: '/deviceProtocolDetail',
    name: 'deviceProtocolDetail',
    component: () => import('@/views/quartzJob/deviceProtocolDetail.vue')
    path: "/deviceProtocolDetail",
    name: "deviceProtocolDetail",
    component: () => import("@/views/quartzJob/deviceProtocolDetail.vue"),
  },
  {
    path: '/dispatchInfo',
    name: 'dispatchInfo',
    component: () => import('@/views/quartzJob/dispatchInfo.vue')
    path: "/dispatchInfo",
    name: "dispatchInfo",
    component: () => import("@/views/quartzJob/dispatchInfo.vue"),
  },
  {
    path: '/scheduler',
    name: 'scheduler',
    component: () => import('@/views/quartzJob/scheduler.vue')
  },{
    path: '/robotTask',
    name: 'robotTask',
    component: () => import('@/views/taskinfo/robotTask.vue')
    path: "/scheduler",
    name: "scheduler",
    component: () => import("@/views/quartzJob/scheduler.vue"),
  },
  {
    path: '/robotState',
    name: 'robotState',
    component: () => import('@/views/taskinfo/robotState.vue')
    path: "/robotTask",
    name: "robotTask",
    component: () => import("@/views/taskinfo/robotTask.vue"),
  },
  {
    path: '/task',
    name: 'task',
    component: () => import('@/views/taskinfo/task.vue')
  },{
    path: '/agvTask',
    name: 'agvTask',
    component: () => import('@/views/taskinfo/agvTask.vue')
    path: "/robotTaskHty",
    name: "robotTaskHty",
    component: () => import("@/views/taskinfo/robotTaskHty.vue"),
  },
  {
    path: '/taskHty',
    name: 'taskHty',
    component: () => import('@/views/taskinfo/taskHty.vue')
    path: "/robotState",
    name: "robotState",
    component: () => import("@/views/taskinfo/robotState.vue"),
  },
  {
    path: '/router',
    name: 'router',
    component: () => import('@/views/basicinfo/router.vue')
  }
    path: "/task",
    name: "task",
    component: () => import("@/views/taskinfo/task.vue"),
  },
  {
    path: "/agvTask",
    name: "agvTask",
    component: () => import("@/views/taskinfo/agvTask.vue"),
  },
  {
    path: "/taskHty",
    name: "taskHty",
    component: () => import("@/views/taskinfo/taskHty.vue"),
  },
  {
    path: "/router",
    name: "router",
    component: () => import("@/views/basicinfo/router.vue"),
  },
];
export default viewgird;
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotState.vue
@@ -12,41 +12,42 @@
export default defineComponent({
  setup() {
    const table = ref({
      key: "Id",
      key: "id",
      footer: "Foots",
      cnName: "机械手状态管理",
      name: "robotState",
      url: "/robotState/",
      sortName: "IPAddress",
      url: "/RobotState/",
      sortName: "CreateDate",
    });
    // ç¼–辑表单字段
    const editFormFields = ref({
      IPAddress: "",
      Version: "",
      IsEventSubscribed: false,
      RobotRunMode: "",
      RobotControlMode: "",
      RobotArmObject: "",
      Homed: "",
      CurrentAction: "",
      OperStatus: "",
      RobotTaskTotalNum: 0,
      IsSplitPallet: false,
      IsGroupPallet: false,
      IsInFakeBatteryMode: false,
      CurrentBatchIndex: 1,
      ChangePalletPhase: 0,
      IsScanNG: false,
      BatteryArrived: false,
      id: "",
      ipAddress: "",
      version: "",
      isEventSubscribed: false,
      robotRunMode: "",
      robotControlMode: "",
      robotArmObject: "",
      homed: "",
      currentAction: "",
      operStatus: "",
      robotTaskTotalNum: 0,
      isSplitPallet: false,
      isGroupPallet: false,
      isInFakeBatteryMode: false,
      currentBatchIndex: 1,
      changePalletPhase: 0,
      isScanNG: false,
      batteryArrived: false,
    });
    // ç¼–辑表单配置
    const editFormOptions = ref([
      [
        { title: "IP地址", field: "ipAddress", type: "string", readonly: true },
        { title: "版本号", field: "version", type: "int", readonly: true },
      ],
      // [
      //   { title: "IP地址", field: "ipAddress", type: "string", readonly: true },
      //   { title: "版本号", field: "version", type: "int", readonly: true },
      // ],
      [
        {
          title: "运行模式",
@@ -57,29 +58,46 @@
            { key: 2, value: "自动模式" },
          ],
        },
        // {
        //   title: "控制模式",
        //   field: "robotControlMode",
        //   type: "select",
        //   data: [
        //     { key: 1, value: "客户端控制" },
        //     { key: 2, value: "其他" },
        //   ],
        // },
        // {
        //   title: "手臂状态",
        //   field: "robotArmObject",
        //   type: "select",
        //   data: [
        //     { key: 0, value: "空闲" },
        //     { key: 1, value: "有物料" },
        //   ],
        // },
        {
          title: "控制模式",
          field: "robotControlMode",
          type: "select",
          title: "回零状态", field: "homed", type: "select",
          data: [
            { key: 1, value: "客户端控制" },
            { key: 2, value: "其他" },
          ],
            { key: "Homed", value: "已经回零" },
            { key: "Homing", value: "正在回零" },
          ]
        },
        {
          title: "手臂状态",
          field: "robotArmObject",
          type: "select",
          title: "当前动作", field: "currentAction", type: "select",
          data: [
            { key: 0, value: "空闲" },
            { key: 1, value: "有物料" },
          ],
            { key: "Picking", value: "正在取货" },
            { key: "Putting", value: "正在放货" },
            { key: "AllPickFinished", value: "全部取货完成" },
            { key: "AllPutFinished", value: "全部放货完成" },
            { key: "PickFinished", value: "取货完成" },
            { key: "PutFinished", value: "放货完成" },
          ]
        },
      ],
      [
        { title: "回零状态", field: "homed", type: "string" },
        { title: "当前动作", field: "currentAction", type: "string" },
        { title: "运行状态", field: "operStatus", type: "string" },
        // ],
        // [
        // { title: "运行状态", field: "operStatus", type: "string" },
      ],
      [
        { title: "任务总数", field: "robotTaskTotalNum", type: "int" },
@@ -124,51 +142,62 @@
          dataKey: "isTrue",
          data: [],
        },
        {
          title: "消息已订阅",
          field: "isEventSubscribed",
          type: "select",
          dataKey: "isTrue",
          data: [],
        },
        // {
        //   title: "消息已订阅",
        //   field: "isEventSubscribed",
        //   type: "select",
        //   dataKey: "isTrue",
        //   data: [],
        // },
      ],
    ]);
    // æœç´¢è¡¨å•字段
    const searchFormFields = ref({
      IPAddress: "",
      CurrentAction: "",
      OperStatus: "",
      ipAddress: "",
      currentAction: "",
      operStatus: "",
    });
    // æœç´¢è¡¨å•配置
    const searchFormOptions = ref([
      [
        { title: "IP地址", field: "ipAddress", type: "string" },
        { title: "IP地址", field: "ipAddress", type: "like" },
        { title: "当前动作", field: "currentAction", type: "string" },
        { title: "运行状态", field: "operStatus", type: "string" },
        {
          title: "运行状态", field: "operStatus", type: "select",
          data: [
            { key: "Picking", value: "正在取货" },
            { key: "Putting", value: "正在放货" },
            { key: "AllPickFinished", value: "全部取货完成" },
            { key: "AllPutFinished", value: "全部放货完成" },
            { key: "PickFinished", value: "取货完成" },
            { key: "PutFinished", value: "放货完成" },
          ]
        },
      ],
    ]);
    // åˆ—定义
    const columns = ref([
      { field: "ipAddress", title: "IP地址", type: "string", width: 140, align: "left" },
      { field: "id", title: "Id", type: "int", width: 90, hidden: true, readonly: true, require: true, align: "left" },
      { field: "ipAddress", title: "IP地址", type: "string", width: 160, align: "left" },
      { field: "version", title: "版本", type: "int", width: 80, align: "left" },
      { field: "robotRunMode", title: "运行模式", type: "int", width: 100, bind: { key: "robotRunMode", data: [{ key: 1, value: "手动模式" }, { key: 2, value: "自动模式" }] }, align: "center" },
      { field: "robotControlMode", title: "控制模式", type: "int", width: 100, bind: { key: "robotControlMode", data: [{ key: 1, value: "客户端控制" }, { key: 2, value: "其他" }] }, align: "center" },
      { field: "robotArmObject", title: "手臂状态", type: "int", width: 90, bind: { key: "robotArmObject", data: [{ key: 0, value: "空闲" }, { key: 1, value: "有物料" }] }, align: "center" },
      // { field: "robotControlMode", title: "控制模式", type: "int", width: 100, bind: { key: "robotControlMode", data: [{ key: 1, value: "客户端控制" }, { key: 2, value: "其他" }] }, align: "center" },
      // { field: "robotArmObject", title: "手臂状态", type: "int", width: 90, bind: { key: "robotArmObject", data: [{ key: 0, value: "空闲" }, { key: 1, value: "有物料" }] }, align: "center" },
      { field: "homed", title: "回零状态", type: "string", width: 100, align: "center", bind: { key: "homed", data: [{ key: "Homed", value: "回零" }, { key: "Homing", value: "回零中" }] }, },
      { field: "currentAction", title: "当前动作", type: "string", width: 100, align: "center", bind: { key: "currentAction", data: [{ key: "Picking", value: "正在取货" }, { key: "Putting", value: "正在放货" }, { key: "AllPickFinished", value: "全部取货完成" }, { key: "AllPutFinished", value: "全部放货完成" }, { key: "PickFinished", value: "取货完成" }, { key: "PutFinished", value: "放货完成" }] }, },
      { field: "operStatus", title: "运行状态", type: "string", width: 100, align: "center", hidden: true },
      // { field: "operStatus", title: "运行状态", type: "string", width: 100, align: "center", hidden: true },
      { field: "robotTaskTotalNum", title: "任务总数", type: "int", width: 90, align: "center" },
      { field: "isSplitPallet", title: "拆盘", type: "byte", width: 60, align: "center", bind: { key: "isTrue", data: [] }, },
      { field: "isGroupPallet", title: "组盘", type: "byte", width: 60, align: "center" , bind: { key: "isTrue", data: [] }, },
      { field: "isInFakeBatteryMode", title: "假电芯", type: "byte", width: 70, align: "center" , bind: { key: "isTrue", data: [] }, },
      { field: "isGroupPallet", title: "组盘", type: "byte", width: 60, align: "center", bind: { key: "isTrue", data: [] }, },
      { field: "isInFakeBatteryMode", title: "假电芯", type: "byte", width: 70, align: "center", bind: { key: "isTrue", data: [] }, },
      { field: "currentBatchIndex", title: "批次", type: "int", width: 60, align: "center" },
      { field: "changePalletPhase", title: "换盘阶段", type: "int", width: 80, align: "center" },
      { field: "isScanNG", title: "扫码NG", type: "byte", width: 80, align: "center" , bind: { key: "isTrue", data: [] }, },
      { field: "batteryArrived", title: "电芯到位", type: "byte", width: 80, align: "center" , bind: { key: "isTrue", data: [] }, },
      { field: "isEventSubscribed", title: "已订阅", type: "byte", width: 70, align: "center", bind: { key: "isTrue", data: [] },  },
      { field: "isScanNG", title: "扫码NG", type: "byte", width: 80, align: "center", bind: { key: "isTrue", data: [] }, },
      { field: "batteryArrived", title: "电芯到位", type: "byte", width: 80, align: "center", bind: { key: "isTrue", data: [] }, },
      // { field: "isEventSubscribed", title: "已订阅", type: "byte", width: 70, align: "center", bind: { key: "isTrue", data: [] },  },
    ]);
    const detail = ref({
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTask.vue
@@ -154,7 +154,7 @@
        field: "robotRoadway",
        title: "巷道",
        type: "string",
        width: 100,
        width: 120,
        align: "left",
      },
      {
Code/WCS/WIDESEAWCS_Client/src/views/taskinfo/robotTaskHty.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,290 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :extend="extend"
  >
  </view-grid>
</template>
<script>
import extend from "@/extension/taskinfo/robotTaskHty.jsx";
import { ref, defineComponent } from "vue";
export default defineComponent({
  setup() {
    const table = ref({
      key: "robotTaskId",           // ä¸»é”®å­—段名
      footer: "Foots",
      cnName: "机器人历史任务",      // ä¸­æ–‡åç§°
      name: "robotTaskHty",         // è¡¨å
      url: "/RobotTask_Hty/",       // API路径
      sortName: "insertTime",       // é»˜è®¤æŽ’序字段(按移入时间排序)
    });
    // ç¼–辑表单字段(历史表通常只读,但保留结构)
    const editFormFields = ref({});
    // ç¼–辑表单配置(历史表通常只读)
    const editFormOptions = ref([]);
    // æœç´¢è¡¨å•字段
    const searchFormFields = ref({
      robotTaskNum: "",
      robotRoadway: "",
      robotTaskType: "",
      robotTaskState: "",
      robotSourceAddress: "",
      robotTargetAddress: "",
      operateType: "",
      insertTime: "",
      creater: "",
      createDate: "",
    });
    // æœç´¢è¡¨å•配置(三行布局)
    const searchFormOptions = ref([
      [
        { title: "任务编号", field: "robotTaskNum", type: "int" },
        { title: "巷道", field: "robotRoadway", type: "like" },
        {
          title: "任务类型",
          field: "robotTaskType",
          type: "selectList",
          dataKey: "taskType",
          data: [],
        },
        {
          title: "任务状态",
          field: "robotTaskState",
          type: "selectList",
          dataKey: "taskState",
          data: [],
        },
      ],
      [
        { title: "来源地址", field: "robotSourceAddress", type: "like" },
        { title: "目标地址", field: "robotTargetAddress", type: "like" },
        { title: "操作类型", field: "operateType", type: "like" },
        { title: "移入历史时间", field: "insertTime", type: "datetime" },
      ],
      [
        { title: "来源线代码", field: "robotSourceAddressLineCode", type: "like" },
        { title: "目标线代码", field: "robotTargetAddressLineCode", type: "like" },
        { title: "创建人", field: "creater", type: "like" },
        { title: "创建时间", field: "createDate", type: "datetime" },
      ],
    ]);
    // åˆ—配置
    const columns = ref([
      {
        field: "robotTaskId",
        title: "历史ID",
        type: "int",
        width: 90,
        hidden: true,        // éšè—åŽ†å²è¡¨ä¸»é”®
        readonly: true,
        require: true,
        align: "left",
      },
      {
        field: "sourceId",
        title: "任务号",
        type: "int",
        width: 100,
        align: "left",
      },
      {
        field: "robotTaskNum",
        title: "任务编号",
        type: "int",
        width: 100,
        align: "left",
        sortable: true,
      },
      {
        field: "robotRoadway",
        title: "巷道",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "robotTaskType",
        title: "任务类型",
        type: "int",
        width: 100,
        align: "left",
        bind: { key: "taskType", data: [] },
      },
      {
        field: "robotTaskState",
        title: "任务状态",
        type: "int",
        width: 120,
        align: "left",
        bind: { key: "taskState", data: [] },
      },
      {
        field: "robotTaskTotalNum",
        title: "任务总数",
        type: "int",
        width: 90,
        align: "left",
      },
      {
        field: "robotSourceAddress",
        title: "来源地址",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "robotTargetAddress",
        title: "目标地址",
        type: "string",
        width: 120,
        align: "left",
      },
      {
        field: "robotSourceAddressLineCode",
        title: "来源线体地址",
        type: "string",
        width: 130,
        align: "left",
      },
      {
        field: "robotTargetAddressLineCode",
        title: "目标线体地址",
        type: "string",
        width: 130,
        align: "left",
      },
      {
        field: "robotSourceAddressPalletCode",
        title: "来源托盘",
        type: "string",
        width: 130,
        align: "left",
      },
      {
        field: "robotTargetAddressPalletCode",
        title: "目标托盘",
        type: "string",
        width: 130,
        align: "left",
      },
      {
        field: "robotExceptionMessage",
        title: "异常信息",
        type: "string",
        width: 200,
        align: "left",
        overflow: "ellipsis",
        tooltip: true,  // é¼ æ ‡æ‚¬åœæ˜¾ç¤ºå®Œæ•´å†…容
      },
      {
        field: "robotGrade",
        title: "优先级",
        type: "int",
        width: 80,
        align: "left",
        bind: {
          key: "robotGrade",
          data: [
            { id: 1, name: "低" },
            { id: 2, name: "普通" },
            { id: 3, name: "高" },
            { id: 4, name: "紧急" },
          ],
        },
      },
      {
        field: "operateType",
        title: "操作类型",
        type: "string",
        width: 120,
        align: "left",
        sortable: true,
      },
      {
        field: "insertTime",
        title: "移入历史时间",
        type: "datetime",
        width: 170,
        align: "left",
        sortable: true,
      },
      {
        field: "robotDispatchertime",
        title: "调度时间",
        type: "datetime",
        width: 160,
        align: "left",
      },
      {
        field: "robotRemark",
        title: "备注",
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "creater",
        title: "创建人",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "createDate",
        title: "创建时间",
        type: "datetime",
        width: 160,
        align: "left",
      },
      {
        field: "modifier",
        title: "修改人",
        type: "string",
        width: 100,
        align: "left",
      },
      {
        field: "modifyDate",
        title: "修改时间",
        type: "datetime",
        width: 160,
        align: "left",
      },
    ]);
    // è¯¦æƒ…弹窗配置
    const detail = ref({
      cnName: "机器人历史任务详情",
      table: "robotTaskHty",
      key: "robotTaskId",
      sortName: "insertTime",
      columns: columns.value.filter(col => !col.hidden), // ä½¿ç”¨éžéšè—å­—段
    });
    return {
      table,
      extend,
      editFormFields,
      editFormOptions,
      searchFormFields,
      searchFormOptions,
      columns,
      detail,
    };
  },
});
</script>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Helper/UtilConvert.cs
@@ -1,565 +1,562 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WIDESEAWCS_Core.Const;
using WIDESEAWCS_Core.Enums;
namespace WIDESEAWCS_Core.Helper
{
    public static class UtilConvert
    {
        private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
        private static long longTime = 621355968000000000;
        private static int samllTime = 10000000;
        /// <summary>
        /// å°†æ—¶é—´æˆ³è½¬æ¢ä¸ºæœ¬åœ°æ—¥æœŸæ—¶é—´
        /// </summary>
        /// <param name="timeStamp">要转换的时间戳对象</param>
        /// <returns>转换后的本地DateTime对象</returns>
        /// <remarks>如果参数为null,则返回默认起始日期</remarks>
        public static DateTime GetTimeSpmpToDate(this object timeStamp)
        {
            if (timeStamp == null) return dateStart;
            DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime();
            return dateTime;
        }
        /// <summary>
        /// å°†å¯¹è±¡åºåˆ—化为JSON字符串
        /// </summary>
        /// <param name="obj">要序列化的对象</param>
        /// <param name="formatDate">日期格式化设置,默认为"yyyy-MM-dd HH:mm:ss"格式</param>
        /// <returns>序列化后的JSON字符串,如果对象为null则返回null</returns>
        public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
        {
            if (obj == null) return null;
            formatDate = formatDate ?? new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            };
            return JsonConvert.SerializeObject(obj, formatDate);
        }
        /// <summary>
        /// å°†JSON字符串反序列化为指定类型的对象
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="json">要反序列化的JSON字符串</param>
        /// <returns>反序列化后的对象实例,如果输入为空则返回默认值</returns>
        /// <remarks>
        /// å½“输入为"{}"时会自动转换为"[]"处理
        /// </remarks>
        public static T DeserializeObject<T>(this string json)
        {
            if (string.IsNullOrEmpty(json))
            {
                return default(T);
            }
            if (json == "{}")
            {
                json = "[]";
            }
            return JsonConvert.DeserializeObject<T>(json);
        }
        /// <summary>
        /// å°†å­—符串的首字母转换为小写
        /// </summary>
        /// <param name="thisValue">要处理的字符串</param>
        /// <returns>首字母小写的字符串,若输入为空则返回空字符串</returns>
        public static string FirstLetterToLower(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToLower() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        /// å°†å­—符串的首字母转换为大写
        /// </summary>
        /// <param name="thisValue">要处理的字符串</param>
        /// <returns>首字母大写的字符串,若输入为空则返回空字符串</returns>
        public static string FirstLetterToUpper(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToUpper() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæ•´åž‹å€¼
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的整型值,转换失败返回0</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理null值、DBNull.Value和枚举类型
        /// </remarks>
        public static int ObjToInt(this object thisValue)
        {
            int reval = 0;
            if (thisValue == null) return 0;
            if (thisValue is Enum && thisValue != DBNull.Value && Enum.TryParse(thisValue.GetType(), thisValue.ToString(), out var val))
            {
                return Convert.ToInt32(val.ChangeType(typeof(int)));
            }
            if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†åŒç²¾åº¦æµ®ç‚¹æ•°è½¬æ¢ä¸º32位有符号整数
        /// </summary>
        /// <param name="thisValue">要转换的双精度浮点数</param>
        /// <returns>转换后的32位有符号整数</returns>
        public static int DoubleToInt(this double thisValue)
        {
            int reval = 0;
            return Convert.ToInt32(thisValue);
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæ•´æ•°ï¼Œè‹¥è½¬æ¢å¤±è´¥åˆ™è¿”回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的错误值</param>
        /// <returns>转换后的整数值或指定的错误值</returns>
        public static int ObjToInt(this object thisValue, int errorValue)
        {
            int reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé•¿æ•´åž‹(long)
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的长整型值,转换失败或为null时返回0</returns>
        /// <remarks>
        /// å¤„理DBNull.Value情况,并尝试将对象转换为long类型
        /// </remarks>
        public static long ObjToLong(this object thisValue)
        {
            long reval = 0;
            if (thisValue == null) return 0;
            if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé‡‘额(double类型)。若转换失败则返回0。
        /// </summary>
        /// <param name="thisValue">待转换的对象</param>
        /// <returns>转换后的金额值,失败返回0</returns>
        public static double ObjToMoney(this object thisValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé‡‘额(double)类型,转换失败时返回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的double值或指定的错误值</returns>
        public static double ObjToMoney(this object thisValue, double errorValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå­—符串,若对象为null则返回空字符串
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>去除前后空格的字符串结果</returns>
        public static string ObjToString(this object thisValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return "";
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ä¸ºç©ºæˆ–null值
        /// </summary>
        /// <param name="thisValue">要判断的对象</param>
        /// <returns>当对象不为空且不等于"undefined"或"null"字符串时返回true,否则返回false</returns>
        public static bool IsNotEmptyOrNull(this object thisValue)
        {
            return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null";
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå­—符串,如果对象为null则返回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">当对象为null时返回的值</param>
        /// <returns>对象的字符串表示或指定的错误值</returns>
        public static string ObjToString(this object thisValue, string errorValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return errorValue;
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ºnull、DBNull或空字符串
        /// </summary>
        /// <param name="thisValue">要检查的对象</param>
        /// <returns>如果对象为null、DBNull或空字符串则返回true,否则返回false</returns>
        public static bool IsNullOrEmpty(this object thisValue) => thisValue == null || thisValue == DBNull.Value || string.IsNullOrWhiteSpace(thisValue.ToString());
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDecimal类型
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的Decimal值,转换失败返回0</returns>
        public static Decimal ObjToDecimal(this object thisValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDecimal类型,若转换失败则返回指定的默认值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的Decimal值或指定的默认值</returns>
        public static Decimal ObjToDecimal(this object thisValue, decimal errorValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDateTime类型
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的DateTime值,转换失败返回DateTime.MinValue</returns>
        public static DateTime ObjToDate(this object thisValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                reval = Convert.ToDateTime(thisValue);
            }
            return reval;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDateTime类型,转换失败时返回指定的默认值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的DateTime值或指定的默认值</returns>
        public static DateTime ObjToDate(this object thisValue, DateTime errorValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå¸ƒå°”值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的布尔值,转换失败时返回false</returns>
        public static bool ObjToBool(this object thisValue)
        {
            bool reval = false;
            if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†DateTime转换为Unix时间戳(秒级)
        /// </summary>
        /// <param name="thisValue">需要转换的DateTime对象</param>
        /// <returns>返回表示Unix时间戳的字符串</returns>
        public static string DateToTimeStamp(this DateTime thisValue)
        {
            TimeSpan ts = thisValue - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæŒ‡å®šç±»åž‹
        /// </summary>
        /// <param name="value">要转换的对象</param>
        /// <param name="type">目标类型</param>
        /// <returns>转换后的对象</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理null值、枚举类型、泛型类型、Guid、Version等特殊类型的转换。
        /// å¦‚果转换失败或类型不匹配,将返回原始值或抛出异常。
        /// </remarks>
        public static object ChangeType(this object value, Type type)
        {
            if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
            if (value == null) return null;
            if (type == value.GetType()) return value;
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value as string);
                else
                    return Enum.ToObject(type, value);
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = ChangeType(value, innerType);
                return Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid)) return new Guid(value as string);
            if (value is string && type == typeof(Version)) return new Version(value as string);
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }
        /// <summary>
        /// å°†å¯¹è±¡å€¼è½¬æ¢ä¸ºæŒ‡å®šç±»åž‹çš„æ³›åž‹åˆ—表。
        /// </summary>
        /// <param name="value">待转换的对象值</param>
        /// <param name="type">目标列表元素类型</param>
        /// <returns>转换后的泛型列表对象,若输入为null则返回默认值</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理以括号包裹的字符串格式(如"(1,2,3)"或"("a","b")"),
        /// è‡ªåŠ¨åŽ»é™¤åˆ†éš”ç¬¦å¹¶å°†å…ƒç´ è½¬æ¢ä¸ºç›®æ ‡ç±»åž‹åŽæ·»åŠ åˆ°åˆ—è¡¨ã€‚
        /// </remarks>
        public static object ChangeTypeList(this object value, Type type)
        {
            if (value == null) return default;
            var gt = typeof(List<>).MakeGenericType(type);
            dynamic lis = Activator.CreateInstance(gt);
            var addMethod = gt.GetMethod("Add");
            string values = value.ToString();
            if (values != null && values.StartsWith("(") && values.EndsWith(")"))
            {
                string[] splits;
                if (values.Contains("\",\""))
                {
                    splits = values.Remove(values.Length - 2, 2)
                        .Remove(0, 2)
                        .Split("\",\"");
                }
                else
                {
                    splits = values.Remove(0, 1)
                        .Remove(values.Length - 2, 1)
                        .Split(",");
                }
                foreach (var split in splits)
                {
                    var str = split;
                    if (split.StartsWith("\"") && split.EndsWith("\""))
                    {
                        str = split.Remove(0, 1)
                            .Remove(split.Length - 2, 1);
                    }
                    addMethod.Invoke(lis, new object[] { ChangeType(str, type) });
                }
            }
            return lis;
        }
        /// <summary>
        /// å°†å¯¹è±¡åºåˆ—化为JSON字符串
        /// </summary>
        /// <param name="value">要序列化的对象</param>
        /// <returns>对象的JSON字符串表示</returns>
        public static string ToJson(this object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦å¯ä»¥è½¬æ¢ä¸ºæ•´æ•°
        /// </summary>
        /// <param name="obj">要判断的对象</param>
        /// <returns>如果可以转换为整数返回true,否则返回false</returns>
        public static bool IsInt(this object obj)
        {
            if (obj == null)
                return false;
            bool reslut = Int32.TryParse(obj.ToString(), out int _number);
            return reslut;
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ºæœ‰æ•ˆæ—¥æœŸæ ¼å¼
        /// </summary>
        /// <param name="str">待检测的对象</param>
        /// <returns>true表示是有效日期,false则不是</returns>
        /// <remarks>此方法是扩展方法,通过调用IsDate(out _)实现</remarks>
        public static bool IsDate(this object str)
        {
            return str.IsDate(out _);
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦å¯ä»¥è½¬æ¢ä¸ºæœ‰æ•ˆçš„æ—¥æœŸæ—¶é—´
        /// </summary>
        /// <param name="str">要判断的对象</param>
        /// <param name="dateTime">输出转换后的日期时间值</param>
        /// <returns>如果转换成功返回true,否则返回false</returns>
        public static bool IsDate(this object str, out DateTime dateTime)
        {
            dateTime = DateTime.Now;
            if (str == null || str.ToString() == "")
            {
                return false;
            }
            return DateTime.TryParse(str.ToString(), out dateTime);
        }
        /// <summary>
        /// åˆ¤æ–­å­—符串是否可以转换为数字
        /// </summary>
        /// <param name="str">要检查的字符串</param>
        /// <param name="formatString">格式字符串(未使用)</param>
        /// <returns>如果字符串可以转换为数字则返回true,否则返回false</returns>
        /// <remarks>
        /// ä½¿ç”¨æ­£åˆ™è¡¨è¾¾å¼éªŒè¯å­—符串是否为数字格式,支持正负号和小数点
        /// </remarks>
        public static bool IsNumber(this string str, string formatString)
        {
            if (string.IsNullOrEmpty(str)) return false;
            return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$");
        }
        /// <summary>
        /// åˆ¤æ–­å­—符串是否为有效的Guid格式
        /// </summary>
        /// <param name="guid">要验证的字符串</param>
        /// <returns>如果字符串是有效的Guid格式则返回true,否则返回false</returns>
        public static bool IsGuid(this string guid)
        {
            Guid newId;
            return guid.GetGuid(out newId);
        }
        /// <summary>
        /// å°†å­—符串转换为Guid类型
        /// </summary>
        /// <param name="guid">要转换的字符串</param>
        /// <param name="outId">输出转换后的Guid</param>
        /// <returns>转换成功返回true,否则返回false</returns>
        public static bool GetGuid(this string guid, out Guid outId)
        {
            Guid emptyId = Guid.Empty;
            return Guid.TryParse(guid, out outId);
        }
        /// <summary>
        /// å°†å­—符串类型的条件转换为对应的Linq表达式类型
        /// </summary>
        /// <param name="stringType">表示条件的字符串</param>
        /// <returns>对应的Linq表达式类型枚举值</returns>
        /// <remarks>
        /// è¯¥æ–¹æ³•用于将前端传递的条件字符串映射为后端Linq查询使用的表达式类型,
        /// æ”¯æŒåŒ…含、大于等于、小于等于、大于、小于、模糊匹配等常见条件类型,
        /// é»˜è®¤è¿”回等于(Equal)类型
        /// </remarks>
        public static LinqExpressionType GetLinqCondition(this string stringType)
        {
            LinqExpressionType linqExpression;
            switch (stringType)
            {
                case HtmlElementType.Contains:
                case HtmlElementType.selectlist:
                case nameof(HtmlElementType.Contains):
                    linqExpression = LinqExpressionType.In;
                    break;
                case HtmlElementType.ThanOrEqual:
                case nameof(HtmlElementType.ThanOrEqual):
                case HtmlElementType.thanorequal:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.LessOrEqual:
                case nameof(HtmlElementType.LessOrEqual):
                case HtmlElementType.lessorequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                case HtmlElementType.GT:
                case nameof(HtmlElementType.GT):
                    linqExpression = LinqExpressionType.GreaterThan;
                    break;
                case HtmlElementType.lt:
                    linqExpression = LinqExpressionType.LessThan;
                    break;
                case HtmlElementType.like:
                    linqExpression = LinqExpressionType.Contains;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WIDESEAWCS_Core.Const;
using WIDESEAWCS_Core.Enums;
namespace WIDESEAWCS_Core.Helper
{
    public static class UtilConvert
    {
        private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
        private static long longTime = 621355968000000000;
        private static int samllTime = 10000000;
        /// <summary>
        /// å°†æ—¶é—´æˆ³è½¬æ¢ä¸ºæœ¬åœ°æ—¥æœŸæ—¶é—´
        /// </summary>
        /// <param name="timeStamp">要转换的时间戳对象</param>
        /// <returns>转换后的本地DateTime对象</returns>
        /// <remarks>如果参数为null,则返回默认起始日期</remarks>
        public static DateTime GetTimeSpmpToDate(this object timeStamp)
        {
            if (timeStamp == null) return dateStart;
            DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime();
            return dateTime;
        }
        /// <summary>
        /// å°†å¯¹è±¡åºåˆ—化为JSON字符串
        /// </summary>
        /// <param name="obj">要序列化的对象</param>
        /// <param name="formatDate">日期格式化设置,默认为"yyyy-MM-dd HH:mm:ss"格式</param>
        /// <returns>序列化后的JSON字符串,如果对象为null则返回null</returns>
        public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
        {
            if (obj == null) return null;
            formatDate = formatDate ?? new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            };
            return JsonConvert.SerializeObject(obj, formatDate);
        }
        /// <summary>
        /// å°†JSON字符串反序列化为指定类型的对象
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="json">要反序列化的JSON字符串</param>
        /// <returns>反序列化后的对象实例,如果输入为空则返回默认值</returns>
        /// <remarks>
        /// å½“输入为"{}"时会自动转换为"[]"处理
        /// </remarks>
        public static T DeserializeObject<T>(this string json)
        {
            if (string.IsNullOrEmpty(json))
            {
                return default(T);
            }
            if (json == "{}")
            {
                json = "[]";
            }
            return JsonConvert.DeserializeObject<T>(json);
        }
        /// <summary>
        /// å°†å­—符串的首字母转换为小写
        /// </summary>
        /// <param name="thisValue">要处理的字符串</param>
        /// <returns>首字母小写的字符串,若输入为空则返回空字符串</returns>
        public static string FirstLetterToLower(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToLower() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        /// å°†å­—符串的首字母转换为大写
        /// </summary>
        /// <param name="thisValue">要处理的字符串</param>
        /// <returns>首字母大写的字符串,若输入为空则返回空字符串</returns>
        public static string FirstLetterToUpper(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToUpper() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæ•´åž‹å€¼
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的整型值,转换失败返回0</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理null值、DBNull.Value和枚举类型
        /// </remarks>
        public static int ObjToInt(this object thisValue)
        {
            int reval = 0;
            if (thisValue == null) return 0;
            if (thisValue is Enum && thisValue != DBNull.Value && Enum.TryParse(thisValue.GetType(), thisValue.ToString(), out var val))
            {
                return Convert.ToInt32(val.ChangeType(typeof(int)));
            }
            if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†åŒç²¾åº¦æµ®ç‚¹æ•°è½¬æ¢ä¸º32位有符号整数
        /// </summary>
        /// <param name="thisValue">要转换的双精度浮点数</param>
        /// <returns>转换后的32位有符号整数</returns>
        public static int DoubleToInt(this double thisValue)
        {
            int reval = 0;
            return Convert.ToInt32(thisValue);
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæ•´æ•°ï¼Œè‹¥è½¬æ¢å¤±è´¥åˆ™è¿”回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的错误值</param>
        /// <returns>转换后的整数值或指定的错误值</returns>
        public static int ObjToInt(this object thisValue, int errorValue)
        {
            int reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé•¿æ•´åž‹(long)
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的长整型值,转换失败或为null时返回0</returns>
        /// <remarks>
        /// å¤„理DBNull.Value情况,并尝试将对象转换为long类型
        /// </remarks>
        public static long ObjToLong(this object thisValue)
        {
            long reval = 0;
            if (thisValue == null) return 0;
            if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé‡‘额(double类型)。若转换失败则返回0。
        /// </summary>
        /// <param name="thisValue">待转换的对象</param>
        /// <returns>转换后的金额值,失败返回0</returns>
        public static double ObjToMoney(this object thisValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºé‡‘额(double)类型,转换失败时返回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的double值或指定的错误值</returns>
        public static double ObjToMoney(this object thisValue, double errorValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå­—符串,若对象为null则返回空字符串
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>去除前后空格的字符串结果</returns>
        public static string ObjToString(this object thisValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return "";
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ä¸ºç©ºæˆ–null值
        /// </summary>
        /// <param name="thisValue">要判断的对象</param>
        /// <returns>当对象不为空且不等于"undefined"或"null"字符串时返回true,否则返回false</returns>
        public static bool IsNotEmptyOrNull(this object thisValue)
        {
            return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null";
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå­—符串,如果对象为null则返回指定的错误值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">当对象为null时返回的值</param>
        /// <returns>对象的字符串表示或指定的错误值</returns>
        public static string ObjToString(this object thisValue, string errorValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return errorValue;
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ºnull、DBNull或空字符串
        /// </summary>
        /// <param name="thisValue">要检查的对象</param>
        /// <returns>如果对象为null、DBNull或空字符串则返回true,否则返回false</returns>
        public static bool IsNullOrEmpty(this object thisValue) => thisValue == null || thisValue == DBNull.Value || string.IsNullOrWhiteSpace(thisValue.ToString());
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDecimal类型
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的Decimal值,转换失败返回0</returns>
        public static Decimal ObjToDecimal(this object thisValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDecimal类型,若转换失败则返回指定的默认值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的Decimal值或指定的默认值</returns>
        public static Decimal ObjToDecimal(this object thisValue, decimal errorValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDateTime类型
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的DateTime值,转换失败返回DateTime.MinValue</returns>
        public static DateTime ObjToDate(this object thisValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                reval = Convert.ToDateTime(thisValue);
            }
            return reval;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºDateTime类型,转换失败时返回指定的默认值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <param name="errorValue">转换失败时返回的默认值</param>
        /// <returns>转换成功的DateTime值或指定的默认值</returns>
        public static DateTime ObjToDate(this object thisValue, DateTime errorValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºå¸ƒå°”值
        /// </summary>
        /// <param name="thisValue">要转换的对象</param>
        /// <returns>转换后的布尔值,转换失败时返回false</returns>
        public static bool ObjToBool(this object thisValue)
        {
            bool reval = false;
            if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// å°†DateTime转换为Unix时间戳(秒级)
        /// </summary>
        /// <param name="thisValue">需要转换的DateTime对象</param>
        /// <returns>返回表示Unix时间戳的字符串</returns>
        public static string DateToTimeStamp(this DateTime thisValue)
        {
            TimeSpan ts = thisValue - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        /// <summary>
        /// å°†å¯¹è±¡è½¬æ¢ä¸ºæŒ‡å®šç±»åž‹
        /// </summary>
        /// <param name="value">要转换的对象</param>
        /// <param name="type">目标类型</param>
        /// <returns>转换后的对象</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理null值、枚举类型、泛型类型、Guid、Version等特殊类型的转换。
        /// å¦‚果转换失败或类型不匹配,将返回原始值或抛出异常。
        /// </remarks>
        public static object ChangeType(this object value, Type type)
        {
            if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
            if (value == null) return null;
            if (type == value.GetType()) return value;
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value as string);
                else
                    return Enum.ToObject(type, value);
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = ChangeType(value, innerType);
                return Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid)) return new Guid(value as string);
            if (value is string && type == typeof(Version)) return new Version(value as string);
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }
        /// <summary>
        /// å°†å¯¹è±¡å€¼è½¬æ¢ä¸ºæŒ‡å®šç±»åž‹çš„æ³›åž‹åˆ—表。
        /// </summary>
        /// <param name="value">待转换的对象值</param>
        /// <param name="type">目标列表元素类型</param>
        /// <returns>转换后的泛型列表对象,若输入为null则返回默认值</returns>
        /// <remarks>
        /// æ”¯æŒå¤„理以括号包裹的字符串格式(如"(1,2,3)"或"("a","b")"),
        /// è‡ªåŠ¨åŽ»é™¤åˆ†éš”ç¬¦å¹¶å°†å…ƒç´ è½¬æ¢ä¸ºç›®æ ‡ç±»åž‹åŽæ·»åŠ åˆ°åˆ—è¡¨ã€‚
        /// </remarks>
        public static object ChangeTypeList(this object value, Type type)
        {
            if (value == null) return default;
            var gt = typeof(List<>).MakeGenericType(type);
            dynamic lis = Activator.CreateInstance(gt);
            var addMethod = gt.GetMethod("Add");
            string values = value.ToString();
            if (values != null && values.StartsWith("(") && values.EndsWith(")"))
            {
                string[] splits;
                if (values.Contains("\",\""))
                {
                    splits = values.Remove(values.Length - 2, 2)
                        .Remove(0, 2)
                        .Split("\",\"");
                }
                else
                {
                    splits = values.Remove(0, 1)
                        .Remove(values.Length - 2, 1)
                        .Split(",");
                }
                foreach (var split in splits)
                {
                    var str = split;
                    if (split.StartsWith("\"") && split.EndsWith("\""))
                    {
                        str = split.Remove(0, 1)
                            .Remove(split.Length - 2, 1);
                    }
                    addMethod.Invoke(lis, new object[] { ChangeType(str, type) });
                }
            }
            return lis;
        }
        /// <summary>
        /// å°†å¯¹è±¡åºåˆ—化为JSON字符串
        /// </summary>
        /// <param name="value">要序列化的对象</param>
        /// <returns>对象的JSON字符串表示</returns>
        public static string ToJson(this object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦å¯ä»¥è½¬æ¢ä¸ºæ•´æ•°
        /// </summary>
        /// <param name="obj">要判断的对象</param>
        /// <returns>如果可以转换为整数返回true,否则返回false</returns>
        public static bool IsInt(this object obj)
        {
            if (obj == null)
                return false;
            bool reslut = Int32.TryParse(obj.ToString(), out int _number);
            return reslut;
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ºæœ‰æ•ˆæ—¥æœŸæ ¼å¼
        /// </summary>
        /// <param name="str">待检测的对象</param>
        /// <returns>true表示是有效日期,false则不是</returns>
        /// <remarks>此方法是扩展方法,通过调用IsDate(out _)实现</remarks>
        public static bool IsDate(this object str)
        {
            return str.IsDate(out _);
        }
        /// <summary>
        /// åˆ¤æ–­å¯¹è±¡æ˜¯å¦å¯ä»¥è½¬æ¢ä¸ºæœ‰æ•ˆçš„æ—¥æœŸæ—¶é—´
        /// </summary>
        /// <param name="str">要判断的对象</param>
        /// <param name="dateTime">输出转换后的日期时间值</param>
        /// <returns>如果转换成功返回true,否则返回false</returns>
        public static bool IsDate(this object str, out DateTime dateTime)
        {
            dateTime = DateTime.Now;
            if (str == null || str.ToString() == "")
            {
                return false;
            }
            return DateTime.TryParse(str.ToString(), out dateTime);
        }
        /// <summary>
        /// åˆ¤æ–­å­—符串是否可以转换为数字
        /// </summary>
        /// <param name="str">要检查的字符串</param>
        /// <param name="formatString">格式字符串(未使用)</param>
        /// <returns>如果字符串可以转换为数字则返回true,否则返回false</returns>
        /// <remarks>
        /// ä½¿ç”¨æ­£åˆ™è¡¨è¾¾å¼éªŒè¯å­—符串是否为数字格式,支持正负号和小数点
        /// </remarks>
        public static bool IsNumber(this string str, string formatString)
        {
            if (string.IsNullOrEmpty(str)) return false;
            return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$");
        }
        /// <summary>
        /// åˆ¤æ–­å­—符串是否为有效的Guid格式
        /// </summary>
        /// <param name="guid">要验证的字符串</param>
        /// <returns>如果字符串是有效的Guid格式则返回true,否则返回false</returns>
        public static bool IsGuid(this string guid)
        {
            Guid newId;
            return guid.GetGuid(out newId);
        }
        /// <summary>
        /// å°†å­—符串转换为Guid类型
        /// </summary>
        /// <param name="guid">要转换的字符串</param>
        /// <param name="outId">输出转换后的Guid</param>
        /// <returns>转换成功返回true,否则返回false</returns>
        public static bool GetGuid(this string guid, out Guid outId)
        {
            Guid emptyId = Guid.Empty;
            return Guid.TryParse(guid, out outId);
        }
        /// <summary>
        /// å°†å­—符串类型的条件转换为对应的Linq表达式类型
        /// </summary>
        /// <param name="stringType">表示条件的字符串</param>
        /// <returns>对应的Linq表达式类型枚举值</returns>
        /// <remarks>
        /// è¯¥æ–¹æ³•用于将前端传递的条件字符串映射为后端Linq查询使用的表达式类型,
        /// æ”¯æŒåŒ…含、大于等于、小于等于、大于、小于、模糊匹配等常见条件类型,
        /// é»˜è®¤è¿”回等于(Equal)类型
        /// </remarks>
        public static LinqExpressionType GetLinqCondition(this string stringType)
        {
            LinqExpressionType linqExpression;
            switch (stringType)
            {
                case HtmlElementType.Contains:
                case HtmlElementType.selectlist:
                case nameof(HtmlElementType.Contains):
                    linqExpression = LinqExpressionType.In;
                    break;
                case HtmlElementType.notequal:
                    linqExpression = LinqExpressionType.NotEqual;
                    break;
                case HtmlElementType.notequal:
                    linqExpression = LinqExpressionType.NotEqual;
                    break;
                default:
                    linqExpression = LinqExpressionType.Equal;
                    break;
            }
            return linqExpression;
        }
    }
}
                case HtmlElementType.ThanOrEqual:
                case nameof(HtmlElementType.ThanOrEqual):
                case HtmlElementType.thanorequal:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.LessOrEqual:
                case nameof(HtmlElementType.LessOrEqual):
                case HtmlElementType.lessorequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                case HtmlElementType.GT:
                case nameof(HtmlElementType.GT):
                    linqExpression = LinqExpressionType.GreaterThan;
                    break;
                case HtmlElementType.lt:
                    linqExpression = LinqExpressionType.LessThan;
                    break;
                case HtmlElementType.like:
                    linqExpression = LinqExpressionType.Contains;
                    break;
                case HtmlElementType.notequal:
                    linqExpression = LinqExpressionType.NotEqual;
                    break;
                default:
                    linqExpression = LinqExpressionType.Equal;
                    break;
            }
            return linqExpression;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoRepository/IRobotTask_HtyRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_IRobotTaskInfoRepository
{
    public interface IRobotTask_HtyRepository : IRepository<Dt_RobotTask_Hty>
    {
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs
@@ -54,6 +54,7 @@
        /// </summary>
        public List<int> TaskRobotTypes { get; }
        public bool DeleteRobotTask(int id);
        public Dt_RobotTask? QueryRobotCraneTask(string deviceCode);
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTask_HtyService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    public interface IRobotTask_HtyService : IService<Dt_RobotTask_Hty>
    {
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/RobotState/Dt_RobotState.cs
@@ -23,7 +23,7 @@
        /// æœºæ¢°æ‰‹ IP åœ°å€ï¼Œå”¯ä¸€ç´¢å¼•
        /// </summary>
        [SugarColumn(Length = 50, ColumnDescription = "机械手IP地址")]
        public string IPAddress { get; set; } = string.Empty;
        public string IpAddress { get; set; }
        /// <summary>
        /// ç‰ˆæœ¬å·ï¼Œç”¨äºŽä¹è§‚并发控制
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/TaskInfo/Dt_RobotTask_Hty.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Magicodes.ExporterAndImporter.Core;
using WIDESEAWCS_Core.DB.Models;
namespace WIDESEAWCS_Model.Models
{
    /// <summary>
    /// æœºå™¨äººåŽ†å²ä»»åŠ¡è¡¨å®žä½“
    /// </summary>
    [SugarTable(nameof(Dt_RobotTask_Hty), "机器人历史任务信息")]
    public class Dt_RobotTask_Hty : Dt_RobotTask, IBaseHistoryEntity
    {
        /// <summary>
        /// åŽŸè¡¨ä¸»é”®
        /// </summary>
        [ImporterHeader(Name = "原表主键")]
        [ExporterHeader(DisplayName = "原表主键")]
        [SugarColumn(IsNullable = false, DefaultValue = "0", ColumnDescription = "原表主键")]
        public int SourceId { get; set; }
        /// <summary>
        /// æ“ä½œç±»åž‹
        /// </summary>
        [ImporterHeader(Name = "操作类型")]
        [ExporterHeader(DisplayName = "操作类型")]
        [SugarColumn(IsNullable = false, Length = 50, ColumnDescription = "操作类型")]
        public string OperateType { get; set; }
        /// <summary>
        /// ç§»å…¥åŽ†å²æ—¶é—´
        /// </summary>
        [ImporterHeader(Name = "移入历史时间")]
        [ExporterHeader(DisplayName = "移入历史时间")]
        [SugarColumn(IsNullable = false, ColumnDescription = "移入历史时间")]
        public DateTime InsertTime { get; set; }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTaskController.cs
@@ -1,17 +1,32 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseController;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ISystemServices;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_Server.Controllers.Task
{
    [Route("api/robotTask")]
    [Route("api/RobotTask")]
    [ApiController]
    public class RobotTaskController : ApiBaseController<IRobotTaskService, Dt_RobotTask>
    {
        public RobotTaskController(IRobotTaskService service) : base(service)
        {
        }
        [HttpGet, HttpPost, Route("DeleteRobotTask"), AllowAnonymous]
        public WebResponseContent DeleteRobotTask(int id)
        {
            if (Service.DeleteRobotTask(id)){
                return WebResponseContent.Instance.OK();
            }
            return WebResponseContent.Instance.Error();
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Task/RobotTask_HtyController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using WIDESEAWCS_Core.BaseController;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_Server.Controllers.Task
{
    namespace WIDESEAWCS_WCSServer.Controllers.Task
    {
        [Route("api/RobotTask_Hty")]
        [ApiController]
        public class RobotTask_HtyController : ApiBaseController<IRobotTask_HtyService, Dt_RobotTask_Hty>
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
            public RobotTask_HtyController(
                IRobotTask_HtyService service,
                IHttpContextAccessor httpContextAccessor) : base(service)
            {
                _httpContextAccessor = httpContextAccessor;
            }
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotStateRepository.cs
@@ -19,7 +19,7 @@
        public Dt_RobotState? GetByIp(string ipAddress)
        {
            return Db.Queryable<Dt_RobotState>()
                .Where(x => x.IPAddress == ipAddress)
                .Where(x => x.IpAddress == ipAddress)
                .First();
        }
@@ -33,7 +33,7 @@
            var newState = new Dt_RobotState
            {
                IPAddress = ipAddress,
                IpAddress = ipAddress,
                Version = DateTime.UtcNow.Ticks,
                RobotCraneJson = JsonConvert.SerializeObject(robotCrane),
                CreateDate = DateTime.Now,
@@ -50,7 +50,7 @@
            // ä¹è§‚锁:WHERE IPAddress = @ip AND Version = @expectedVersion,版本匹配才更新
            var affectedRows = Db.Updateable<Dt_RobotState>(newState)
                .Where(x => x.IPAddress == ipAddress)
                .Where(x => x.IpAddress == ipAddress)
                .ExecuteCommand();
            return affectedRows > 0;
@@ -60,7 +60,7 @@
        {
            var state = new RobotSocketState
            {
                IPAddress = entity.IPAddress,
                IPAddress = entity.IpAddress,
                Version = entity.Version,
                IsEventSubscribed = entity.IsEventSubscribed,
                RobotRunMode = entity.RobotRunMode,
@@ -112,7 +112,7 @@
        {
            var entity = new Dt_RobotState
            {
                IPAddress = state.IPAddress,
                IpAddress = state.IPAddress,
                IsEventSubscribed = state.IsEventSubscribed,
                RobotRunMode = state.RobotRunMode,
                RobotControlMode = state.RobotControlMode,
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoRepository/RobotTaskInfoRepository.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_IRobotTaskInfoRepository;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_RobotTaskInfoRepository
{
    public class RobotTask_HtyRepository : RepositoryBase<Dt_RobotTask_Hty>, IRobotTask_HtyRepository
    {
        public RobotTask_HtyRepository(IUnitOfWorkManage unitOfWorkManage) : base(unitOfWorkManage)
        {
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -29,6 +29,7 @@
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.Utilities;
using WIDESEAWCS_DTO.Stock;
@@ -70,6 +71,23 @@
            _httpClientHelper = httpClientHelper;
            _taskExecuteDetailService = taskExecuteDetailService;
            _logger = logger;
        }
        public override WebResponseContent DeleteData(object[] keys)
        {
            List<int> taskKeys = new List<int>();
            for (int i = 0; i < keys.Length; i++)
            {
                taskKeys.Add(Convert.ToInt32(keys[i]));
            }
            List<Dt_RobotTask> tasks = BaseDal.QueryData(x => taskKeys.Contains(x.RobotTaskId));
            BaseDal.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.人工删除);
            return WebResponseContent.Instance.OK($"成功删除{tasks.Count}条数据");
        }
        public bool DeleteRobotTask(int id)
        {
            Dt_RobotTask task = BaseDal.QueryFirst(x => x.RobotTaskId == id);
            return BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成);
        }
        public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO)
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTask_HtyService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
using MapsterMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_IRobotTaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_TaskInfoService
{
    public class RobotTask_HtyService : ServiceBase<Dt_RobotTask_Hty, IRobotTask_HtyRepository>, IRobotTask_HtyService
    {
        private readonly IRouterService _routerService;
        private readonly IMapper _mapper;
        public RobotTask_HtyService(
            IRobotTask_HtyRepository BaseDal,
            IRouterService routerService,
            IMapper mapper) : base(BaseDal)
        {
            _routerService = routerService;
            _mapper = mapper;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -79,7 +79,7 @@
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger _logger;
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
@@ -146,7 +146,7 @@
        /// <returns>删除是否成功</returns>
        public bool? DeleteTask(int ID)
        {
            return _robotTaskService.Repository.DeleteDataById(ID);
            return _robotTaskService.DeleteRobotTask(ID);
        }
        /// <summary>
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockChat.vue
@@ -67,8 +67,8 @@
                <div v-if="selectedLocation.details && selectedLocation.details.length > 0" class="detail-table">
                    <h4>库存明细</h4>
                    <el-table :data="selectedLocation.details" border size="small" max-height="400">
                        <el-table-column prop="materielName" label="物料名称" min-width="140" show-overflow-tooltip />
                        <el-table-column prop="serialNumber" label="电芯条码" min-width="160" show-overflow-tooltip />
                        <el-table-column prop="materielName" label="物料名称" min-width="90" show-overflow-tooltip />
                        <el-table-column prop="serialNumber" label="电芯条码" min-width="180" show-overflow-tooltip />
                        <el-table-column prop="inboundOrderRowNo" label="通道号" min-width="100" show-overflow-tooltip />
                    </el-table>
                </div>
@@ -777,9 +777,9 @@
        selectedLocation.value = null
        // æ¸…空筛选条件
        filterStockStatus.value = null
        filterMaterielCode.value = null
        filterBatchNo.value = null
         filterStockStatus.value = null
         filterMaterielCode.value = null
         filterBatchNo.value = null
        const res = await proxy.http.get(`/api/StockInfo/Get3DLayout?warehouseId=${warehouseId}`)
        if (res.status && res.data) {
            const data = res.data
@@ -1161,13 +1161,13 @@
    selectedLocation.value = null
    // æ¸…空所有筛选条件
    filterStockStatus.value = null
    filterMaterielCode.value = null
    filterBatchNo.value = null
    // filterStockStatus.value = null
    // filterMaterielCode.value = null
    // filterBatchNo.value = null
    // æ¸…空筛选选项列表
    materielCodeList.value = []
    batchNoList.value = []
    // // æ¸…空筛选选项列表
    // materielCodeList.value = []
    // batchNoList.value = []
    // åŠ è½½æ–°ä»“åº“æ•°æ®
    await loadWarehouseData(warehouseId)
@@ -1375,7 +1375,7 @@
}
.detail-content {
    padding: 20px;
    padding: 10px;
}
.detail-table {
Code/WMS/WIDESEA_WMSClient/src/views/stock/stockInfo.vue
@@ -1,16 +1,7 @@
<template>
  <view-grid
    ref="grid"
    :columns="columns"
    :detail="detail"
    :editFormFields="editFormFields"
    :editFormOptions="editFormOptions"
    :searchFormFields="searchFormFields"
    :searchFormOptions="searchFormOptions"
    :table="table"
    :tableExpand="tableExpand"
    :extend="extend"
  >
  <view-grid ref="grid" :columns="columns" :detail="detail" :editFormFields="editFormFields"
    :editFormOptions="editFormOptions" :searchFormFields="searchFormFields" :searchFormOptions="searchFormOptions"
    :table="table" :tableExpand="tableExpand" :extend="extend">
  </view-grid>
</template>
@@ -30,6 +21,7 @@
  palletCode: "托盘编号",
  stockStatus: "库存状态",
  locationCode: "货位编号",
  outboundDate: "出库时间",
  warehouse: "仓库",
  creator: "创建人",
  createDate: "创建时间",
@@ -64,7 +56,7 @@
      sortName: "id",
    });
     const editFormFields = ref({
    const editFormFields = ref({
      palletCode: "",
      palletType: 0,
      warehouseId: 0,
@@ -78,7 +70,7 @@
    const editFormOptions = ref([
      [
        { field: "palletCode", title: TEXT.palletCode, type: "string" },
        { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: []},
        { field: "stockStatus", title: TEXT.stockStatus, type: "select", dataKey: "stockStatusEmun", data: [] },
        { field: "locationCode", title: TEXT.locationCode, type: "string" },
      ],
    ]);
@@ -112,7 +104,7 @@
        field: "palletCode",
        title: TEXT.palletCode,
        type: "string",
        width: 120,
        width: 150,
        align: "left",
      },
      {
@@ -132,10 +124,17 @@
        bind: { key: "mesUploadStatusEnum", data: [] },
      },
      {
        field: "outboundDate",
        title: TEXT.outboundDate,
        type: "string",
        width: 150,
        align: "left",
      },
      {
        field: "locationCode",
        title: TEXT.locationCode,
        type: "string",
        width: 150,
        width: 120,
        align: "left",
      },
      {
Code/WMS/WIDESEA_WMSServer/WIDESEA_Core/Helper/UtilConvert.cs
@@ -1,998 +1,998 @@
using NetTaste;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using WIDESEA_Core.Const;
using WIDESEA_Core.Enums;
namespace WIDESEA_Core.Helper
{
    public static class UtilConvert
    {
        private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
        private static long longTime = 621355968000000000;
        private static int samllTime = 10000000;
        /// <summary>
        /// æ—¶é—´æˆ³è½¬æ¢æˆæ—¥æœŸ
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <returns></returns>
        public static DateTime GetTimeSpmpToDate(this object timeStamp)
        {
            if (timeStamp == null) return dateStart;
            DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime();
            return dateTime;
        }
        public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
        {
            if (obj == null) return null;
            formatDate = formatDate ?? new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            };
            return JsonConvert.SerializeObject(obj, formatDate);
        }
        public static T DeserializeObject<T>(this string json)
        {
            if (string.IsNullOrEmpty(json))
            {
                return default(T);
            }
            if (json == "{}")
            {
                json = "[]";
            }
            return JsonConvert.DeserializeObject<T>(json);
        }
        public static string FirstLetterToLower(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToLower() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        public static string FirstLetterToUpper(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToUpper() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static int ObjToInt(this object thisValue)
        {
            int reval = 0;
            if (thisValue == null) return 0;
            if (thisValue is Enum && thisValue != DBNull.Value && Enum.TryParse(thisValue.GetType(), thisValue.ToString(), out var val))
            {
                return Convert.ToInt32(val.ChangeType(typeof(int)));
            }
            if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static int DoubleToInt(this double thisValue)
        {
            int reval = 0;
            return Convert.ToInt32(thisValue);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static int ObjToInt(this object thisValue, int errorValue)
        {
            int reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        public static long ObjToLong(this object thisValue)
        {
            long reval = 0;
            if (thisValue == null) return 0;
            if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static double ObjToMoney(this object thisValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static double ObjToMoney(this object thisValue, double errorValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static string ObjToString(this object thisValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return "";
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static bool IsNotEmptyOrNull(this object thisValue)
        {
            return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null";
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static string ObjToString(this object thisValue, string errorValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return errorValue;
        }
        public static bool IsNullOrEmpty(this object thisValue) => thisValue == null || thisValue == DBNull.Value || string.IsNullOrWhiteSpace(thisValue.ToString());
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static Decimal ObjToDecimal(this object thisValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static Decimal ObjToDecimal(this object thisValue, decimal errorValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static DateTime ObjToDate(this object thisValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                reval = Convert.ToDateTime(thisValue);
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static DateTime ObjToDate(this object thisValue, DateTime errorValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static bool ObjToBool(this object thisValue)
        {
            bool reval = false;
            if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// èŽ·å–å½“å‰æ—¶é—´çš„æ—¶é—´æˆ³
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static string DateToTimeStamp(this DateTime thisValue)
        {
            TimeSpan ts = thisValue - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        public static object ChangeType(this object value, Type type)
        {
            if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
            if (value == null) return null;
            if (type == value.GetType()) return value;
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value as string);
                else
                    return Enum.ToObject(type, value);
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = ChangeType(value, innerType);
                return Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid)) return new Guid(value as string);
            if (value is string && type == typeof(Version)) return new Version(value as string);
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }
        public static object ChangeTypeList(this object value, Type type)
        {
            if (value == null) return default;
            var gt = typeof(List<>).MakeGenericType(type);
            dynamic lis = Activator.CreateInstance(gt);
            var addMethod = gt.GetMethod("Add");
            string values = value.ToString();
            if (values != null && values.StartsWith("(") && values.EndsWith(")"))
            {
                string[] splits;
                if (values.Contains("\",\""))
                {
                    splits = values.Remove(values.Length - 2, 2)
                        .Remove(0, 2)
                        .Split("\",\"");
                }
                else
                {
                    splits = values.Remove(0, 1)
                        .Remove(values.Length - 2, 1)
                        .Split(",");
                }
                foreach (var split in splits)
                {
                    var str = split;
                    if (split.StartsWith("\"") && split.EndsWith("\""))
                    {
                        str = split.Remove(0, 1)
                            .Remove(split.Length - 2, 1);
                    }
                    addMethod.Invoke(lis, new object[] { ChangeType(str, type) });
                }
            }
            return lis;
        }
        public static string ToJson(this object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        public static bool IsNumeric(this object value)
        {
            if (value == null)
                return false;
            bool reslut = decimal.TryParse(value.ToString(), out decimal _number);
            return reslut;
        }
        public static bool IsInt(this object obj)
        {
            if (obj == null)
                return false;
            bool reslut = Int32.TryParse(obj.ToString(), out int _number);
            return reslut;
        }
        public static bool IsDate(this object str)
        {
            return str.IsDate(out _);
        }
        public static bool IsDate(this object str, out DateTime dateTime)
        {
            dateTime = DateTime.Now;
            if (str == null || str.ToString() == "")
            {
                return false;
            }
            return DateTime.TryParse(str.ToString(), out dateTime);
        }
        /// <summary>
        /// æ ¹æ®ä¼ å…¥æ ¼å¼åˆ¤æ–­æ˜¯å¦ä¸ºå°æ•°
        /// </summary>
        /// <param name="str"></param>
        /// <param name="formatString">18,5</param>
        /// <returns></returns>
        public static bool IsNumber(this string str, string formatString)
        {
            if (string.IsNullOrEmpty(str)) return false;
            return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$");
        }
        public static bool IsGuid(this string guid)
        {
            Guid newId;
            return guid.GetGuid(out newId);
        }
        public static bool GetGuid(this string guid, out Guid outId)
        {
            Guid emptyId = Guid.Empty;
            return Guid.TryParse(guid, out outId);
        }
        /// <summary>
        /// è½¬æ¢ä¸ºçŸ­æ•´åž‹ qy 2024-7-15
        /// </summary>
        /// <param name="data">数据</param>
        public static short ToShort(this object data)
        {
            if (data == null)
                return 0;
            short result;
            var success = short.TryParse(data.ToString(), out result);
            if (success)
                return result;
            try
            {
                return Convert.ToInt16(data);
            }
            catch (Exception)
            {
                return 0;
            }
        }
        /// <summary>
        /// è½¬æ¢ä¸ºé«˜ç²¾åº¦æµ®ç‚¹æ•°,并按指定的小数位4舍5入 qy 2024-7-15
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="digits">小数位数</param>
        public static decimal ToDecimal(this object data, int digits)
        {
            return Math.Round(ObjToDecimal(data), digits);
        }
        /// <summary>
        /// æžšä¸¾è½¬List qy 2024-7-15
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<object> GetEnumList<T>()
        {
            List<object> list = new List<object>();
            var t = typeof(T);
            foreach (var item in Enum.GetValues(typeof(T)))
            {
                FieldInfo f = t.GetField(Enum.GetName(typeof(T), item));
                var r = (System.ComponentModel.DescriptionAttribute[])f.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
                list.Add(new { ID = item, value = Enum.GetName(typeof(T), item), name = r[0].Description });
            }
            return list;
        }
        /// <summary>
        /// éªŒè¯åŠ¨æ€ç±»åž‹å…ƒç´ æ˜¯å¦ä¸ºç©º qy 2024-7-15
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool CheckDynamic(object obj)
        {
            return (obj != null && Convert.ToString(obj) != "") ? true : false;
        }
        /// <summary>
        /// åŠ¨æ€ç±»åž‹å…ƒç´ è½¬å­—ç¬¦ä¸²å¹¶è§£ç  qy 2024-7-15
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string DynamicToString(object obj)
        {
            return CheckDynamic(obj) ? HttpUtility.UrlDecode(Convert.ToString(obj).Trim()) : "";
        }
        /// <summary>
        /// DataTable转为json  qy 2024-7-15
        /// </summary>
        /// <param name="parObjRefDataTable">DataTable</param>
        /// <returns>json数据</returns>
        public static string ToJson(this DataTable parObjRefDataTable)
        {
            List<object> objArrList = new List<object>();
            foreach (DataRow objDataRow in parObjRefDataTable.Rows)
            {
                Dictionary<string, object> objResult = new Dictionary<string, object>();
                foreach (DataColumn objDataColumn in parObjRefDataTable.Columns)
                    objResult.Add(objDataColumn.ColumnName, objDataRow[objDataColumn].ToString());
                objArrList.Add(objResult);
            }
            return ToJson(objArrList);
        }
        /// <summary>
        /// Json转List qy 2024-7-15
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="parJson"></param>
        /// <returns></returns>
        public static List<T> JsonToList<T>(this string parJson)
        {
            if (string.IsNullOrWhiteSpace(parJson))
            {
                return new List<T>();
            }
            else
            {
                return JsonConvert.DeserializeObject<List<T>>(parJson);
            }
        }
        /// <summary>
        /// æ—¥æœŸè½¬ä¸ºunix值
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="utc">T:按UTC时间计算(默认);F:按本地时间计算</param>
        /// <returns></returns>
        /// <summary>
        /// æ—¥æœŸè½¬ä¸ºunix值
        /// </summary>
        /// <param name="dt">日期时间</param>
        /// <param name="utc">T:按UTC时间计算(默认);F:按本地时间计算</param>
        /// <returns></returns>
        public static double ToUnix(this DateTime dt, bool utc = true)
        {
            double intResult = 0;
            System.DateTime startTime = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local);
            intResult = (dt - startTime).TotalSeconds;
            intResult = Math.Round(intResult, 0);
            return intResult;
        }
        #region åˆ¤æ–­æ˜¯å¦ä¸ºå­—符串 qy 2024-7-15
        /// <summary>
        /// åˆ¤æ–­å­—符串是否为合法的json字符串 qy 2024-7-15
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static bool IsJson(string json)
        {
            int errIndex;
            return IsJson(json, out errIndex);
        }
        public static bool IsJson(string json, out int errIndex)
        {
            errIndex = 0;
            if (IsJsonStart(ref json))
            {
                CharState cs = new CharState();
                char c;
                for (int i = 0; i < json.Length; i++)
                {
                    c = json[i];
                    if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
                    {
                        string item = json.Substring(i);
                        int err;
                        int length = GetValueLength(item, true, out err);
                        cs.childrenStart = false;
                        if (err > 0)
                        {
                            errIndex = i + err;
                            return false;
                        }
                        i = i + length - 1;
                    }
                    if (cs.isError)
                    {
                        errIndex = i;
                        return false;
                    }
                }
                return !cs.arrayStart && !cs.jsonStart;
            }
            return false;
        }
        private static bool IsJsonStart(ref string json)
        {
            if (!string.IsNullOrEmpty(json))
            {
                json = json.Trim('\r', '\n', ' ');
                if (json.Length > 1)
                {
                    char s = json[0];
                    char e = json[json.Length - 1];
                    return (s == '{' && e == '}') || (s == '[' && e == ']');
                }
            }
            return false;
        }
        /// <summary>
        /// èŽ·å–å€¼çš„é•¿åº¦ï¼ˆå½“Json值嵌套以"{"或"["开头时) qy 2024-7-15
        /// </summary>
        private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
        {
            errIndex = 0;
            int len = 0;
            if (!string.IsNullOrEmpty(json))
            {
                CharState cs = new CharState();
                char c;
                for (int i = 0; i < json.Length; i++)
                {
                    c = json[i];
                    if (!SetCharState(c, ref cs))//设置关键符号状态。
                    {
                        if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
                        {
                            break;
                        }
                    }
                    else if (cs.childrenStart)//正常字符,值状态下。
                    {
                        int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
                        cs.childrenStart = false;
                        cs.valueStart = 0;
                        //cs.state = 0;
                        i = i + length - 1;
                    }
                    if (breakOnErr && cs.isError)
                    {
                        errIndex = i;
                        return i;
                    }
                    if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
                    {
                        len = i + 1;//长度比索引+1
                        break;
                    }
                }
            }
            return len;
        }
        /// <summary>
        /// å­—符状态 qy 2024-7-15
        /// </summary>
        private class CharState
        {
            internal bool jsonStart = false;//以 "{"开始了...
            internal bool setDicValue = false;// å¯ä»¥è®¾ç½®å­—典值了。
            internal bool escapeChar = false;//以"\"转义符号开始了
            /// <summary>
            /// æ•°ç»„开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。
            /// </summary>
            internal bool arrayStart = false;//以"[" ç¬¦å·å¼€å§‹äº†
            internal bool childrenStart = false;//子级嵌套开始了。
            /// <summary>
            /// ã€0 åˆå§‹çŠ¶æ€ï¼Œæˆ– é‡åˆ°â€œ,”逗号】;【1 é‡åˆ°â€œï¼šâ€å†’号】
            /// </summary>
            internal int state = 0;
            /// <summary>
            /// ã€-1 å–值结束】【0 æœªå¼€å§‹ã€‘【1 æ— å¼•号开始】【2 å•引号开始】【3 åŒå¼•号开始】
            /// </summary>
            internal int keyStart = 0;
            /// <summary>
            /// ã€-1 å–值结束】【0 æœªå¼€å§‹ã€‘【1 æ— å¼•号开始】【2 å•引号开始】【3 åŒå¼•号开始】
            /// </summary>
            internal int valueStart = 0;
            internal bool isError = false;//是否语法错误。
            internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
            {
                if (keyStart > 1 || valueStart > 1)
                {
                    return;
                }
                //示例 ["aa",{"bbbb":123,"fff","ddd"}]
                switch (c)
                {
                    case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                        isError = jsonStart && state == 0;//重复开始错误 åŒæ—¶ä¸æ˜¯å€¼å¤„理。
                        break;
                    case '}':
                        isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 æˆ–者 æå‰ç»“束{"aa"}。正常的有{}
                        break;
                    case '[':
                        isError = arrayStart && state == 0;//重复开始错误
                        break;
                    case ']':
                        isError = !arrayStart || jsonStart;//重复开始错误 æˆ–者 Json æœªç»“束
                        break;
                    case '"':
                    case '\'':
                        isError = !(jsonStart || arrayStart); //json æˆ–数组开始。
                        if (!isError)
                        {
                            //重复开始 [""",{"" "}]
                            isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);
                        }
                        if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
                        {
                            isError = true;
                        }
                        break;
                    case ':':
                        isError = !jsonStart || state == 1;//重复出现。
                        break;
                    case ',':
                        isError = !(jsonStart || arrayStart); //json æˆ–数组开始。
                        if (!isError)
                        {
                            if (jsonStart)
                            {
                                isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
                            }
                            else if (arrayStart)//["aa,] [,]  [{},{}]
                            {
                                isError = keyStart == 0 && !setDicValue;
                            }
                        }
                        break;
                    case ' ':
                    case '\r':
                    case '\n'://[ "a",\r\n{} ]
                    case '\0':
                    case '\t':
                        break;
                    default: //值开头。。
                        isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
                        break;
                }
                //if (isError)
                //{
                //}
            }
        }
        /// <summary>
        /// è®¾ç½®å­—符状态(返回true则为关键词,返回false则当为普通字符处理) qy 2024-7-15
        /// </summary>
        private static bool SetCharState(char c, ref CharState cs)
        {
            cs.CheckIsError(c);
            switch (c)
            {
                case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                    #region å¤§æ‹¬å·
                    if (cs.keyStart <= 0 && cs.valueStart <= 0)
                    {
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        if (cs.jsonStart && cs.state == 1)
                        {
                            cs.childrenStart = true;
                        }
                        else
                        {
                            cs.state = 0;
                        }
                        cs.jsonStart = true;//开始。
                        return true;
                    }
                    #endregion
                    break;
                case '}':
                    #region å¤§æ‹¬å·ç»“束
                    if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
                    {
                        cs.jsonStart = false;//正常结束。
                        cs.state = 0;
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        cs.setDicValue = true;
                        return true;
                    }
                    // cs.isError = !cs.jsonStart && cs.state == 0;
                    #endregion
                    break;
                case '[':
                    #region ä¸­æ‹¬å·å¼€å§‹
                    if (!cs.jsonStart)
                    {
                        cs.arrayStart = true;
                        return true;
                    }
                    else if (cs.jsonStart && cs.state == 1)
                    {
                        cs.childrenStart = true;
                        return true;
                    }
                    #endregion
                    break;
                case ']':
                    #region ä¸­æ‹¬å·ç»“束
                    if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
                    {
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        cs.arrayStart = false;
                        return true;
                    }
                    #endregion
                    break;
                case '"':
                case '\'':
                    #region å¼•号
                    if (cs.jsonStart || cs.arrayStart)
                    {
                        if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
                        {
                            if (cs.keyStart <= 0)
                            {
                                cs.keyStart = (c == '"' ? 3 : 2);
                                return true;
                            }
                            else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"'))
                            {
                                if (!cs.escapeChar)
                                {
                                    cs.keyStart = -1;
                                    return true;
                                }
                                else
                                {
                                    cs.escapeChar = false;
                                }
                            }
                        }
                        else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
                        {
                            if (cs.valueStart <= 0)
                            {
                                cs.valueStart = (c == '"' ? 3 : 2);
                                return true;
                            }
                            else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"'))
                            {
                                if (!cs.escapeChar)
                                {
                                    cs.valueStart = -1;
                                    return true;
                                }
                                else
                                {
                                    cs.escapeChar = false;
                                }
                            }
                        }
                    }
                    #endregion
                    break;
                case ':':
                    #region å†’号
                    if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
                    {
                        if (cs.keyStart == 1)
                        {
                            cs.keyStart = -1;
                        }
                        cs.state = 1;
                        return true;
                    }
                    // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
                    #endregion
                    break;
                case ',':
                    #region é€—号 //["aa",{aa:12,}]
                    if (cs.jsonStart)
                    {
                        if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
                        {
                            cs.state = 0;
                            cs.keyStart = 0;
                            cs.valueStart = 0;
                            //if (cs.valueStart == 1)
                            //{
                            //    cs.valueStart = 0;
                            //}
                            cs.setDicValue = true;
                            return true;
                        }
                    }
                    else if (cs.arrayStart && cs.keyStart <= 2)
                    {
                        cs.keyStart = 0;
                        //if (cs.keyStart == 1)
                        //{
                        //    cs.keyStart = -1;
                        //}
                        return true;
                    }
                    #endregion
                    break;
                case ' ':
                case '\r':
                case '\n'://[ "a",\r\n{} ]
                case '\0':
                case '\t':
                    if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
                    {
                        return true;//跳过空格。
                    }
                    break;
                default: //值开头。。
                    if (c == '\\') //转义符号
                    {
                        if (cs.escapeChar)
                        {
                            cs.escapeChar = false;
                        }
                        else
                        {
                            cs.escapeChar = true;
                            return true;
                        }
                    }
                    else
                    {
                        cs.escapeChar = false;
                    }
                    if (cs.jsonStart || cs.arrayStart) // Json æˆ–数组开始了。
                    {
                        if (cs.keyStart <= 0 && cs.state == 0)
                        {
                            cs.keyStart = 1;//无引号的
                        }
                        else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
                        {
                            cs.valueStart = 1;//无引号的
                        }
                    }
                    break;
            }
            return false;
        }
        #endregion
        public static LinqExpressionType GetLinqCondition(this string stringType)
        {
            LinqExpressionType linqExpression;
            switch (stringType)
            {
                case HtmlElementType.Contains:
                    linqExpression = LinqExpressionType.In;
                    break;
                case HtmlElementType.ThanOrEqual:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.LessOrequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                case HtmlElementType.GT:
                    linqExpression = LinqExpressionType.GreaterThan;
                    break;
                case HtmlElementType.lt:
                    linqExpression = LinqExpressionType.LessThan;
                    break;
                case HtmlElementType.like:
                    linqExpression = LinqExpressionType.Contains;
using NetTaste;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using WIDESEA_Core.Const;
using WIDESEA_Core.Enums;
namespace WIDESEA_Core.Helper
{
    public static class UtilConvert
    {
        private static DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
        private static long longTime = 621355968000000000;
        private static int samllTime = 10000000;
        /// <summary>
        /// æ—¶é—´æˆ³è½¬æ¢æˆæ—¥æœŸ
        /// </summary>
        /// <param name="timeStamp"></param>
        /// <returns></returns>
        public static DateTime GetTimeSpmpToDate(this object timeStamp)
        {
            if (timeStamp == null) return dateStart;
            DateTime dateTime = new DateTime(longTime + Convert.ToInt64(timeStamp) * samllTime, DateTimeKind.Utc).ToLocalTime();
            return dateTime;
        }
        public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
        {
            if (obj == null) return null;
            formatDate = formatDate ?? new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss"
            };
            return JsonConvert.SerializeObject(obj, formatDate);
        }
        public static T DeserializeObject<T>(this string json)
        {
            if (string.IsNullOrEmpty(json))
            {
                return default(T);
            }
            if (json == "{}")
            {
                json = "[]";
            }
            return JsonConvert.DeserializeObject<T>(json);
        }
        public static string FirstLetterToLower(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToLower() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        public static string FirstLetterToUpper(this string thisValue)
        {
            if (string.IsNullOrEmpty(thisValue)) return string.Empty;
            string result = thisValue.Substring(0, 1).ToUpper() + thisValue.Substring(1, thisValue.Length - 1);
            return result;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static int ObjToInt(this object thisValue)
        {
            int reval = 0;
            if (thisValue == null) return 0;
            if (thisValue is Enum && thisValue != DBNull.Value && Enum.TryParse(thisValue.GetType(), thisValue.ToString(), out var val))
            {
                return Convert.ToInt32(val.ChangeType(typeof(int)));
            }
            if (thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static int DoubleToInt(this double thisValue)
        {
            int reval = 0;
            return Convert.ToInt32(thisValue);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static int ObjToInt(this object thisValue, int errorValue)
        {
            int reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        public static long ObjToLong(this object thisValue)
        {
            long reval = 0;
            if (thisValue == null) return 0;
            if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static double ObjToMoney(this object thisValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static double ObjToMoney(this object thisValue, double errorValue)
        {
            double reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static string ObjToString(this object thisValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return "";
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static bool IsNotEmptyOrNull(this object thisValue)
        {
            return ObjToString(thisValue) != "" && ObjToString(thisValue) != "undefined" && ObjToString(thisValue) != "null";
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static string ObjToString(this object thisValue, string errorValue)
        {
            if (thisValue != null) return thisValue.ToString().Trim();
            return errorValue;
        }
        public static bool IsNullOrEmpty(this object thisValue) => thisValue == null || thisValue == DBNull.Value || string.IsNullOrWhiteSpace(thisValue.ToString());
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static Decimal ObjToDecimal(this object thisValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return 0;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static Decimal ObjToDecimal(this object thisValue, decimal errorValue)
        {
            Decimal reval = 0;
            if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static DateTime ObjToDate(this object thisValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                reval = Convert.ToDateTime(thisValue);
            }
            return reval;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <param name="errorValue"></param>
        /// <returns></returns>
        public static DateTime ObjToDate(this object thisValue, DateTime errorValue)
        {
            DateTime reval = DateTime.MinValue;
            if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return errorValue;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static bool ObjToBool(this object thisValue)
        {
            bool reval = false;
            if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval))
            {
                return reval;
            }
            return reval;
        }
        /// <summary>
        /// èŽ·å–å½“å‰æ—¶é—´çš„æ—¶é—´æˆ³
        /// </summary>
        /// <param name="thisValue"></param>
        /// <returns></returns>
        public static string DateToTimeStamp(this DateTime thisValue)
        {
            TimeSpan ts = thisValue - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        public static object ChangeType(this object value, Type type)
        {
            if (value == null && type.IsGenericType) return Activator.CreateInstance(type);
            if (value == null) return null;
            if (type == value.GetType()) return value;
            if (type.IsEnum)
            {
                if (value is string)
                    return Enum.Parse(type, value as string);
                else
                    return Enum.ToObject(type, value);
            }
            if (!type.IsInterface && type.IsGenericType)
            {
                Type innerType = type.GetGenericArguments()[0];
                object innerValue = ChangeType(value, innerType);
                return Activator.CreateInstance(type, new object[] { innerValue });
            }
            if (value is string && type == typeof(Guid)) return new Guid(value as string);
            if (value is string && type == typeof(Version)) return new Version(value as string);
            if (!(value is IConvertible)) return value;
            return Convert.ChangeType(value, type);
        }
        public static object ChangeTypeList(this object value, Type type)
        {
            if (value == null) return default;
            var gt = typeof(List<>).MakeGenericType(type);
            dynamic lis = Activator.CreateInstance(gt);
            var addMethod = gt.GetMethod("Add");
            string values = value.ToString();
            if (values != null && values.StartsWith("(") && values.EndsWith(")"))
            {
                string[] splits;
                if (values.Contains("\",\""))
                {
                    splits = values.Remove(values.Length - 2, 2)
                        .Remove(0, 2)
                        .Split("\",\"");
                }
                else
                {
                    splits = values.Remove(0, 1)
                        .Remove(values.Length - 2, 1)
                        .Split(",");
                }
                foreach (var split in splits)
                {
                    var str = split;
                    if (split.StartsWith("\"") && split.EndsWith("\""))
                    {
                        str = split.Remove(0, 1)
                            .Remove(split.Length - 2, 1);
                    }
                    addMethod.Invoke(lis, new object[] { ChangeType(str, type) });
                }
            }
            return lis;
        }
        public static string ToJson(this object value)
        {
            return JsonConvert.SerializeObject(value);
        }
        public static bool IsNumeric(this object value)
        {
            if (value == null)
                return false;
            bool reslut = decimal.TryParse(value.ToString(), out decimal _number);
            return reslut;
        }
        public static bool IsInt(this object obj)
        {
            if (obj == null)
                return false;
            bool reslut = Int32.TryParse(obj.ToString(), out int _number);
            return reslut;
        }
        public static bool IsDate(this object str)
        {
            return str.IsDate(out _);
        }
        public static bool IsDate(this object str, out DateTime dateTime)
        {
            dateTime = DateTime.Now;
            if (str == null || str.ToString() == "")
            {
                return false;
            }
            return DateTime.TryParse(str.ToString(), out dateTime);
        }
        /// <summary>
        /// æ ¹æ®ä¼ å…¥æ ¼å¼åˆ¤æ–­æ˜¯å¦ä¸ºå°æ•°
        /// </summary>
        /// <param name="str"></param>
        /// <param name="formatString">18,5</param>
        /// <returns></returns>
        public static bool IsNumber(this string str, string formatString)
        {
            if (string.IsNullOrEmpty(str)) return false;
            return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$");
        }
        public static bool IsGuid(this string guid)
        {
            Guid newId;
            return guid.GetGuid(out newId);
        }
        public static bool GetGuid(this string guid, out Guid outId)
        {
            Guid emptyId = Guid.Empty;
            return Guid.TryParse(guid, out outId);
        }
        /// <summary>
        /// è½¬æ¢ä¸ºçŸ­æ•´åž‹ qy 2024-7-15
        /// </summary>
        /// <param name="data">数据</param>
        public static short ToShort(this object data)
        {
            if (data == null)
                return 0;
            short result;
            var success = short.TryParse(data.ToString(), out result);
            if (success)
                return result;
            try
            {
                return Convert.ToInt16(data);
            }
            catch (Exception)
            {
                return 0;
            }
        }
        /// <summary>
        /// è½¬æ¢ä¸ºé«˜ç²¾åº¦æµ®ç‚¹æ•°,并按指定的小数位4舍5入 qy 2024-7-15
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="digits">小数位数</param>
        public static decimal ToDecimal(this object data, int digits)
        {
            return Math.Round(ObjToDecimal(data), digits);
        }
        /// <summary>
        /// æžšä¸¾è½¬List qy 2024-7-15
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<object> GetEnumList<T>()
        {
            List<object> list = new List<object>();
            var t = typeof(T);
            foreach (var item in Enum.GetValues(typeof(T)))
            {
                FieldInfo f = t.GetField(Enum.GetName(typeof(T), item));
                var r = (System.ComponentModel.DescriptionAttribute[])f.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
                list.Add(new { ID = item, value = Enum.GetName(typeof(T), item), name = r[0].Description });
            }
            return list;
        }
        /// <summary>
        /// éªŒè¯åŠ¨æ€ç±»åž‹å…ƒç´ æ˜¯å¦ä¸ºç©º qy 2024-7-15
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool CheckDynamic(object obj)
        {
            return (obj != null && Convert.ToString(obj) != "") ? true : false;
        }
        /// <summary>
        /// åŠ¨æ€ç±»åž‹å…ƒç´ è½¬å­—ç¬¦ä¸²å¹¶è§£ç  qy 2024-7-15
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string DynamicToString(object obj)
        {
            return CheckDynamic(obj) ? HttpUtility.UrlDecode(Convert.ToString(obj).Trim()) : "";
        }
        /// <summary>
        /// DataTable转为json  qy 2024-7-15
        /// </summary>
        /// <param name="parObjRefDataTable">DataTable</param>
        /// <returns>json数据</returns>
        public static string ToJson(this DataTable parObjRefDataTable)
        {
            List<object> objArrList = new List<object>();
            foreach (DataRow objDataRow in parObjRefDataTable.Rows)
            {
                Dictionary<string, object> objResult = new Dictionary<string, object>();
                foreach (DataColumn objDataColumn in parObjRefDataTable.Columns)
                    objResult.Add(objDataColumn.ColumnName, objDataRow[objDataColumn].ToString());
                objArrList.Add(objResult);
            }
            return ToJson(objArrList);
        }
        /// <summary>
        /// Json转List qy 2024-7-15
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="parJson"></param>
        /// <returns></returns>
        public static List<T> JsonToList<T>(this string parJson)
        {
            if (string.IsNullOrWhiteSpace(parJson))
            {
                return new List<T>();
            }
            else
            {
                return JsonConvert.DeserializeObject<List<T>>(parJson);
            }
        }
        /// <summary>
        /// æ—¥æœŸè½¬ä¸ºunix值
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="utc">T:按UTC时间计算(默认);F:按本地时间计算</param>
        /// <returns></returns>
        /// <summary>
        /// æ—¥æœŸè½¬ä¸ºunix值
        /// </summary>
        /// <param name="dt">日期时间</param>
        /// <param name="utc">T:按UTC时间计算(默认);F:按本地时间计算</param>
        /// <returns></returns>
        public static double ToUnix(this DateTime dt, bool utc = true)
        {
            double intResult = 0;
            System.DateTime startTime = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local);
            intResult = (dt - startTime).TotalSeconds;
            intResult = Math.Round(intResult, 0);
            return intResult;
        }
        #region åˆ¤æ–­æ˜¯å¦ä¸ºå­—符串 qy 2024-7-15
        /// <summary>
        /// åˆ¤æ–­å­—符串是否为合法的json字符串 qy 2024-7-15
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static bool IsJson(string json)
        {
            int errIndex;
            return IsJson(json, out errIndex);
        }
        public static bool IsJson(string json, out int errIndex)
        {
            errIndex = 0;
            if (IsJsonStart(ref json))
            {
                CharState cs = new CharState();
                char c;
                for (int i = 0; i < json.Length; i++)
                {
                    c = json[i];
                    if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
                    {
                        string item = json.Substring(i);
                        int err;
                        int length = GetValueLength(item, true, out err);
                        cs.childrenStart = false;
                        if (err > 0)
                        {
                            errIndex = i + err;
                            return false;
                        }
                        i = i + length - 1;
                    }
                    if (cs.isError)
                    {
                        errIndex = i;
                        return false;
                    }
                }
                return !cs.arrayStart && !cs.jsonStart;
            }
            return false;
        }
        private static bool IsJsonStart(ref string json)
        {
            if (!string.IsNullOrEmpty(json))
            {
                json = json.Trim('\r', '\n', ' ');
                if (json.Length > 1)
                {
                    char s = json[0];
                    char e = json[json.Length - 1];
                    return (s == '{' && e == '}') || (s == '[' && e == ']');
                }
            }
            return false;
        }
        /// <summary>
        /// èŽ·å–å€¼çš„é•¿åº¦ï¼ˆå½“Json值嵌套以"{"或"["开头时) qy 2024-7-15
        /// </summary>
        private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
        {
            errIndex = 0;
            int len = 0;
            if (!string.IsNullOrEmpty(json))
            {
                CharState cs = new CharState();
                char c;
                for (int i = 0; i < json.Length; i++)
                {
                    c = json[i];
                    if (!SetCharState(c, ref cs))//设置关键符号状态。
                    {
                        if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
                        {
                            break;
                        }
                    }
                    else if (cs.childrenStart)//正常字符,值状态下。
                    {
                        int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
                        cs.childrenStart = false;
                        cs.valueStart = 0;
                        //cs.state = 0;
                        i = i + length - 1;
                    }
                    if (breakOnErr && cs.isError)
                    {
                        errIndex = i;
                        return i;
                    }
                    if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
                    {
                        len = i + 1;//长度比索引+1
                        break;
                    }
                }
            }
            return len;
        }
        /// <summary>
        /// å­—符状态 qy 2024-7-15
        /// </summary>
        private class CharState
        {
            internal bool jsonStart = false;//以 "{"开始了...
            internal bool setDicValue = false;// å¯ä»¥è®¾ç½®å­—典值了。
            internal bool escapeChar = false;//以"\"转义符号开始了
            /// <summary>
            /// æ•°ç»„开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。
            /// </summary>
            internal bool arrayStart = false;//以"[" ç¬¦å·å¼€å§‹äº†
            internal bool childrenStart = false;//子级嵌套开始了。
            /// <summary>
            /// ã€0 åˆå§‹çŠ¶æ€ï¼Œæˆ– é‡åˆ°â€œ,”逗号】;【1 é‡åˆ°â€œï¼šâ€å†’号】
            /// </summary>
            internal int state = 0;
            /// <summary>
            /// ã€-1 å–值结束】【0 æœªå¼€å§‹ã€‘【1 æ— å¼•号开始】【2 å•引号开始】【3 åŒå¼•号开始】
            /// </summary>
            internal int keyStart = 0;
            /// <summary>
            /// ã€-1 å–值结束】【0 æœªå¼€å§‹ã€‘【1 æ— å¼•号开始】【2 å•引号开始】【3 åŒå¼•号开始】
            /// </summary>
            internal int valueStart = 0;
            internal bool isError = false;//是否语法错误。
            internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
            {
                if (keyStart > 1 || valueStart > 1)
                {
                    return;
                }
                //示例 ["aa",{"bbbb":123,"fff","ddd"}]
                switch (c)
                {
                    case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                        isError = jsonStart && state == 0;//重复开始错误 åŒæ—¶ä¸æ˜¯å€¼å¤„理。
                        break;
                    case '}':
                        isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 æˆ–者 æå‰ç»“束{"aa"}。正常的有{}
                        break;
                    case '[':
                        isError = arrayStart && state == 0;//重复开始错误
                        break;
                    case ']':
                        isError = !arrayStart || jsonStart;//重复开始错误 æˆ–者 Json æœªç»“束
                        break;
                    case '"':
                    case '\'':
                        isError = !(jsonStart || arrayStart); //json æˆ–数组开始。
                        if (!isError)
                        {
                            //重复开始 [""",{"" "}]
                            isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);
                        }
                        if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
                        {
                            isError = true;
                        }
                        break;
                    case ':':
                        isError = !jsonStart || state == 1;//重复出现。
                        break;
                    case ',':
                        isError = !(jsonStart || arrayStart); //json æˆ–数组开始。
                        if (!isError)
                        {
                            if (jsonStart)
                            {
                                isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
                            }
                            else if (arrayStart)//["aa,] [,]  [{},{}]
                            {
                                isError = keyStart == 0 && !setDicValue;
                            }
                        }
                        break;
                    case ' ':
                    case '\r':
                    case '\n'://[ "a",\r\n{} ]
                    case '\0':
                    case '\t':
                        break;
                    default: //值开头。。
                        isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
                        break;
                }
                //if (isError)
                //{
                //}
            }
        }
        /// <summary>
        /// è®¾ç½®å­—符状态(返回true则为关键词,返回false则当为普通字符处理) qy 2024-7-15
        /// </summary>
        private static bool SetCharState(char c, ref CharState cs)
        {
            cs.CheckIsError(c);
            switch (c)
            {
                case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
                    #region å¤§æ‹¬å·
                    if (cs.keyStart <= 0 && cs.valueStart <= 0)
                    {
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        if (cs.jsonStart && cs.state == 1)
                        {
                            cs.childrenStart = true;
                        }
                        else
                        {
                            cs.state = 0;
                        }
                        cs.jsonStart = true;//开始。
                        return true;
                    }
                    #endregion
                    break;
                case '}':
                    #region å¤§æ‹¬å·ç»“束
                    if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
                    {
                        cs.jsonStart = false;//正常结束。
                        cs.state = 0;
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        cs.setDicValue = true;
                        return true;
                    }
                    // cs.isError = !cs.jsonStart && cs.state == 0;
                    #endregion
                    break;
                case '[':
                    #region ä¸­æ‹¬å·å¼€å§‹
                    if (!cs.jsonStart)
                    {
                        cs.arrayStart = true;
                        return true;
                    }
                    else if (cs.jsonStart && cs.state == 1)
                    {
                        cs.childrenStart = true;
                        return true;
                    }
                    #endregion
                    break;
                case ']':
                    #region ä¸­æ‹¬å·ç»“束
                    if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
                    {
                        cs.keyStart = 0;
                        cs.valueStart = 0;
                        cs.arrayStart = false;
                        return true;
                    }
                    #endregion
                    break;
                case '"':
                case '\'':
                    #region å¼•号
                    if (cs.jsonStart || cs.arrayStart)
                    {
                        if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
                        {
                            if (cs.keyStart <= 0)
                            {
                                cs.keyStart = (c == '"' ? 3 : 2);
                                return true;
                            }
                            else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"'))
                            {
                                if (!cs.escapeChar)
                                {
                                    cs.keyStart = -1;
                                    return true;
                                }
                                else
                                {
                                    cs.escapeChar = false;
                                }
                            }
                        }
                        else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
                        {
                            if (cs.valueStart <= 0)
                            {
                                cs.valueStart = (c == '"' ? 3 : 2);
                                return true;
                            }
                            else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"'))
                            {
                                if (!cs.escapeChar)
                                {
                                    cs.valueStart = -1;
                                    return true;
                                }
                                else
                                {
                                    cs.escapeChar = false;
                                }
                            }
                        }
                    }
                    #endregion
                    break;
                case ':':
                    #region å†’号
                    if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
                    {
                        if (cs.keyStart == 1)
                        {
                            cs.keyStart = -1;
                        }
                        cs.state = 1;
                        return true;
                    }
                    // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
                    #endregion
                    break;
                case ',':
                    #region é€—号 //["aa",{aa:12,}]
                    if (cs.jsonStart)
                    {
                        if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
                        {
                            cs.state = 0;
                            cs.keyStart = 0;
                            cs.valueStart = 0;
                            //if (cs.valueStart == 1)
                            //{
                            //    cs.valueStart = 0;
                            //}
                            cs.setDicValue = true;
                            return true;
                        }
                    }
                    else if (cs.arrayStart && cs.keyStart <= 2)
                    {
                        cs.keyStart = 0;
                        //if (cs.keyStart == 1)
                        //{
                        //    cs.keyStart = -1;
                        //}
                        return true;
                    }
                    #endregion
                    break;
                case ' ':
                case '\r':
                case '\n'://[ "a",\r\n{} ]
                case '\0':
                case '\t':
                    if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
                    {
                        return true;//跳过空格。
                    }
                    break;
                default: //值开头。。
                    if (c == '\\') //转义符号
                    {
                        if (cs.escapeChar)
                        {
                            cs.escapeChar = false;
                        }
                        else
                        {
                            cs.escapeChar = true;
                            return true;
                        }
                    }
                    else
                    {
                        cs.escapeChar = false;
                    }
                    if (cs.jsonStart || cs.arrayStart) // Json æˆ–数组开始了。
                    {
                        if (cs.keyStart <= 0 && cs.state == 0)
                        {
                            cs.keyStart = 1;//无引号的
                        }
                        else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
                        {
                            cs.valueStart = 1;//无引号的
                        }
                    }
                    break;
            }
            return false;
        }
        #endregion
        public static LinqExpressionType GetLinqCondition(this string stringType)
        {
            LinqExpressionType linqExpression;
            switch (stringType)
            {
                case HtmlElementType.Contains:
                    linqExpression = LinqExpressionType.In;
                    break;
                case HtmlElementType.ThanOrEqual:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.LessOrequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                case HtmlElementType.GT:
                    linqExpression = LinqExpressionType.GreaterThan;
                    break;
                case HtmlElementType.lt:
                    linqExpression = LinqExpressionType.LessThan;
                    break;
                case HtmlElementType.like:
                    linqExpression = LinqExpressionType.Contains;
                    break;
                case HtmlElementType.thanorequal:
                    linqExpression = LinqExpressionType.ThanOrEqual;
                    break;
                case HtmlElementType.lessorequal:
                    linqExpression = LinqExpressionType.LessThanOrEqual;
                    break;
                    break;
                case HtmlElementType.notequal:
                    linqExpression = LinqExpressionType.NotEqual;
                    break;
                default:
                    linqExpression = LinqExpressionType.Equal;
                    break;
            }
            return linqExpression;
        }
    }
}
                    break;
                default:
                    linqExpression = LinqExpressionType.Equal;
                    break;
            }
            return linqExpression;
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs
@@ -257,12 +257,12 @@
                    // ç©ºæ‰˜ç›˜ä¹Ÿæœ‰åº“存记录,只是不包含明细
                    item.PalletCode = stockInfo.PalletCode;
                    item.StockStatus = stockInfo.StockStatus; // ç›´æŽ¥ä½¿ç”¨åŽç«¯åº“存状态
                    // åªæœ‰å½“Details不为null且有数据时才处理库存明细
                    if (stockInfo.Details != null && stockInfo.Details.Any())
                    {
                        item.StockQuantity = stockInfo.Details.Sum(d => d.StockQuantity);
                        item.OutboundDate = stockInfo.OutboundDate;
                        // èŽ·å–ç¬¬ä¸€ä¸ªæ˜Žç»†çš„ç‰©æ–™ä¿¡æ¯ï¼ˆå¦‚æžœå­˜åœ¨ï¼‰
                        var firstDetail = stockInfo.Details.FirstOrDefault();
                        if (firstDetail != null)
@@ -278,6 +278,7 @@
                            Id = d.Id,
                            MaterielCode = d.MaterielCode,
                            MaterielName = d.MaterielName,
                            SerialNumber = d.SerialNumber,
                            BatchNo = d.BatchNo,
                            StockQuantity = d.StockQuantity,
                            Unit = d.Unit,