|
|
|
|
@ -3,6 +3,17 @@
|
|
|
|
|
<div ref="ganttContainerRef" class="schedule-gantt-container" :style="{ height }"></div>
|
|
|
|
|
<div class="schedule-detail-panel">
|
|
|
|
|
<div class="schedule-detail-title">计划信息</div>
|
|
|
|
|
<div v-if="!editable" class="schedule-status-legend">
|
|
|
|
|
<div
|
|
|
|
|
v-for="item in sortedPlanStatusList"
|
|
|
|
|
:key="item.key"
|
|
|
|
|
class="legend-item"
|
|
|
|
|
:style="{ borderLeftColor: item.color }"
|
|
|
|
|
>
|
|
|
|
|
<span class="legend-color" :style="{ backgroundColor: item.color }"></span>
|
|
|
|
|
<span class="legend-label">{{ item.label }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<template v-if="activePreviewDevice">
|
|
|
|
|
<el-descriptions :column="1" border size="small">
|
|
|
|
|
<el-descriptions-item label="设备名称">{{ activePreviewDevice.deviceName }}</el-descriptions-item>
|
|
|
|
|
@ -21,6 +32,13 @@
|
|
|
|
|
>
|
|
|
|
|
<div class="schedule-plan-item-head">
|
|
|
|
|
<span class="schedule-plan-item-title">{{ plan.productCode ?? '-' }} / {{ plan.productName ?? '-' }}</span>
|
|
|
|
|
<span
|
|
|
|
|
v-if="plan.planStatus && PLAN_STATUS_COLOR_MAP[plan.planStatus]"
|
|
|
|
|
class="plan-status-tag"
|
|
|
|
|
:style="{ backgroundColor: PLAN_STATUS_COLOR_MAP[plan.planStatus].color }"
|
|
|
|
|
>
|
|
|
|
|
{{ PLAN_STATUS_COLOR_MAP[plan.planStatus].label }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div>计划编码:{{ plan.taskCode ?? '-' }}</div>
|
|
|
|
|
<div>计划数量:{{ plan.planNumber ?? '-' }}</div>
|
|
|
|
|
@ -87,6 +105,19 @@ import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
|
|
|
|
|
|
|
|
|
|
defineOptions({ name: 'ScheduleGanttPanel' })
|
|
|
|
|
|
|
|
|
|
// 计划状态颜色映射表
|
|
|
|
|
const PLAN_STATUS_COLOR_MAP = {
|
|
|
|
|
1: { label: '已排产', color: '#409eff', textColor: '#ffffff', sort: 1 },
|
|
|
|
|
8: { label: '已开工', color: '#67c23a', textColor: '#ffffff', sort: 2 },
|
|
|
|
|
3: { label: '暂停', color: '#e6a23c', textColor: '#ffffff', sort: 3 },
|
|
|
|
|
4: { label: '待入库', color: '#f56c6c', textColor: '#ffffff', sort: 4 },
|
|
|
|
|
5: { label: '已入库', color: '#8e7cc3', textColor: '#ffffff', sort: 5 },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sortedPlanStatusList = Object.entries(PLAN_STATUS_COLOR_MAP)
|
|
|
|
|
.map(([key, val]) => ({ key: Number(key), ...val }))
|
|
|
|
|
.sort((a, b) => a.sort - b.sort)
|
|
|
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
|
defineProps<{
|
|
|
|
|
scheduleList: any[]
|
|
|
|
|
@ -726,7 +757,30 @@ const initGanttPreview = () => {
|
|
|
|
|
gantt.templates.tooltip_text = (start, end, task: any) => buildTaskTooltipHtml(task, start, end)
|
|
|
|
|
gantt.templates.task_class = (_start, _end, task: any) => {
|
|
|
|
|
if (!task?._planData) return ''
|
|
|
|
|
return String(task?._planData?.sourceType ?? '').toUpperCase() === 'HISTORY' ? 'schedule-plan-task-history' : 'schedule-plan-task'
|
|
|
|
|
|
|
|
|
|
// 当 editable 为 false 时,根据 planStatus 显示对应的颜色
|
|
|
|
|
if (!props.editable) {
|
|
|
|
|
const planStatus = task._planData?.planStatus
|
|
|
|
|
const statusMap: Record<number | string, string> = {
|
|
|
|
|
'1': 'schedule-plan-task-status-1',
|
|
|
|
|
1: 'schedule-plan-task-status-1',
|
|
|
|
|
'8': 'schedule-plan-task-status-8',
|
|
|
|
|
8: 'schedule-plan-task-status-8',
|
|
|
|
|
'3': 'schedule-plan-task-status-3',
|
|
|
|
|
3: 'schedule-plan-task-status-3',
|
|
|
|
|
'4': 'schedule-plan-task-status-4',
|
|
|
|
|
4: 'schedule-plan-task-status-4',
|
|
|
|
|
'5': 'schedule-plan-task-status-5',
|
|
|
|
|
5: 'schedule-plan-task-status-5',
|
|
|
|
|
'2': 'schedule-plan-task-status-2',
|
|
|
|
|
2: 'schedule-plan-task-status-2'
|
|
|
|
|
}
|
|
|
|
|
return statusMap[planStatus] || 'schedule-plan-task-default'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当 editable 为 true 时,使用原来的逻辑
|
|
|
|
|
const sourceType = String(task?._planData?.sourceType ?? '').toUpperCase()
|
|
|
|
|
return sourceType === 'HISTORY' ? 'schedule-plan-task-history' : 'schedule-plan-task'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const globalRange = getGlobalDateRange(previewScheduleList.value)
|
|
|
|
|
@ -737,6 +791,12 @@ const initGanttPreview = () => {
|
|
|
|
|
|
|
|
|
|
const ganttData = buildPreviewGanttData(previewScheduleList.value)
|
|
|
|
|
gantt.parse(ganttData)
|
|
|
|
|
|
|
|
|
|
// 强制刷新所有任务的样式,确保颜色正确应用
|
|
|
|
|
gantt.eachTask((task: any) => {
|
|
|
|
|
gantt.refreshTask(task.id)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
initTaskTooltips()
|
|
|
|
|
|
|
|
|
|
if (ganttData.data.length) {
|
|
|
|
|
@ -946,6 +1006,39 @@ onBeforeUnmount(() => {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-status-legend {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
|
|
|
|
gap: 8px;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
background: var(--el-fill-color-light);
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
border-left: 3px solid;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-color {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
width: 12px;
|
|
|
|
|
height: 12px;
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-label {
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-plan-list-title {
|
|
|
|
|
margin-top: 14px;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
@ -979,6 +1072,17 @@ onBeforeUnmount(() => {
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.plan-status-tag {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
padding: 2px 8px;
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
}
|
|
|
|
|
.schedule-plan-item-active {
|
|
|
|
|
border: 1px solid var(--el-color-success-light-5);
|
|
|
|
|
background: var(--el-color-success-light-9);
|
|
|
|
|
@ -1016,6 +1120,76 @@ onBeforeUnmount(() => {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 已排产状态 - 蓝色 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-1) {
|
|
|
|
|
background: #409eff !important;
|
|
|
|
|
border-color: #409eff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-1 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 已开工状态 - 绿色 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-8) {
|
|
|
|
|
background: #67c23a !important;
|
|
|
|
|
border-color: #67c23a !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-8 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 暂停状态 - 橙色 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-3) {
|
|
|
|
|
background: #e6a23c !important;
|
|
|
|
|
border-color: #e6a23c !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-3 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 待入库状态 - 红色 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-4) {
|
|
|
|
|
background: #f56c6c !important;
|
|
|
|
|
border-color: #f56c6c !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-4 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 已入库状态 - 紫色 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-5) {
|
|
|
|
|
background: #8e7cc3 !important;
|
|
|
|
|
border-color: #8e7cc3 !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-5 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 其他状态 - 深灰 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-2) {
|
|
|
|
|
background: #606266 !important;
|
|
|
|
|
border-color: #606266 !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-status-2 .gantt_task_content) {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 默认状态 */
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-default) {
|
|
|
|
|
background: #909399;
|
|
|
|
|
border-color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-default .gantt_task_content) {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-history) {
|
|
|
|
|
background: #909399;
|
|
|
|
|
border-color: #909399;
|
|
|
|
|
|