liulijun
2026-03-05 98a69d51981ee6a49136024c8b005f134d3313cd
增加任务异常提示和空托数量预警

增加任务异常提示和空托数量预警
已修改7个文件
627 ■■■■ 文件已修改
项目代码/WMS/WMSClient/src/extension/stock/ProStockView.js 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/extension/taskinfo/task.js 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/main.js 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/store/index.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/views/Home.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/views/Index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS/WMSClient/src/views/index/Message.vue 197 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WMS/WMSClient/src/extension/stock/ProStockView.js
@@ -19,6 +19,13 @@
  methods: {
    //下面这些方法可以保留也可以删除
    onInit() {
      // åˆå§‹åŒ–空托检查定时器
      // è®¾ç½®å®šæ—¶å™¨ï¼Œæ¯60秒检查一次
      this.checkEmptyPalletTimer = setInterval(() => {
        this.checkEmptyPalletWarning();
      }, 10000); // æ¯10秒检查一次
      // åŽŸæœ‰ä»£ç ...
      // let InOrder = this.buttons.find(x => x.value == 'StockOutbound');
      // if (InOrder) {
      //   InOrder.onClick = function () {
@@ -73,7 +80,14 @@
              const daysSinceClosest = Math.ceil(Math.abs((today - closestDate) / (1000 * 60 * 60 * 24)));
              return '<span style="color: #F56C6C">' + daysSinceClosest + "天" + '</span>';
            } else {
              return '<span style="color: #F56C6C">' + "无保质期" + '</span>';
              // ç©ºæ‰˜è®°å½•会进入这个分支,返回"1个"或"10个"这样的字符串
              // åœ¨è¿™é‡Œè®°å½•空托数量
              const emptyPalletCount = 1; // æ¯æ¡ç©ºæ‰˜è®°å½•代表1个空托
              // ä¿å­˜åˆ°row对象,方便后续checkEmptyPalletWarning方法使用
              row.emptyPalletCount = emptyPalletCount;
              return '<span style="color: #F56C6C">' + emptyPalletCount + "个" + '</span>';
            }
          }
@@ -88,7 +102,14 @@
                })
              return '<span style="color: #F56C6C">' + sum + row.details[0].unit + '</span>';
            } else {
              return '<span style="color: #F56C6C">' + "1个" + '</span>';
              // ç©ºæ‰˜è®°å½•会进入这个分支,返回"1个"或"10个"这样的字符串
              // åœ¨è¿™é‡Œè®°å½•空托数量
              const emptyPalletCount = 1; // æ¯æ¡ç©ºæ‰˜è®°å½•代表1个空托
              // ä¿å­˜åˆ°row对象,方便后续checkEmptyPalletWarning方法使用
              row.emptyPalletCount = emptyPalletCount;
              return '<span style="color: #F56C6C">' + emptyPalletCount + "个" + '</span>';
            }
          }
