From cfae899789f4dbe52d7e6b484f83dabbbc44b46b Mon Sep 17 00:00:00 2001 From: zhangdi <15053473693@163.com> Date: Fri, 26 Dec 2025 17:23:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E6=A0=B7=E5=BC=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedulingDashboard/index.vue | 870 +++++++++++--- .../schedulingDashboard/index111.vue | 1059 ----------------- 2 files changed, 676 insertions(+), 1253 deletions(-) delete mode 100644 src/views/productionSchedulingPlan/schedulingDashboard/index111.vue diff --git a/src/views/productionSchedulingPlan/schedulingDashboard/index.vue b/src/views/productionSchedulingPlan/schedulingDashboard/index.vue index 734db00..fdbec32 100644 --- a/src/views/productionSchedulingPlan/schedulingDashboard/index.vue +++ b/src/views/productionSchedulingPlan/schedulingDashboard/index.vue @@ -3,7 +3,7 @@ - + - + - + - + + + + + + + + + + + + + + + + - +
搜索 @@ -93,25 +121,42 @@ 导出
- - 已完成 + + 未开始 +
+
- - 进行中 + + 进行中 +
- - 未开始 + + 已完成 +
-
+
+
序号
订单信息
@@ -125,6 +170,7 @@ }" >
+
{{ index + 1 }}
订单号:{{ order.woCode }}
@@ -132,17 +178,12 @@
零件号:{{ order.partCode }}
- -
批次号:{{ order.batchNo }}
- -
- -
数量:{{ order.makeQty }}
- -
- -
质量等级:{{ order.productIdent }}
- + +
+ {{ order.batchNo }} / {{ order.makeQty }} / {{ order.productIdent }} / {{ order.priorityAps }} +
@@ -154,62 +195,73 @@
+ +
+ +
+ +
- {{ time }} + {{ formatHourLabel(time.label) }}
-
+
- {{ time }} -
-
-
-
- {{ time }} + {{ time.label }}
+ +
-
+
-
-
-
+ -
+
+
现在
+
@@ -220,7 +272,7 @@ v-for="(time, index) in majorTickLabels" :key="index" class="grid-line" - :style="{ left: `${(index / 24) * 100}%` }" + :style="{ left: `${time.position}%` }" >
@@ -239,13 +291,16 @@ v-for="(task, taskIndex) in layer" :key="taskIndex" class="task-bar" + :class="{ + 'task-bar-narrow': getWidthPercent(task.startTime, task.endTime) < 6, + }" :style="{ left: `${getPositionPercent(task.startTime)}%`, width: `${getWidthPercent(task.startTime, task.endTime)}%`, backgroundColor: getStatusColor(task), top: `${getLayerOffset( layerIndex, - getLayeredTasks(order.woCode).length, + getLayerTaskHeight(getLayeredTasks(order.woCode).length, order.woCode), order.woCode )}px`, height: `${getLayerTaskHeight( @@ -258,17 +313,21 @@ >
{{ task.processName }}
+
+ {{ task.processName }} +
@@ -383,8 +442,13 @@ export default { processName: '', //工序 processId: '', //工序 woCode: '', //车间订单号 + timeRange: [], //时间范围 + receiveTime: '', //接收时间 + partCode: '', //订单号 + batchNo: '', //批次号 + planStatusList: [], //工序状态 }, - zoomLevel: 12, // 缩放级别 (1-4) + zoomLevel: 1, // 缩放级别 (1-4) minZoom: 1, maxZoom: 4, @@ -396,7 +460,7 @@ export default { // 分页参数 currentPage: 1, - pageSize: 6, + pageSize: 10, // 提示框相关 tooltipVisible: false, @@ -405,8 +469,8 @@ export default { tooltipY: 0, // 样式相关 - baseRowHeight: 70, - baseRowChartHeight: 71, + baseRowHeight: 50, + baseRowChartHeight: 51, rowHeights: {}, selectTeamOptions: [], selectEquipOptions: [], @@ -414,61 +478,243 @@ export default { // 当前时间位置 currentTimePosition: 0, + + timelineWidth: 300, // 3天的宽度 (每天100%) + baseStartTime: null, // 基准开始时间 + currentViewStartTime: null, // 当前视图开始时间 + currentViewEndTime: null, // 当前视图结束时间 + + legendStatus: { + completed: false, + processing: true, + pending: true, + }, }; }, computed: { - timelineWidth() { - return 100 * this.zoomLevel; + // 计算基准开始时间(今天0点) + baseDate() { + if (this.formLabelAlign.timeRange && this.formLabelAlign.timeRange.length === 2) { + const start = new Date(this.formLabelAlign.timeRange[0]); + start.setHours(0, 0, 0, 0); + return start; + } + // 默认显示当前日期 + const now = new Date(); + const base = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0); + return base; }, - majorTickLabels() { - return Array.from({ length: 24 }, (_, i) => `${i}:00`); + // 计算结束日期 + endDate() { + if (this.formLabelAlign.timeRange && this.formLabelAlign.timeRange.length === 2) { + const end = new Date(this.formLabelAlign.timeRange[1]); + end.setHours(23, 59, 59, 999); + return end; + } + // 默认显示当前日期+2天 + const now = new Date(); + const base = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 2, 23, 59, 59, 999); + return base; }, - minorTickLabels() { - const labels = []; - for (let hour = 0; hour < 24; hour++) { - labels.push(''); - labels.push(`${hour}:30`); + // 计算总小时数 + totalHours() { + const diffTime = this.endDate - this.baseDate; + return Math.ceil(diffTime / (1000 * 60 * 60)); // 计算总小时数 + }, + + // 计算当前视图开始时间(当前小时) + viewStartTime() { + return this.baseDate; + }, + + // 生成3天的时间刻度 + timelineHours() { + const hours = []; + const start = new Date(this.baseDate); + + for (let i = 0; i < this.totalHours; i++) { + const hour = new Date(start); + hour.setHours(start.getHours() + i); + hours.push(hour); } - return labels; + return hours; }, - quarterTickLabels() { + + // 生成主要时间标签(每小时) + majorTickLabels() { const labels = []; - for (let hour = 0; hour < 24; hour++) { - labels.push(''); // 0分位置留空(与小时刻度重叠) - labels.push(`${hour}:15`); - labels.push(''); // 30分位置留空(与半小时刻度重叠) - labels.push(`${hour}:45`); + const start = new Date(this.baseDate); + const end = new Date(this.endDate); + + for (let i = 0; i < this.totalHours; i++) { + const hour = new Date(start); + hour.setHours(start.getHours() + i); + + // 检查时间是否超出结束时间 + if (hour > end) { + break; // 如果超出结束时间则停止添加 + } + + // 计算时间点在时间轴上的位置百分比 + const timeDiff = hour - this.baseDate; + const totalDuration = this.totalHours * 60 * 60 * 1000; // 总毫秒数 + const positionPercent = (timeDiff / totalDuration) * 100; + + labels.push({ + time: hour, + label: `${hour.getMonth() + 1}-${hour.getDate()} ${hour.getHours()}:00`, + position: Math.min(100, positionPercent), // 确保不超过100% + }); } return labels; }, - tenMinuteTickLabels() { + + // 生成日期标签 + dateLabels() { + const dates = []; + const start = new Date(this.baseDate); + const end = new Date(this.endDate); + + // 计算总天数 + const totalDays = Math.ceil((end - start) / (1000 * 60 * 60 * 24)); + + for (let i = 0; i <= totalDays; i++) { + const date = new Date(start); + date.setDate(start.getDate() + i); + + // 检查日期是否超出结束日期 + if (date > end) { + break; // 如果超出结束日期则停止添加 + } + + // 计算每个日期在时间轴上的开始位置百分比 + const timeDiff = date - this.baseDate; + const totalDuration = this.totalHours * 60 * 60 * 1000; // 总毫秒数 + const positionPercent = (timeDiff / totalDuration) * 100; + + // 确保位置在有效范围内 + if (positionPercent <= 100) { + dates.push({ + date: date, + position: Math.max(0, Math.min(100, positionPercent)), + label: `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`, // 显示年/月/日 + dayName: this.getDayName(date.getDay()), + }); + } + } + return dates; + }, + + // 生成次要时间标签(每半小时) + minorTickLabels() { const labels = []; - for (let hour = 0; hour < 24; hour++) { - // 每小时包含6个10分钟刻度(0,10,20,30,40,50) - // 0分和30分位置留空避免与已有刻度重叠 - labels.push(''); // 0分 - labels.push(`${hour}:10`); - labels.push(`${hour}:20`); - labels.push(''); // 30分 - labels.push(`${hour}:40`); - labels.push(`${hour}:50`); + const start = new Date(this.baseDate); + const end = new Date(this.endDate); // 添加结束时间变量 + const totalHalfHours = this.totalHours * 2; // 每小时2个刻度 + + for (let i = 0; i < totalHalfHours; i++) { + const halfHour = new Date(start); + halfHour.setHours(start.getHours() + Math.floor(i / 2), (i % 2) * 30, 0, 0); + + // 检查时间是否超出结束时间 + if (halfHour > end) { + break; // 如果超出结束时间则停止添加 + } + + // 计算时间点在时间轴上的位置百分比 + const timeDiff = halfHour - this.baseDate; + const totalDuration = this.totalHours * 60 * 60 * 1000; // 总毫秒数 + const positionPercent = (timeDiff / totalDuration) * 100; + + if (i % 2 === 1) { + // 只显示半小时标记 + labels.push({ + time: halfHour, + label: `${halfHour.getMonth() + 1}-${halfHour.getDate()} ${halfHour.getHours()}:30`, + position: Math.min(100, positionPercent), // 确保不超过100% + }); + } } return labels; }, + + // 当前时间位置 + currentTimePosition() { + const now = new Date(); + const viewStart = this.baseDate; + const viewEnd = this.endDate; + + // 如果当前时间不在显示范围内,返回-1表示不显示 + if (now < viewStart || now > viewEnd) { + return -1; + } + + const diffMs = now - viewStart; + const totalDuration = this.totalHours * 60 * 60 * 1000; + const positionPercent = (diffMs / totalDuration) * 100; + + return Math.max(0, Math.min(100, positionPercent)); + }, + // 动态计算时间轴宽度 + timelineWidth() { + // 根据时间范围动态调整时间轴宽度 + return Math.max(100, this.totalHours * (100 / 24)); // 每24小时为100%宽度,最小为100% + }, + // 动态计算甘特图容器高度 + ganttWrapperHeight() { + // 根据实际页面元素计算可用高度 + return `calc(100vh - 250px)`; // 调整数值以适应您的页面布局 + }, }, mounted() { - this.formLabelAlign.startTime = new Date().toISOString().substr(0, 10); this.getSelectTeam(); this.getSelectEquip(); this.getProcessSet(); - this.getData(); - this.calcCurrentTimePosition(); - // 定时更新当前时间线位置 - setInterval(() => { + this.updateTime(); + this.updateTimeAxis(); + this.$nextTick(() => { this.calcCurrentTimePosition(); - }, 600000); // 每分钟更新一次 + }); + + // 定时更新当前时间线位置 + // setInterval(() => { + // this.calcCurrentTimePosition(); + // }, 60000); }, methods: { + updateTime() { + // 设置默认时间范围为今天到后两天 + const today = new Date(); + const endDay = new Date(today); + endDay.setDate(today.getDate() + 2); + // 设置日期范围,格式为 YYYY-MM-DD + const startDate = today.toISOString().split('T')[0]; + const endDate = endDay.toISOString().split('T')[0]; + + this.formLabelAlign.timeRange = [startDate, endDate]; + this.handleLegendChange(); + }, + // 处理图例状态变化 + handleLegendChange() { + // 如果需要重新加载数据,可以调用 + this.formLabelAlign.planStatusList = []; + if (this.legendStatus.completed) { + this.formLabelAlign.planStatusList.push('5'); + } + if (this.legendStatus.processing) { + this.formLabelAlign.planStatusList.push('2', '3'); + } + if (this.legendStatus.pending) { + this.formLabelAlign.planStatusList.push('1'); + } + + this.getData(); + }, + // 获取星期名称 + getDayName(dayIndex) { + const days = ['', '一', '二', '三', '四', '五', '六']; + return `星期${days[dayIndex]}`; + }, processChange(val) { this.formLabelAlign.processName = val.name; }, @@ -483,7 +729,6 @@ export default { exportXls() { exportBlob(`/blade-scheduling/workOrder/exportBoard`, this.formLabelAlign).then(res => { // - console.log(this.$route.path == '/productionSchedulingPlan/schedulingDashboard/index'); if (this.$route.path == '/productionSchedulingPlan/schedulingDashboard/index') { downloadXls(res.data, `排产看板数据.xlsx`); } else { @@ -507,25 +752,27 @@ export default { } }); }, - // 计算当前时间在时间轴上的位置百分比 - calcCurrentTimePosition() { - const now = new Date(); - const hours = now.getHours(); - const minutes = now.getMinutes(); - const totalMinutes = hours * 60 + minutes; - this.currentTimePosition = (totalMinutes / (24 * 60)) * 100; - - // 自动滚动到当前时间位置 - this.scrollToCurrentTime(); - }, // 滚动到当前时间位置 scrollToCurrentTime() { const container = this.$refs.timelineContainer; - if (container) { - const scrollPosition = - (this.currentTimePosition / 100) * container.scrollWidth - container.clientWidth / 2; - container.scrollLeft = scrollPosition; + if (container && this.currentTimePosition >= 0 && this.currentTimePosition <= 100) { + // 计算当前时间位置的像素值 + const scrollWidth = container.scrollWidth; + const containerWidth = container.clientWidth; + + // 计算当前时间位置的像素坐标 + const timePositionPx = (this.currentTimePosition / 100) * scrollWidth; + + // 计算需要滚动到的位置,使当前时间线在左侧可见 + // 使用容器宽度的1/4位置作为目标,使当前时间在左侧区域显示 + const targetPosition = timePositionPx - containerWidth / 100; + + // 平滑滚动到指定位置 + container.scrollTo({ + left: Math.max(0, Math.min(scrollWidth - containerWidth, targetPosition)), + behavior: 'smooth', // 平滑滚动 + }); } }, @@ -547,6 +794,13 @@ export default { // 数据获取 getData() { + if (this.formLabelAlign.timeRange.length > 0) { + this.formLabelAlign.startTime = this.formLabelAlign.timeRange[0]; + this.formLabelAlign.endTime = this.formLabelAlign.timeRange[1]; + } + if (this.formLabelAlign.planStatusList.length <= 0) { + this.formLabelAlign.planStatusList = null; + } getData(this.formLabelAlign).then(res => { this.processData(res.data.data); }); @@ -584,13 +838,14 @@ export default { batchNo: firstTask.batchNo, makeQty: firstTask.makeQty, productIdent: firstTask.productIdent, + priorityAps: firstTask.priorityAps, }); } // 处理任务数据 woTasks.forEach(task => { tasks.push({ ...task, - status: this.calcTaskStatus(task.startTime, task.endTime), + // status: this.calcTaskStatus(task.startTime, task.endTime), }); }); }); @@ -598,6 +853,7 @@ export default { this.allOrders = orders; this.totalOrders = orders.length; this.taskData = tasks; + this.updateCurrentPageOrders(); }, @@ -605,23 +861,54 @@ export default { calcTaskStatus(startTime, endTime) { const now = new Date(); const current = now.getHours() * 60 + now.getMinutes(); - const start = this.timeToMinutes(startTime); - let end = this.timeToMinutes(endTime); - if (end < start) end += 24 * 60; + // 解析开始时间 + let startMinutes; + if (startTime.includes(' ')) { + const timePart = startTime.split(' ')[1]; + const [startHour, startMinute] = timePart.split(':').map(Number); + startMinutes = startHour * 60 + startMinute; + } else { + const [startHour, startMinute] = startTime.split(':').map(Number); + startMinutes = startHour * 60 + startMinute; + } + + // 解析结束时间 + let endMinutes; + if (endTime.includes(' ')) { + const timePart = endTime.split(' ')[1]; + const [endHour, endMinute] = timePart.split(':').map(Number); + endMinutes = endHour * 60 + endMinute; + } else { + const [endHour, endMinute] = endTime.split(':').map(Number); + endMinutes = endHour * 60 + endMinute; + } + + if (endMinutes < startMinutes) endMinutes += 24 * 60; - if (current >= end) return '已完成'; - else if (current >= start) return '进行中'; + if (current >= endMinutes) return '已完成'; + else if (current >= startMinutes) return '进行中'; else return '未开始'; }, // 事件处理 handleSubmit() { + if (!this.formLabelAlign.timeRange || this.formLabelAlign.timeRange.length !== 2) { + this.$message.warning('请选择时间范围'); + return; + } + + // 将时间范围设置到请求参数中 + this.formLabelAlign.startTime = this.formLabelAlign.timeRange[0]; + this.formLabelAlign.endTime = this.formLabelAlign.timeRange[1]; + this.getData(); }, handleReset() { this.formLabelAlign = { - startTime: new Date().toISOString().substr(0, 10), + timeRange: [], // 重置为默认值 + startTime: null, + endTime: null, teamName: '', teamId: '', equipName: '', @@ -629,7 +916,14 @@ export default { processName: '', processId: '', woCode: '', + receiveTime: '', //接收时间 + partCode: '', //订单号 + batchNo: '', //批次号 }; + this.legendStatus.completed = false; + this.legendStatus.processing = true; + this.legendStatus.pending = true; + this.updateTime(); this.getData(); }, @@ -643,21 +937,6 @@ export default { const [hours, minutes] = timeStr.split(':').map(Number); return hours * 60 + minutes; }, - - // 甘特图位置计算 - getPositionPercent(startTime) { - const totalMinutes = 24 * 60; - const startMinutes = this.timeToMinutes(startTime); - return (startMinutes / totalMinutes) * 100; - }, - getWidthPercent(startTime, endTime) { - const startMinutes = this.timeToMinutes(startTime); - let endMinutes = this.timeToMinutes(endTime); - if (endMinutes < startMinutes) endMinutes += 24 * 60; - const duration = endMinutes - startMinutes; - return (duration / (24 * 60)) * 100; - }, - // 任务 样式计算 getStatusColor(row) { switch (row.planStatus) { @@ -738,38 +1017,18 @@ export default { // 固定行高,不随层数变化 return this.baseRowChartHeight; }, - getLayerOffset(layerIndex, totalLayers, device) { + getLayerOffset(layerIndex, height, device) { const rowHeight = this.getRowChartHeight(device); - if (totalLayers <= 1) return 2; - - // 计算总间隔和可用高度 - const totalSpacing = (totalLayers - 1) * 4; // 层间间隔 - const availableHeight = rowHeight - 40 - totalSpacing; // 减去上下边距 - const layerHeight = availableHeight / totalLayers; - - // 计算当前层的偏移量 - return 20 + layerIndex * (layerHeight + 4); // 20是顶部边距 + return Math.max(0, (rowHeight - height) / 2); }, getTastTopOffset(layerIndex, totalLayers, device) { - const rowHeight = this.getRowChartHeight(device); - if (totalLayers <= 1) return 8; - - // 计算总间隔和可用高度 - const totalSpacing = (totalLayers - 1) * 4; // 层间间隔 - const availableHeight = rowHeight - 40 - totalSpacing; // 减去上下边距 - const layerHeight = availableHeight / totalLayers; - // 计算当前层的偏移量 - return 0; // 20是顶部边距 + const taskHeight = this.getLayerTaskHeight(totalLayers, device); + // 计算任务条内部文字的垂直居中位置 + return Math.max(0, (taskHeight - 31) / 2); // 文字高度约10px }, getLayerTaskHeight(totalLayers, device) { const rowHeight = this.getRowChartHeight(device); - if (totalLayers <= 1) { - return rowHeight - 40; // 减去上下边距 - } else { - const totalSpacing = (totalLayers - 1) * 4; - const availableHeight = rowHeight - 30 - totalSpacing; - return availableHeight / totalLayers; // 平均分配高度 - } + return rowHeight - 31; }, // 任务分层 @@ -777,34 +1036,39 @@ export default { const tasks = this.getDeviceTasks(device); if (!tasks.length) return []; + // 按开始时间排序 const sortedTasks = [...tasks].sort((a, b) => { const aStart = this.timeToMinutes(a.startTime); const bStart = this.timeToMinutes(b.startTime); - if (this.timeToMinutes(a.endTime) < aStart && this.timeToMinutes(b.endTime) >= bStart) { - return -1; - } return aStart - bStart; }); const layers = []; sortedTasks.forEach(task => { - let placed = false; const taskStart = this.timeToMinutes(task.startTime); const taskEnd = this.timeToMinutes(task.endTime); - const adjustedEnd = taskEnd < taskStart ? taskEnd + 24 * 60 : taskEnd; + // 处理跨天情况 + const adjustedTaskEnd = taskEnd < taskStart ? taskEnd + 24 * 60 : taskEnd; + + // 寻找可以放置任务的层 + let placed = false; for (let i = 0; i < layers.length; i++) { - const lastTask = layers[i][layers[i].length - 1]; + const layer = layers[i]; + const lastTask = layer[layer.length - 1]; const lastEnd = this.timeToMinutes(lastTask.endTime); - const lastAdjustedEnd = + const adjustedLastEnd = lastEnd < this.timeToMinutes(lastTask.startTime) ? lastEnd + 24 * 60 : lastEnd; - if (taskStart >= lastAdjustedEnd) { - layers[i].push(task); + // 检查是否有时间重叠 + if (taskStart >= adjustedLastEnd) { + // 没有时间重叠,可以放在这一层 + layer.push(task); placed = true; break; } } + // 如果没有找到合适的层,创建新层 if (!placed) { layers.push([task]); } @@ -812,6 +1076,103 @@ export default { return layers; }, + // 格式化小时标签,只显示小时部分 + formatHourLabel(timeStr) { + return timeStr.split(' ')[1]; // 只返回时间部分 + }, + + // 格式化分钟标签 + formatMinuteLabel(timeStr) { + return timeStr.split(' ')[1]; // 只返回时间部分 + }, + + // 更新时间轴数据 + updateTimeAxis() { + // 更新当前视图时间范围 + this.currentViewStartTime = new Date(this.baseDate); + this.currentViewEndTime = new Date(this.endDate); + }, + + // 计算任务位置百分比(基于3天时间轴) + getPositionPercent(startTime) { + const startHour = this.parseTimeToHours(startTime); + const totalDuration = this.totalHours; // 使用实际总小时数 + + // 确保百分比在有效范围内 + const percent = (startHour / totalDuration) * 100; + return Math.max(0, Math.min(100, percent)); + }, + + // 计算任务宽度百分比 + getWidthPercent(startTime, endTime) { + const startHour = this.parseTimeToHours(startTime); + const endHour = this.parseTimeToHours(endTime); + + const totalDuration = this.totalHours; // 使用实际总小时数 + + let duration = endHour - startHour; + if (duration < 0) { + // 处理跨天情况 - 这里需要根据实际业务逻辑调整 + duration = this.totalHours - startHour + endHour; + } + + // 确保宽度在有效范围内 + const width = (duration / totalDuration) * 100; + return Math.max(0, Math.min(100, width)); + }, + + // // 将时间字符串转换为小时数(从基准日期开始计算) + parseTimeToHours(timeStr) { + if (!timeStr) { + console.error('timeStr is undefined or null'); + return 0; + } + + // timeStr 格式是 "YYYY-MM-DD HH:mm" 如 "2025-12-25 18:35" + const [datePart, timePart] = timeStr.split(' '); + const [year, month, day] = datePart.split('-').map(Number); + const [hours, minutes] = timePart.split(':').map(Number); + + // 创建完整日期时间对象 + const fullDate = new Date(year, month - 1, day, hours, minutes); + + // 计算与基准开始时间的差值(小时) + const diffMs = fullDate - this.baseDate; + const diffHours = diffMs / (1000 * 60 * 60); + + // 确保结果在合理范围内 + return Math.max(0, Math.min(this.totalHours, diffHours)); + }, + + // 更新当前时间位置 + calcCurrentTimePosition() { + const now = new Date(); + const viewStart = this.baseDate; + const viewEnd = this.endDate; + + // 如果当前时间不在显示范围内,不显示当前时间线 + if (now < viewStart || now > viewEnd) { + this.currentTimePosition = -1; // 特殊值表示不显示 + return; + } + + // 计算当前时间相对于视图开始时间的毫秒差 + const diffMs = now - viewStart; + + // 计算整个视图范围的总毫秒数 + const totalDurationMs = viewEnd - viewStart; + + // 计算百分比位置 + const positionPercent = (diffMs / totalDurationMs) * 100; + + // 确保百分比在有效范围内 [0, 100] + this.currentTimePosition = Math.max(0, Math.min(100, positionPercent)); + + // 自动滚动到当前时间位置 + this.$nextTick(() => { + this.scrollToCurrentTime(); + }); + }, }, }; @@ -842,6 +1203,31 @@ export default { gap: 5px; font-size: 14px; } +.legend-text { + margin-left: 5px; +} +:deep(.el-checkbox__input.is-checked .el-checkbox__inner:after) { + border-color: #fff; + left: 5px; + top: 2px; +} +:deep(.el-checkbox__input.is-checked .el-checkbox__inner) { + background-color: var(--checkbox-color); +} + +:deep(.el-checkbox__inner) { + border-color: var(--checkbox-color); + background-color: var(--checkbox-color); + width: 16px; + height: 16px; +} +:deep(.el-checkbox__inner:hover) { + border-color: var(--checkbox-color); +} +:deep(.el-checkbox__label) { + color: #606266; + font-size: 14px; +} .legend-color { display: inline-block; @@ -862,8 +1248,6 @@ export default { .gantt-wrapper { display: flex; - height: calc(100% - 180px); - /* border: 1px solid #eee; */ overflow: hidden; } @@ -871,12 +1255,10 @@ export default { .info-list { width: 450px; background-color: #f8f9fa; - /* border-right: 1px solid #eee; */ flex-shrink: 0; } .info-container { - /* margin-bottom:-16px; - padding-bottom:16px */ + } .info-item-title { @@ -884,7 +1266,8 @@ export default { background: #284c89; color: #fff; font-weight: bold; - height: 30px; + height: 50px; + line-height: 50px; } .info-item-txt { line-height: 25px; @@ -892,15 +1275,19 @@ export default { text-overflow: ellipsis; white-space: nowrap; font-size: 12px; - text-align: center; + text-align: left; + padding-left: 15px; +} +.info-item-txt i { + font-style: normal; } .info-title-cell { flex: 1; text-align: center; - line-height: 30px; + line-height: 50px; border-right: 1px solid #eee; - font-size: 12px; + font-size: 14px; } .info-title-num { width: 50px; @@ -914,13 +1301,12 @@ export default { .info-item { display: flex; height: 100%; - padding: 5px; + /* padding: 5px; */ } .info-cell { flex: 1; text-align: center; - /* padding: 5px; */ box-sizing: border-box; border-right: 1px solid #eee; overflow: hidden; @@ -934,13 +1320,12 @@ export default { display: flex; flex-direction: column; overflow-y: hidden; - /* 添加固定高度,确保滚动条不会挤压内容 */ - /* height: calc(100vh - 240px); */ + overflow-x: auto; /* 确保支持横向滚动 */ } /* 图表X轴区域样式 */ .chart-axis { - height: 30px; + height: 50px; position: relative; } @@ -949,7 +1334,7 @@ export default { top: 0; left: 0; width: 100%; - height: 30px; + height: 50px; display: flex; background-color: #284c89; } @@ -962,7 +1347,7 @@ export default { color: #fff; font-weight: 500; white-space: nowrap; - line-height: 30px; + line-height: 50px; } .minor-labels { @@ -980,7 +1365,7 @@ export default { font-size: 12px; color: #fff; white-space: nowrap; - line-height: 30px; + line-height: 50px; padding: 0 2px; } @@ -1123,15 +1508,21 @@ export default { .task-bar { position: absolute; - border-radius: 18px; + border-radius: 5px; display: flex; align-items: center; - padding: 0 10px; + padding: 2px 8px; box-sizing: border-box; cursor: pointer; overflow: hidden; transition: all 0.2s; white-space: nowrap; + border: 1px solid rgba(255, 255, 255, 0.3); + min-width: 20px; + z-index: 1; +} +.task-bar.task-bar-narrow { + overflow: visible; /* 允许覆盖元素超出边界 */ } .task-bar:hover { @@ -1143,16 +1534,38 @@ export default { position: relative; width: 100%; height: 100%; + text-align: center; } .task-label-txt { position: absolute; - /* top: 8px; */ - left: -5px; - font-size: 10px; + /* left: 2px; */ + font-size: 9px; color: white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + max-width: 95%; + text-align: center; +} +.task-label-txt-inside { + top: 50%; + transform: translateY(-50%); +} +.task-overlay-text { + position: absolute; + top: -20px; + left: 0; + color: rgba(0, 0, 0); + padding: 2px 4px 2px 0; + border-radius: 3px; + font-size: 10px; + white-space: nowrap; + z-index: 10; + transform: none; + min-width: max-content; + pointer-events: none; /* 避免影响鼠标事件 */ + display: inline-block; + transform: scale(0.8); } /* 提示框样式 */ @@ -1225,4 +1638,73 @@ export default { background-color: #284c89 !important; color: #fff; } +:deep(.el-col) { + margin-bottom: 0px; +} + +/* 日期标签行 */ +.date-labels { + position: absolute; + top: 0; + left: 0; + height: 20px; + display: flex; +} + +.date-label { + position: absolute; + top: 0; + height: 20px; + background-color: #1a3a6c; + color: #fff; + font-size: 12px; + display: flex; + align-items: center; + justify-content: center; + border-right: 1px solid #fff; + box-sizing: border-box; +} + +.time-labels { + position: absolute; + top: 20px; /* 为日期行留出空间 */ + left: 0; + width: 100%; + height: 30px; + display: flex; + background-color: #284c89; +} + +.major-label { + position: absolute; + top: 0; + left: 0; + font-size: 12px; + color: #fff; + white-space: nowrap; + line-height: 30px; + transform: translateX(-50%); +} + +.current-time-line { + position: absolute; + top: 0; + bottom: 0; + width: 2px; + transform: translateX(-50%); + z-index: 10; + height: 100%; +} + +.current-time-indicator { + position: absolute; + top: -20px; + left: -15px; + background-color: #ff4d4f; + color: white; + padding: 2px 5px; + border-radius: 3px; + font-size: 10px; + white-space: nowrap; +} diff --git a/src/views/productionSchedulingPlan/schedulingDashboard/index111.vue b/src/views/productionSchedulingPlan/schedulingDashboard/index111.vue deleted file mode 100644 index e9e9a88..0000000 --- a/src/views/productionSchedulingPlan/schedulingDashboard/index111.vue +++ /dev/null @@ -1,1059 +0,0 @@ - - - - -