| | |
| | | <template> |
| | | <div class="title"></div> |
| | | <div class="container"> |
| | | <div class="header"> |
| | | <h2 class="title">货位排图</h2> |
| | | </div> |
| | | |
| | | <div class="content-wrapper"> |
| | | <!-- 控制面板区域 --> |
| | | <div class="control-panel"> |
| | | <div class="form-group"> |
| | | <label>区域:</label> |
| | | <el-select |
| | | size="mini" |
| | | filterable |
| | | v-model="Area.shelf_code" |
| | | placeholder="请选择" |
| | | class="full-width" |
| | | > |
| | | <el-option |
| | | v-for="item in slectData" |
| | | :value="item.shelf_code" |
| | | :label="item.house_name" |
| | | :key="item.house_name" |
| | | ></el-option> |
| | | </el-select> |
| | | </div> |
| | | |
| | | <div class="form-group"> |
| | | <label>排:</label> |
| | | <el-select |
| | | size="mini" |
| | | clearable |
| | | filterable |
| | | @change="SCChange" |
| | | v-model="Area.tunnel" |
| | | placeholder="请选择" |
| | | class="full-width" |
| | | > |
| | | <el-option |
| | | v-for="item in scList" |
| | | :value="item" |
| | | :label="item" |
| | | :key="item" |
| | | ></el-option> |
| | | </el-select> |
| | | </div> |
| | | |
| | | <el-button type="success" class="refresh-btn" @click="GetViewData"> |
| | | 刷新 |
| | | </el-button> |
| | | |
| | | <div class="legend-section"> |
| | | <h4>说明</h4> |
| | | <div class="legend-grid"> |
| | | <div |
| | | class="legend-item" |
| | | v-for="item in infoMsg" |
| | | :key="item.bgcolor" |
| | | > |
| | | <span |
| | | class="color-box" |
| | | :style="{ 'background-color': item.bgcolor }" |
| | | ></span> |
| | | <span class="legend-label">{{ item.msg }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 货位展示区域 --> |
| | | <div class="location-view"> |
| | | <div |
| | | class="layer-container" |
| | | v-for="layer in locationData" |
| | | :key="layer.index" |
| | | > |
| | | <h3 class="layer-title">第{{ layer.index }}层</h3> |
| | | <div class="row" v-for="row in layer.rows" :key="row.index"> |
| | | <div |
| | | class="location-cell" |
| | | :style="{ 'background-color': GetBgColor(col) }" |
| | | v-for="col in row.cols" |
| | | :key="col.index" |
| | | @mouseenter="showTooltip(col, $event)" |
| | | @mouseleave="hideTooltip" |
| | | > |
| | | {{ row.index }}-{{ col.index }}-{{ layer.index }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 悬浮提示框 --> |
| | | <div |
| | | v-if="showTooltipFlag" |
| | | class="location-tooltip" |
| | | :style="{ |
| | | left: tooltipPosition.x + 'px', |
| | | top: tooltipPosition.y + 'px', |
| | | }" |
| | | > |
| | | <div v-if="currentLocation"> |
| | | <p><strong>货位号:</strong>{{ currentLocation.locationCode }}</p> |
| | | <p> |
| | | <strong>货位排列层:</strong> {{ currentLocation.row }}排{{ |
| | | currentLocation.index |
| | | }}列{{ currentLocation.layer }}层 |
| | | </p> |
| | | <p><strong>状态:</strong> {{ getStatusText(currentLocation) }}</p> |
| | | <p> |
| | | <strong>禁用:</strong> |
| | | {{ currentLocation.location_lock == 3 ? "是" : "否" }} |
| | | </p> |
| | | <!-- 恢复物料信息显示,适配有货状态 --> |
| | | <p v-if="currentLocation.location_state === 2"> |
| | | <strong>物料编码:</strong> |
| | | {{ currentLocation.material_code || "无" }} |
| | | </p> |
| | | <p v-if="currentLocation.location_state === 2"> |
| | | <strong>数量:</strong> {{ currentLocation.quantity || "无" }} |
| | | </p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref, reactive } from 'vue' |
| | | import { ElButton } from "element-plus"; |
| | | |
| | | export default { |
| | | setup() { |
| | | data() { |
| | | return { |
| | | slectData: [], |
| | | scList: [], |
| | | Area: { house_name: "", tunnel: "", shelf_code: "" }, |
| | | mian_height: "", |
| | | infoMsg: [ |
| | | { bgcolor: "lightgreen", msg: "空货位", state: 0 }, |
| | | { bgcolor: "orange", msg: "有货", state: 2 }, // 关键改:state从100→2 |
| | | { bgcolor: "#2BB3D5", msg: "锁定", state: "InAssigned" }, |
| | | { bgcolor: "#ccc", msg: "禁用", state: 3 }, |
| | | { bgcolor: "#b7ba6b", msg: "其它", state: "else" }, |
| | | ], |
| | | locationData: [], |
| | | showTooltipFlag: false, |
| | | currentLocation: null, |
| | | tooltipPosition: { x: 0, y: 0 }, |
| | | }; |
| | | }, |
| | | computed: { |
| | | GetBgColor() { |
| | | return (col) => { |
| | | var bgColor = "#b7ba6b"; |
| | | //优先显示禁用状态 |
| | | if (col.location_lock == 3) { |
| | | this.infoMsg.forEach((el) => { |
| | | if (el.state == col.location_lock) { |
| | | bgColor = el.bgcolor; |
| | | } |
| | | }); |
| | | } else { |
| | | this.infoMsg.forEach((el) => { |
| | | // 关键改:匹配有货状态(2),而非100 |
| | | if (col.location_state === 2) { |
| | | bgColor = this.infoMsg.find(item => item.state === 2).bgcolor; |
| | | } |
| | | // 锁定状态(1/10/20/99)逻辑保持不变 |
| | | else if (col.location_state > 0 && col.location_state < 100) { |
| | | if (el.state == "InAssigned") { |
| | | bgColor = el.bgcolor; |
| | | } |
| | | } |
| | | // 空货位(0)逻辑保持不变 |
| | | else if (el.state == col.location_state) { |
| | | bgColor = el.bgcolor; |
| | | } |
| | | }); |
| | | } |
| | | return bgColor; |
| | | }; |
| | | }, |
| | | }, |
| | | watch: { |
| | | //切换库区 |
| | | "Area.shelf_code"(newValue, oldValue) { |
| | | this.scList = []; |
| | | this.slectData.forEach((e) => { |
| | | if (e.shelf_code == newValue) { |
| | | this.Area.tunnel = e.tunnel[0]; |
| | | this.scList = e.tunnel; |
| | | } |
| | | }); |
| | | this.GetViewData(); |
| | | }, |
| | | }, |
| | | methods: { |
| | | GetViewData() { |
| | | var _this = this; |
| | | this.http |
| | | .post("/api/LocationInfoRow/GetLocationStatu", _this.Area, "查询中") |
| | | .then((x) => { |
| | | _this.locationData = x; |
| | | console.log("后端返回:", x); |
| | | }); |
| | | }, |
| | | // 切换排 |
| | | SCChange() { |
| | | this.GetViewData(); |
| | | }, |
| | | showTooltip(location, event) { |
| | | this.currentLocation = location; |
| | | this.showTooltipFlag = true; |
| | | |
| | | } |
| | | } |
| | | } |
| | | // 设置提示框位置,稍微偏移避免遮挡鼠标 |
| | | this.tooltipPosition = { |
| | | x: event.clientX + 10, |
| | | y: event.clientY + 10, |
| | | }; |
| | | }, |
| | | |
| | | hideTooltip() { |
| | | this.showTooltipFlag = false; |
| | | this.currentLocation = null; |
| | | }, |
| | | |
| | | getStatusText(location) { |
| | | // 关键改:明确匹配有货状态(2) |
| | | if (location.location_state === 2) return "有货"; |
| | | if (location.location_state === 0) return "空货位"; |
| | | if (location.location_state === 1) return "锁定"; |
| | | if (location.location_state === 10) return "有货锁定"; |
| | | if (location.location_state === 20) return "空闲锁定"; |
| | | if (location.location_state === 99) return "大托盘锁定"; |
| | | return "其他"; |
| | | }, |
| | | }, |
| | | mounted() { |
| | | var mainHeight = document.getElementById("vol-main"); |
| | | this.mian_height = mainHeight.offsetHeight - 40 + "px"; |
| | | var _this = this; |
| | | //加载下拉选项 |
| | | this.http.get("/api/LocationInfoRow/GetArea", {}, "查询中").then((x) => { |
| | | _this.slectData = x; |
| | | //加载第一个区域,第一排 |
| | | _this.Area.shelf_code = _this.slectData[0].shelf_code; |
| | | _this.scList = _this.slectData[0].tunnel; |
| | | }); |
| | | }, |
| | | components: { ElButton }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .title { |
| | | line-height: 70vh; |
| | | /* 样式部分无修改,保持原逻辑 */ |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .header { |
| | | text-align: center; |
| | | font-size: 28px; |
| | | color: orange; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .title { |
| | | font-size: 20px; |
| | | font-weight: bold; |
| | | margin: 0; |
| | | } |
| | | |
| | | .content-wrapper { |
| | | display: flex; |
| | | flex: 1; |
| | | min-height: 0; |
| | | } |
| | | |
| | | .control-panel { |
| | | width: 220px; |
| | | padding: 15px; |
| | | background-color: #f5f7fa; |
| | | border-radius: 4px; |
| | | margin-right: 15px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .form-group { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .full-width { |
| | | width: 100%; |
| | | } |
| | | |
| | | .refresh-btn { |
| | | margin-top: 10px; |
| | | width: 100%; |
| | | } |
| | | |
| | | .legend-section { |
| | | margin-top: 30px; |
| | | } |
| | | |
| | | .legend-section h4 { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .legend-grid { |
| | | display: grid; |
| | | grid-template-columns: 1fr; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .legend-item { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .color-box { |
| | | display: inline-block; |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-right: 8px; |
| | | border-radius: 3px; |
| | | } |
| | | |
| | | .legend-label { |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .location-view { |
| | | flex: 1; |
| | | overflow: auto; |
| | | padding: 10px; |
| | | background-color: white; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .layer-container { |
| | | margin-bottom: 25px; |
| | | } |
| | | |
| | | .layer-title { |
| | | margin: 0 0 10px 0; |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | |
| | | .row { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | margin-bottom: 8px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .location-cell { |
| | | width: 66px; |
| | | height: 38px; |
| | | margin: 3px; |
| | | text-align: center; |
| | | font-size: 14px; |
| | | border-radius: 3px; |
| | | line-height: 38px; |
| | | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .location-tooltip { |
| | | position: fixed; |
| | | z-index: 9999; |
| | | background-color: white; |
| | | border: 1px solid #ddd; |
| | | border-radius: 4px; |
| | | padding: 10px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | pointer-events: none; |
| | | max-width: 250px; |
| | | } |
| | | |
| | | .location-tooltip p { |
| | | margin: 5px 0; |
| | | font-size: 13px; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .location-tooltip strong { |
| | | display: inline-block; |
| | | width: 70px; |
| | | color: #666; |
| | | } |
| | | </style> |