@@ -128,6 +149,104 @@
      //(3)this.editFormFields.字段='xxx';
      //如果需要给下拉框设置默认值,请遍历this.editFormOptions找到字段配置对应data属性的key值
      //看不懂就把输出看:console.log(this.editFormOptions)
    },
    // æ£€æŸ¥ç©ºæ‰˜æ•°é‡
    checkEmptyPalletWarning() {
      // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore,检查是否存在相同的警告消息
      const globalObj = this.$global || window.$global || {};
      const store = this.$store || window.$store;
      const globalMessageList = globalObj.messageList || [];
      const storeMessageList = store?.state?.messageList || [];
      // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨æœªæ¸…除的空托预警消息
      const hasExistingWarning = [...globalMessageList, ...storeMessageList].some(msg =>
        msg.businessType === 'pallet_warning' && msg.type === 'warning'
      );
      if (hasExistingWarning) return;
      // èŽ·å–å½“å‰æ‰€æœ‰åº“å­˜æ•°æ®
      const stockData = this.$refs.table?.rowData || this.$refs.table?.tableData || [];
      // è®¡ç®—空托总数量:只计算proStockAttribute为5的记录
      let totalEmptyPalletCount = 0;
      // éåŽ†æ‰€æœ‰åº“å­˜è®°å½•ï¼Œç´¯åŠ ç©ºæ‰˜æ•°é‡
      stockData.forEach(stock => {
        const proStockAttribute = stock.proStockAttribute || stock.ProStockAttribute || 0;
        if (proStockAttribute === 5) {
          // è§£æžsumStock的值,提取数字部分
          const sumStocks = stock.sumStocks || stock.sumStock || 0;
          const stockQuantity = typeof sumStocks === 'string'
            ? parseInt(sumStocks.match(/\d+/)?.[0] || 0)
            : parseInt(sumStocks || 0);
          totalEmptyPalletCount += stockQuantity;
        }
      });
      // ç©ºæ‰˜é¢„警阈值为50个
      const warningThreshold = 50;
      // å¦‚果空托总数量小于阈值,发送警告消息
      if (totalEmptyPalletCount < warningThreshold) {
        this.sendPalletWarningMessage(totalEmptyPalletCount, warningThreshold);
      }
    },
    // å‘送空托警告消息
    sendPalletWarningMessage(emptyPalletCount, warningThreshold) {
      // åˆ›å»ºè­¦å‘Šæ¶ˆæ¯
      const warningMessage = {
        id: Date.now(),
        title: '空托数量预警',
        message: `成品库空托数量不足,当前总数量:${emptyPalletCount},低于预警阈值:${warningThreshold},建议及时补充!`,
        type: 'warning',
        businessType: 'pallet_warning',
        createTime: new Date().toLocaleString(),
        relatedData: {
          EmptyPalletCount: emptyPalletCount,
          Threshold: warningThreshold
        }
      };
      // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore
      const globalObj = this.$global || window.$global || {};
      const store = this.$store || window.$store;
      // æ·»åŠ æ¶ˆæ¯åˆ°store
      if (store) {
        store.commit('addMessage', warningMessage);
      }
      // æ·»åŠ æ¶ˆæ¯åˆ°å…¨å±€æ¶ˆæ¯åˆ—è¡¨ï¼Œç¡®ä¿åˆ—è¡¨å­˜åœ¨
      if (!globalObj.messageList) {
        globalObj.messageList = [];
      }
      globalObj.messageList.push(warningMessage);
      // æ˜¾ç¤ºæç¤ºæ¡†
      // const $alert = this.$alert;
      // const $message = this.$message;
      // if ($alert) {
      //   $alert(warningMessage.message, warningMessage.title, {
      //     confirmButtonText: '确定',
      //     type: warningMessage.type,
      //     closeOnClickModal: false,
      //     closeOnPressEscape: false,
      //     showCancelButton: false
      //   });
      // } else if ($message) {
      //   $message.warning(warningMessage.message);
      // } else {
      //   alert(`${warningMessage.title}: ${warningMessage.message}`);
      // }
    },
    // åœ¨æŸ¥è¯¢åŽå¤„理数据
    searchAfter(result) {
      return true;
    }
  }
};
ÏîÄ¿´úÂë/WMS/WMSClient/src/extension/taskinfo/task.js
@@ -94,6 +94,185 @@
          this.$refs.gridHeader.open();
        }
      }
      // åˆå§‹åŒ–任务状态检查定时器
      this.taskStatusMap = {}; // å­˜å‚¨ä»»åŠ¡çŠ¶æ€å¼€å§‹æ—¶é—´
      this.taskTimeoutMinutes = 1; // ä»»åŠ¡è¶…æ—¶æ—¶é—´ï¼Œå•ä½ä¸ºåˆ†é’Ÿ
      this.checkTaskStatusTimer = setInterval(() => {
        this.checkTaskStatus();
      }, 1000); // æ¯1秒检查一次,提高检查精度,减少延迟
      },
      // æ£€æŸ¥ä»»åŠ¡çŠ¶æ€
      checkTaskStatus() {
        // èŽ·å–å½“å‰æ‰€æœ‰ä»»åŠ¡æ•°æ®
        const taskData = this.$refs.table?.rowData || this.$refs.table?.tableData || [];
        const now = new Date();
        // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore
        const globalObj = this.$global || window.$global || {};
        const store = this.$store || window.$store;
        // å¤„理消息删除逻辑,重置对应任务的定时器
        const deletedMessages = globalObj.messageDeleted || [];
        if (deletedMessages.length > 0) {
          const storeMessageList = store?.state?.messageList || [];
          // éåŽ†è¢«åˆ é™¤çš„æ¶ˆæ¯ID,重置对应任务的定时器
          deletedMessages.forEach(deletedId => {
            const deletedMessage = storeMessageList.find(msg => msg.id === deletedId);
            if (deletedMessage?.businessType === 'task_timeout' && deletedMessage.taskNum && this.taskStatusMap[deletedMessage.taskNum]) {
              this.taskStatusMap[deletedMessage.taskNum] = now;
            }
          });
          // æ¸…空已处理的删除消息列表
          globalObj.messageDeleted = [];
        }
        // èŽ·å–å½“å‰æ‰€æœ‰ä»»åŠ¡å·å’ŒçŠ¶æ€
        const currentTaskStatuses = {};
        taskData.forEach(task => {
          currentTaskStatuses[task.taskNum] = task.taskStatus;
        });
        // æ£€æŸ¥ä»»åŠ¡çŠ¶æ€
        taskData.forEach(task => {
          if (task.taskStatus === 210) {
            // å †åž›æœºæ‰§è¡Œä¸­çŠ¶æ€
            if (!this.taskStatusMap[task.taskNum]) {
              this.taskStatusMap[task.taskNum] = now;
            } else {
              // è®¡ç®—持续时间(分钟)
              const duration = (now - this.taskStatusMap[task.taskNum]) / 60000;
              if (duration >= this.taskTimeoutMinutes) {
                this.sendTaskWarningMessage(task, duration);
                delete this.taskStatusMap[task.taskNum];
              }
            }
          } else {
            // ä»»åŠ¡çŠ¶æ€å·²æ”¹å˜ï¼Œæ¸…é™¤è®°å½•
            delete this.taskStatusMap[task.taskNum];
          }
        });
        // æ¸…除已解决的任务超时消息
        this.clearResolvedTaskMessages(currentTaskStatuses);
      },
      // æ¸…除已解决的任务超时消息
      clearResolvedTaskMessages(currentTaskStatuses) {
        // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore
        const globalObj = this.$global || window.$global || {};
        const store = this.$store || window.$store;
        // èŽ·å–æ‰€æœ‰æ¶ˆæ¯åˆ—è¡¨
        const globalMessageList = globalObj.messageList || [];
        const storeMessageList = store?.state?.messageList || [];
        // åˆå¹¶æ‰€æœ‰æ¶ˆæ¯ï¼Œæ‰¾å‡ºéœ€è¦æ¸…除的任务超时消息
        const allMessages = [...globalMessageList, ...storeMessageList];
        const taskTimeoutMessages = allMessages.filter(msg => msg.businessType === 'task_timeout');
        // éåŽ†æ‰€æœ‰ä»»åŠ¡è¶…æ—¶æ¶ˆæ¯
        taskTimeoutMessages.forEach(msg => {
          const taskNum = msg.taskNum;
          // æ£€æŸ¥è¯¥ä»»åŠ¡æ˜¯å¦ä»ç„¶å¤„äºŽå †åž›æœºæ‰§è¡Œä¸­çŠ¶æ€
          if (currentTaskStatuses[taskNum] && currentTaskStatuses[taskNum] !== 210) {
            // ä»»åŠ¡å·²ä¸å†å¤„äºŽå †åž›æœºæ‰§è¡Œä¸­çŠ¶æ€ï¼Œæ¸…é™¤è¯¥æ¶ˆæ¯
            this.handleDeleteTaskMessage(msg);
          }
        });
      },
      // å¤„理删除单个任务消息
      handleDeleteTaskMessage(message) {
        // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore
        const globalObj = this.$global || window.$global || {};
        const store = this.$store || window.$store;
        // ä»Žå…¨å±€æ¶ˆæ¯åˆ—表中删除该消息
        if (globalObj.messageList) {
          const index = globalObj.messageList.findIndex(msg => msg.id === message.id);
          if (index !== -1) {
            globalObj.messageList.splice(index, 1);
          }
        }
        // ä»Žstore中删除该消息
        if (store) {
          store.commit('removeMessage', message.id);
        }
      },
      // å‘送任务警告消息
      sendTaskWarningMessage(task, duration) {
        // åˆ›å»ºè­¦å‘Šæ¶ˆæ¯
        const warningMessage = {
          id: Date.now(),
          title: '任务异常警告',
          message: `任务号 ${task.taskNum} å·²åœ¨å †åž›æœºæ‰§è¡Œä¸­çŠ¶æ€è¶…è¿‡${Math.round(duration)}分钟,请及时处理!`,
          type: 'warning',
          businessType: 'task_timeout',
          taskNum: task.taskNum,
          createTime: new Date().toLocaleString()
        };
        // èŽ·å–å…¨å±€å¯¹è±¡å’Œstore,检查是否存在相同的警告消息
        const globalObj = this.$global || window.$global || {};
        const store = this.$store || window.$store;
        const globalMessageList = globalObj.messageList || [];
        const storeMessageList = store?.state?.messageList || [];
        // æ£€æŸ¥æ˜¯å¦å·²ç»å­˜åœ¨ç›¸åŒçš„任务超时警告
        const hasExistingWarning = [...globalMessageList, ...storeMessageList].some(msg =>
          msg.businessType === 'task_timeout' && msg.taskNum === task.taskNum
        );
        if (hasExistingWarning) return;
        // å‘送消息到消息列表
        try {
          // æ·»åŠ æ¶ˆæ¯åˆ°store
          const $store = this.$store || window.$store;
          if ($store) {
            $store.commit('addMessage', warningMessage);
          }
          // æ·»åŠ æ¶ˆæ¯åˆ°å…¨å±€æ¶ˆæ¯åˆ—è¡¨
          if (globalObj.messageList) {
            globalObj.messageList.push(warningMessage);
          }
          // æ˜¾ç¤ºè­¦å‘Šå¯¹è¯æ¡†ï¼Œä¼˜å…ˆä½¿ç”¨$alert
          // const $global = this.$global || window.$global;
          // const alertOptions = {
          //   confirmButtonText: '确定',
          //   type: warningMessage.type,
          //   closeOnClickModal: false,
          //   closeOnPressEscape: false,
          //   showCancelButton: false
          // };
          // if (this.$alert || window.$alert) {
          //   const $alert = this.$alert || window.$alert;
          //   $alert(warningMessage.message, warningMessage.title, alertOptions);
          // } else if (this.$confirm || window.$confirm) {
          //   const $confirm = this.$confirm || window.$confirm;
          //   $confirm(warningMessage.message, warningMessage.title, alertOptions);
          // } else {
          //   // ä½¿ç”¨æµè§ˆå™¨åŽŸç”Ÿalert作为备选
          //   alert(`${warningMessage.title}: ${warningMessage.message}`);
          // }
        } catch (error) {
          // å‡ºé”™æ—¶ä½¿ç”¨æµè§ˆå™¨åŽŸç”Ÿalert作为最终备选
          try {
            alert(`任务异常警告: ä»»åŠ¡å· ${task.taskNum} å·²åœ¨å †åž›æœºæ‰§è¡Œä¸­çŠ¶æ€è¶…è¿‡${Math.round(duration)}分钟,请及时处理!`);
          } catch (e) {
            // å¿½ç•¥æ‰€æœ‰é”™è¯¯
          }
        }
      },
      onInited() {
        //框架初始化配置后
@@ -106,7 +285,7 @@
        return true;
      },
      searchAfter(result) {
        //查询后,result返回的查询数据,可以在显示到表格前处理表格的值
        // æŸ¥è¯¢åŽï¼Œresult返回的查询数据,可以在显示到表格前处理表格的值
        return true;
      },
      addBefore(formData) {
ÏîÄ¿´úÂë/WMS/WMSClient/src/main.js
@@ -1,4 +1,4 @@
import { createApp } from 'vue'
import { createApp, reactive } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
@@ -24,7 +24,9 @@
app.config.globalProperties.http = http;
app.config.globalProperties.$tabs = {};
app.config.globalProperties.permission = permission;
app.config.globalProperties.$global = {
app.config.globalProperties.$store = store;
// åˆ›å»ºå“åº”式的全局对象
const globalState = reactive({
    signalR: false, //是否开启signalR
    table: {
        //vol-table带数据源的单元格是否启用tag标签(下拉框等单元格以tag标签显示)
@@ -42,8 +44,16 @@
        // å®¡æ ¸ä¸­ = 2,
        // å®¡æ ¸æœªé€šè¿‡ = 3,
        // é©³å›ž = 4
    }
}
    },
    messageList: [], //全局消息列表
    messageDeleted: [] //存储被删除的消息ID,用于通知组件重置定时器
});
app.config.globalProperties.$global = globalState;
// å°†store挂载到window对象上,方便在扩展组件中访问
window.$store = store;
window.$global = app.config.globalProperties.$global;
//2023.03.13,
//修改见:volupload.vue,后台AliOSSController.cs,阿里云OSS配置.doc
window.oss = {
ÏîÄ¿´úÂë/WMS/WMSClient/src/store/index.js
@@ -15,6 +15,7 @@
    isLoading: false,//2020.06.03增加路由切换时加载提示
    userInfo: null,
    websocke: null,//websocket
    messageList: [],//消息列表
    // wcsState: true//wcs服务状态
  },
  mutations: {
@@ -42,6 +43,15 @@
    },
    setWebsocket(state, data) {
      state.websocke = data;
    },
    addMessage(state, message) {
      state.messageList.push(message);
    },
    removeMessage(state, messageId) {
      state.messageList = state.messageList.filter(message => message.id !== messageId);
    },
    clearMessages(state) {
      state.messageList = [];
    }
  }, getters: {
    getPermission: (state) => (path) => {  //调用方式 store.getters.getPermission('sys_User')
@@ -80,6 +90,9 @@
    getData: (state) => () => {
      return state.data;
    },
    getMessageList: (state) => () => {
      return state.messageList;
    }
  }, actions: {
    setPermission(context, data) {
      context.commit('setPermission', data); //调用方式 store.dispatch('push')
@@ -89,6 +102,9 @@
    },
    onLoading(context, flag) {
      context.commit("updateLoadingState", flag);
    },
    addMessage(context, message) {
      context.commit('addMessage', message);
    }
  }
})
ÏîÄ¿´úÂë/WMS/WMSClient/src/views/Home.vue
@@ -139,6 +139,8 @@
          { bgcolor: "lightgreen", msg: "空闲", state: 0 },
          { bgcolor: "orange", msg: "有货", state: 100 },
          { bgcolor: "#2BB3D5", msg: "锁定", state: 1 },
          { bgcolor: "yellow", msg: "空闲锁定", state: 20 },
          { bgcolor: "purple", msg: "有货锁定", state: 10 },
        ],
        locationData: [],
        showTooltipFlag: false,
@@ -285,6 +287,8 @@
      if (location.location_lock === 0) return "空闲";
      if (location.location_lock === 1) return "锁定";
      if (location.location_lock === 100) return "有货";
      if (location.location_lock === 20) return "空闲锁定";
      if (location.location_lock === 10) return "有货锁定";
      // if (location.location_state > 0 && location.location_state < 100)
      //   return "锁定";
      return "其他";
@@ -407,7 +411,7 @@
}
.location-cell {
  width: 80px;
  width: 85px;
  height: 38px;
  margin: 3px;
  text-align: center;
ÏîÄ¿´úÂë/WMS/WMSClient/src/views/Index.vue
@@ -191,12 +191,29 @@
      destroy-on-close
      size="40%"
    >
      <Message :list="messageList"></Message>
      <div style="margin-bottom: 20px;">
        <el-button type="danger" @click="clearAllMessages">全部清除</el-button>
      </div>
      <Message :list="messageList" @delete-message="handleDeleteMessage"></Message>
    </el-drawer>
  </div>
</template>
<style lang="less" scoped>
@import "./index/index.less";
/* ä¸ºæ¶ˆæ¯åˆ—表的drawer添加圆角 */
:deep(.el-drawer__header) {
  padding: 20px;
}
:deep(.el-drawer__body) {
  padding: 0 20px 20px 20px;
}
:deep(.el-drawer) {
  border-radius: 12px 0 0 12px !important;
  overflow: hidden;
}
</style>
<script>
import loading from "@/components/basic/RouterLoading";
@@ -297,7 +314,6 @@
    const theme = ref("blue2");
    const menuOptions = ref([]);
    const permissionInited = ref(false);
    const messageList = reactive([]);
    let _config = getCurrentInstance().appContext.config.globalProperties;
    let router = useRouter();
    const toggleLeft = () => {
@@ -316,7 +332,8 @@
    const handleMessage = (e) => {
      let data = JSON.parse(e.data);
      messageList.push(data);
      // ä½¿ç”¨store的addMessage mutation添加消息
      store.commit('addMessage', data);
      ElNotification({
        title: data.title,
        message: h("i", { style: "color: teal" }, data.message),
@@ -626,7 +643,8 @@
        //开启消息推送(main.js中设置是否开启signalR)2022.05.05
        if (_config.$global.signalR) {
          MessageConfig(http, (result) => {
            messageList.unshift(result);
            // ä½¿ç”¨store的addMessage mutation添加消息
            store.commit('addMessage', result);
            //    console.log(result)
          });
        }
@@ -654,6 +672,59 @@
      });
    };
    created();
    // å¤„理删除单条消息
    const handleDeleteMessage = ({ item, index }) => {
      // ä»Žå…¨å±€æ¶ˆæ¯åˆ—表中删除该消息
      if (_config.$global.messageList && Array.isArray(_config.$global.messageList)) {
        _config.$global.messageList = _config.$global.messageList.filter(msg => msg.id !== item.id);
      }
      // ä»Žstore中删除该消息
      if (store) {
        // ä½¿ç”¨mutation删除单个消息
        store.commit('removeMessage', item.id);
      }
      // å°†åˆ é™¤çš„æ¶ˆæ¯ID添加到messageDeleted数组,用于通知组件重置定时器
      if (_config.$global.messageDeleted && Array.isArray(_config.$global.messageDeleted)) {
        _config.$global.messageDeleted.push(item.id);
      }
      // æ˜¾ç¤ºæˆåŠŸæç¤º
      _config.$message.success('消息已删除');
      // å¼ºåˆ¶ç»„件更新,确保消息列表立即刷新
      proxy.$nextTick(() => {
        // è§¦å‘重渲染
        _config.$forceUpdate && _config.$forceUpdate();
      });
    };
    // æ¸…理全部消息
    const clearAllMessages = () => {
      // èŽ·å–æ‰€æœ‰å½“å‰æ¶ˆæ¯çš„ID,用于重置定时器
      const messageIds = _config.$global.messageList.map(msg => msg.id);
      // å…ˆæ¸…空store中的消息列表
      store.commit('clearMessages');
      // ç„¶åŽæ¸…空全局消息列表,使用重新赋值的方式确保响应式更新
      _config.$global.messageList = [];
      // å°†æ‰€æœ‰åˆ é™¤çš„æ¶ˆæ¯ID添加到messageDeleted数组,用于通知组件重置定时器
      if (_config.$global.messageDeleted && Array.isArray(_config.$global.messageDeleted)) {
        _config.$global.messageDeleted.push(...messageIds);
      }
      // æ˜¾ç¤ºæˆåŠŸæç¤º
      _config.$message.success('消息已全部清除');
      // å¼ºåˆ¶ç»„件更新,确保消息列表立即刷新
      proxy.$nextTick(() => {
        // è§¦å‘重渲染
        _config.$forceUpdate && _config.$forceUpdate();
      });
    };
    return {
      menuWidth,
      isCollapse,
@@ -681,12 +752,17 @@
      to,
      toggleLeft,
      messageModel,
      messageList,
      // ä»Žå…¨å±€å¯¹è±¡ä¸­èŽ·å–æ¶ˆæ¯åˆ—è¡¨
      get messageList() {
        return _config.$global.messageList;
      },
      contextMenuVisible,
      visibleItem,
      closeTabsMenu,
      closeTabs,
      currentMenuId,
      clearAllMessages,
      handleDeleteMessage,
    };
  },
  /**
ÏîÄ¿´úÂë/WMS/WMSClient/src/views/index/Message.vue
@@ -1,57 +1,80 @@
<template>
  <div class="message-container">
    <div class="item" v-for="(item, index) in list" :key="index">
      <div class="title">{{ item.title }}({{ item.date }})</div>
    <div class="item" v-for="(item, index) in list" :key="item.id || index">
      <div class="title-container">
        <div class="title">{{ item.title }}({{ item.createTime || item.date }})</div>
        <el-button
          type="text"
          class="delete-btn"
          @click="handleDeleteMessage(item, index)"
          size="small"
        >
          <i class="el-icon-close"></i>
        </el-button>
      </div>
      <div class="content">
        <el-row>
          <el-col :span="8">
            <label>收货单号:{{ item.formData.receiveOrderNo }}</label>
          </el-col>
          <el-col :span="8">
            <label>质检单号:{{ item.formData.checkOrderNo }}</label>
          </el-col>
          <el-col :span="8">
            <label>收货明细行号:{{ item.formData.receiveDetailRowNo }}</label>
          </el-col>
        </el-row>
        <!-- å¦‚果有formData,显示质检审批相关内容 -->
        <template v-if="item.formData">
          <el-row>
            <el-col :span="8">
              <label>收货单号:{{ item.formData.receiveOrderNo }}</label>
            </el-col>
            <el-col :span="8">
              <label>质检单号:{{ item.formData.checkOrderNo }}</label>
            </el-col>
            <el-col :span="8">
              <label>收货明细行号:{{ item.formData.receiveDetailRowNo }}</label>
            </el-col>
          </el-row>
        <el-row>
          <el-col :span="8">
            <label>物料编号:{{ item.formData.materielCode }}</label>
          </el-col>
          <el-col :span="8">
            <label>合格数量:{{ item.formData.qualifiedQuantity }}</label>
          </el-col>
          <el-col :span="8">
            <label>特采数量:{{ item.formData.defectedQuantity }}</label>
          </el-col>
        </el-row>
          <el-row>
            <el-col :span="8">
              <label>物料编号:{{ item.formData.materielCode }}</label>
            </el-col>
            <el-col :span="8">
              <label>合格数量:{{ item.formData.qualifiedQuantity }}</label>
            </el-col>
            <el-col :span="8">
              <label>特采数量:{{ item.formData.defectedQuantity }}</label>
            </el-col>
          </el-row>
        <el-row>
          <el-col :span="8">
            <label>退货数量:{{ item.formData.returnQuantity }}</label>
          </el-col>
          <el-col :span="8">
            <label>报废数量:{{ item.formData.scrappedQuantity }}</label>
          </el-col>
          <el-col :span="8">
            <label>质检总数:{{ item.formData.receivedQuantity }}</label>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="16">
            <label>特采说明:{{ item.formData.defectedNote }}</label>
          </el-col>
          <el-col :span="8">
            <label>检验人:{{ item.formData.checkUserName }}</label>
          </el-col>
        </el-row>
          <el-row>
            <el-col :span="8">
              <label>退货数量:{{ item.formData.returnQuantity }}</label>
            </el-col>
            <el-col :span="8">
              <label>报废数量:{{ item.formData.scrappedQuantity }}</label>
            </el-col>
            <el-col :span="8">
              <label>质检总数:{{ item.formData.receivedQuantity }}</label>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="16">
              <label>特采说明:{{ item.formData.defectedNote }}</label>
            </el-col>
            <el-col :span="8">
              <label>检验人:{{ item.formData.checkUserName }}</label>
            </el-col>
          </el-row>
          <div style="margin-top: 20px">
            <el-button type="primary">同意</el-button
            ><el-button type="danger">驳回</el-button>
          </div>
        </template>
        <!-- å¦åˆ™æ˜¾ç¤ºæ™®é€šæ¶ˆæ¯å†…容 -->
        <template v-else>
          <div class="simple-message">
            {{ item.message || '无消息内容' }}
          </div>
        </template>
      </div>
      <div style="margin-top: 20px">
        <el-button type="primary">同意</el-button
        ><el-button type="danger">驳回</el-button>
      </div>
    </div>
    <!-- å¦‚果没有消息,显示提示 -->
    <div v-if="list.length === 0" class="no-message">
      æš‚无消息
    </div>
  </div>
</template>
@@ -88,21 +111,87 @@
    //   });
    // }
  },
  methods: {
    // å¤„理确认按钮点击事件
    handleConfirm(item) {
      console.log('确认消息:', item);
      // è¿™é‡Œå¯ä»¥æ·»åŠ ç¡®è®¤åŽçš„é€»è¾‘ï¼Œæ¯”å¦‚ä»Žæ¶ˆæ¯åˆ—è¡¨ä¸­ç§»é™¤è¯¥æ¶ˆæ¯
      // ç”±äºŽprops是单向数据流,需要通过事件通知父组件处理
      this.$emit('confirm', item);
    },
    // å¤„理删除单条消息
    handleDeleteMessage(item, index) {
      // é€šè¿‡äº‹ä»¶é€šçŸ¥çˆ¶ç»„件删除该消息
      this.$emit('delete-message', { item, index });
    }
  }
};
</script>
<style scoped lang="less">
.message-container {
  .title {
    padding-bottom: 10px;
    font-weight: bold;
  }
  padding: 10px;
  background-color: #fafafa;
  border-radius: 12px;
  .item {
    border-bottom: 1px solid #eee;
    padding: 10px 20px;
    background-color: white;
    border: 1px solid #e4e7ed;
    border-radius: 12px;
    padding: 15px 20px;
    margin-bottom: 15px;
    position: relative;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
    &:hover {
      box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
      transform: translateY(-2px);
    }
    &:last-child {
      margin-bottom: 0;
    }
  }
  .title-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
  }
  .title {
    font-weight: bold;
    flex: 1;
    color: #303133;
    font-size: 16px;
  }
  .delete-btn {
    margin-left: 10px;
    color: #909399;
    &:hover {
      color: #f56c6c;
    }
  }
  .content {
    color: #1b1b1b;
    font-size: 14px;
  }
  .simple-message {
    line-height: 1.7;
    color: #606266;
  }
  .no-message {
    text-align: center;
    padding: 50px 0;
    color: #909399;
    background-color: white;
    border-radius: 12px;
    border: 1px solid #e4e7ed;
  }
}
</style>