|
|
|
@ -167,7 +167,7 @@
|
|
|
|
<el-descriptions :column="1" border size="small" v-if="activePreviewDevice">
|
|
|
|
<el-descriptions :column="1" border size="small" v-if="activePreviewDevice">
|
|
|
|
<el-descriptions-item label="设备名称">{{ activePreviewDevice.deviceName }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="设备名称">{{ activePreviewDevice.deviceName }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="设备ID">{{ activePreviewDevice.deviceId }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="设备ID">{{ activePreviewDevice.deviceId }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="额定产能">{{ activePreviewDevice.ratedCapacity ?? '-' }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="产能">{{ activePreviewDevice.ratedCapacity ?? '-' }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="计划条数">{{ activePreviewDevice.plans?.length ?? 0 }}</el-descriptions-item>
|
|
|
|
<el-descriptions-item label="计划条数">{{ activePreviewDevice.plans?.length ?? 0 }}</el-descriptions-item>
|
|
|
|
</el-descriptions>
|
|
|
|
</el-descriptions>
|
|
|
|
<el-empty v-else description="暂无计划信息" :image-size="80" />
|
|
|
|
<el-empty v-else description="暂无计划信息" :image-size="80" />
|
|
|
|
@ -189,6 +189,7 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<template #footer>
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button type="primary" :loading="previewSaveLoading" @click="handlePreviewSave">保存</el-button>
|
|
|
|
<el-button @click="previewVisible = false">关闭</el-button>
|
|
|
|
<el-button @click="previewVisible = false">关闭</el-button>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</Dialog>
|
|
|
|
</Dialog>
|
|
|
|
@ -199,6 +200,7 @@
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { DICT_TYPE } from '@/utils/dict'
|
|
|
|
import { DICT_TYPE } from '@/utils/dict'
|
|
|
|
import { TaskApi } from '@/api/mes/task'
|
|
|
|
import { TaskApi } from '@/api/mes/task'
|
|
|
|
|
|
|
|
import { PlanApi } from '@/api/mes/plan'
|
|
|
|
import ItemNeedIndex from '@/views/mes/bom/ItemNeedIndex.vue'
|
|
|
|
import ItemNeedIndex from '@/views/mes/bom/ItemNeedIndex.vue'
|
|
|
|
import { dateFormatter2 } from '@/utils/formatTime'
|
|
|
|
import { dateFormatter2 } from '@/utils/formatTime'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
@ -215,6 +217,7 @@ const dialogVisible = ref(false)
|
|
|
|
const taskLoading = ref(false)
|
|
|
|
const taskLoading = ref(false)
|
|
|
|
const detailLoading = ref(false)
|
|
|
|
const detailLoading = ref(false)
|
|
|
|
const submitLoading = ref(false)
|
|
|
|
const submitLoading = ref(false)
|
|
|
|
|
|
|
|
const previewSaveLoading = ref(false)
|
|
|
|
const previewVisible = ref(false)
|
|
|
|
const previewVisible = ref(false)
|
|
|
|
const itemNeedRef = ref()
|
|
|
|
const itemNeedRef = ref()
|
|
|
|
const taskTableRef = ref()
|
|
|
|
const taskTableRef = ref()
|
|
|
|
@ -541,6 +544,7 @@ const buildPreviewGanttData = (scheduleList: any[]) => {
|
|
|
|
const endDate = formatGanttDate(plan.planEndTimeStr)
|
|
|
|
const endDate = formatGanttDate(plan.planEndTimeStr)
|
|
|
|
const duration = Number(plan.scheduleDays) > 0 ? Number(plan.scheduleDays) : Math.max(plan._end.diff(plan._start, 'day') + 1, 1)
|
|
|
|
const duration = Number(plan.scheduleDays) > 0 ? Number(plan.scheduleDays) : Math.max(plan._end.diff(plan._start, 'day') + 1, 1)
|
|
|
|
if (!startDate || !endDate) return
|
|
|
|
if (!startDate || !endDate) return
|
|
|
|
|
|
|
|
const isHistory = String(plan.sourceType ?? '').toUpperCase() === 'HISTORY'
|
|
|
|
const planTaskId = `plan-${device.deviceId}-${plan.taskDetailId ?? index}-${index}`
|
|
|
|
const planTaskId = `plan-${device.deviceId}-${plan.taskDetailId ?? index}-${index}`
|
|
|
|
tasks.push({
|
|
|
|
tasks.push({
|
|
|
|
id: planTaskId,
|
|
|
|
id: planTaskId,
|
|
|
|
@ -550,6 +554,7 @@ const buildPreviewGanttData = (scheduleList: any[]) => {
|
|
|
|
duration,
|
|
|
|
duration,
|
|
|
|
parent: deviceId,
|
|
|
|
parent: deviceId,
|
|
|
|
progress: 0,
|
|
|
|
progress: 0,
|
|
|
|
|
|
|
|
readonly: isHistory,
|
|
|
|
_planData: plan,
|
|
|
|
_planData: plan,
|
|
|
|
_deviceData: device
|
|
|
|
_deviceData: device
|
|
|
|
})
|
|
|
|
})
|
|
|
|
@ -582,6 +587,7 @@ const formatGridDateText = (value: unknown) => {
|
|
|
|
|
|
|
|
|
|
|
|
const syncPlanTimeFromTask = (task: any) => {
|
|
|
|
const syncPlanTimeFromTask = (task: any) => {
|
|
|
|
if (!task?._planData) return
|
|
|
|
if (!task?._planData) return
|
|
|
|
|
|
|
|
if (String(task?._planData?.sourceType ?? '').toUpperCase() !== 'CURRENT') return
|
|
|
|
const start = dayjs(task.start_date)
|
|
|
|
const start = dayjs(task.start_date)
|
|
|
|
const end = dayjs(task.end_date)
|
|
|
|
const end = dayjs(task.end_date)
|
|
|
|
if (!start.isValid() || !end.isValid()) return
|
|
|
|
if (!start.isValid() || !end.isValid()) return
|
|
|
|
@ -648,7 +654,7 @@ const initGanttPreview = () => {
|
|
|
|
align: 'center',
|
|
|
|
align: 'center',
|
|
|
|
width: 210,
|
|
|
|
width: 210,
|
|
|
|
template: (task: any) =>
|
|
|
|
template: (task: any) =>
|
|
|
|
task?._planData
|
|
|
|
task?._planData && String(task?._planData?.sourceType ?? '').toUpperCase() === 'CURRENT'
|
|
|
|
? `<span class="gantt-inline-editor-trigger" data-field="start_date">${formatGridDateText(task.start_date)}</span>`
|
|
|
|
? `<span class="gantt-inline-editor-trigger" data-field="start_date">${formatGridDateText(task.start_date)}</span>`
|
|
|
|
: formatGridDateText(task.start_date),
|
|
|
|
: formatGridDateText(task.start_date),
|
|
|
|
editor: {
|
|
|
|
editor: {
|
|
|
|
@ -662,7 +668,7 @@ const initGanttPreview = () => {
|
|
|
|
align: 'center',
|
|
|
|
align: 'center',
|
|
|
|
width: 60,
|
|
|
|
width: 60,
|
|
|
|
template: (task: any) =>
|
|
|
|
template: (task: any) =>
|
|
|
|
task?._planData
|
|
|
|
task?._planData && String(task?._planData?.sourceType ?? '').toUpperCase() === 'CURRENT'
|
|
|
|
? `<span class="gantt-inline-editor-trigger" data-field="duration">${task.duration ?? 0}</span>`
|
|
|
|
? `<span class="gantt-inline-editor-trigger" data-field="duration">${task.duration ?? 0}</span>`
|
|
|
|
: String(task.duration ?? 0),
|
|
|
|
: String(task.duration ?? 0),
|
|
|
|
editor: {
|
|
|
|
editor: {
|
|
|
|
@ -693,7 +699,10 @@ const initGanttPreview = () => {
|
|
|
|
<div>计划条数:${plans.length}</div>
|
|
|
|
<div>计划条数:${plans.length}</div>
|
|
|
|
`
|
|
|
|
`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gantt.templates.task_class = (_start, _end, task: any) => (task?._planData ? 'schedule-plan-task' : '')
|
|
|
|
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'
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const globalRange = getGlobalDateRange(previewScheduleList.value)
|
|
|
|
const globalRange = getGlobalDateRange(previewScheduleList.value)
|
|
|
|
gantt.config.start_date = dayjs(globalRange.start).startOf('day').toDate()
|
|
|
|
gantt.config.start_date = dayjs(globalRange.start).startOf('day').toDate()
|
|
|
|
@ -715,7 +724,7 @@ const initGanttPreview = () => {
|
|
|
|
const editableNode = target?.closest('.gantt-inline-editor-trigger') as HTMLElement | null
|
|
|
|
const editableNode = target?.closest('.gantt-inline-editor-trigger') as HTMLElement | null
|
|
|
|
const field = editableNode?.dataset?.field
|
|
|
|
const field = editableNode?.dataset?.field
|
|
|
|
const inlineEditors = (gantt.ext as any)?.inlineEditors
|
|
|
|
const inlineEditors = (gantt.ext as any)?.inlineEditors
|
|
|
|
if (field && task?._planData && inlineEditors?.startEdit) {
|
|
|
|
if (field && task?._planData && String(task?._planData?.sourceType ?? '').toUpperCase() === 'CURRENT' && inlineEditors?.startEdit) {
|
|
|
|
inlineEditors.startEdit(id, field)
|
|
|
|
inlineEditors.startEdit(id, field)
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -736,6 +745,54 @@ const initGanttPreview = () => {
|
|
|
|
ganttEventIds.value.push(clickEventId, dragEventId, updateEventId)
|
|
|
|
ganttEventIds.value.push(clickEventId, dragEventId, updateEventId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handlePreviewSave = async () => {
|
|
|
|
|
|
|
|
const createReqVOList = previewScheduleList.value.flatMap((device: any) => {
|
|
|
|
|
|
|
|
const plans = Array.isArray(device?.plans) ? device.plans : []
|
|
|
|
|
|
|
|
return plans
|
|
|
|
|
|
|
|
.filter((plan: any) => String(plan?.sourceType ?? '').toUpperCase() === 'CURRENT')
|
|
|
|
|
|
|
|
.map((plan: any) => {
|
|
|
|
|
|
|
|
const startValue = dayjs(plan?.planStartTimeStr)
|
|
|
|
|
|
|
|
const endValue = dayjs(plan?.planEndTimeStr)
|
|
|
|
|
|
|
|
const deliveryDateValue = dayjs(plan?.deliveryDateStr)
|
|
|
|
|
|
|
|
const latestStartValue = dayjs(plan?.latestStartTimeStr)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
productId: plan?.productId,
|
|
|
|
|
|
|
|
taskId: plan?.taskId,
|
|
|
|
|
|
|
|
taskDetailId: plan?.taskDetailId,
|
|
|
|
|
|
|
|
planNumber: Number(plan?.planNumber ?? 0),
|
|
|
|
|
|
|
|
finishNumber: Number(plan?.finishNumber ?? 0),
|
|
|
|
|
|
|
|
isCode: typeof plan?.isCode === 'boolean' ? plan.isCode : true,
|
|
|
|
|
|
|
|
isPreProduction: Number(plan?.isPreProduction ?? 0),
|
|
|
|
|
|
|
|
planStartTime: startValue.isValid() ? startValue.valueOf() : undefined,
|
|
|
|
|
|
|
|
planEndTime: endValue.isValid() ? endValue.valueOf() : undefined,
|
|
|
|
|
|
|
|
reyaNumber: Number(plan?.reyaNumber ?? plan?.planNumber ?? 0),
|
|
|
|
|
|
|
|
workerId: plan?.workerId,
|
|
|
|
|
|
|
|
feedingPipeline: plan?.feedingPipeline ?? device?.deviceId,
|
|
|
|
|
|
|
|
deviceId: device?.deviceId ?? plan?.deviceId,
|
|
|
|
|
|
|
|
deliveryDate: deliveryDateValue.isValid() ? deliveryDateValue.valueOf() : undefined,
|
|
|
|
|
|
|
|
LatestStartTime: latestStartValue.isValid() ? latestStartValue.valueOf() : undefined,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!createReqVOList.length) {
|
|
|
|
|
|
|
|
message.warning('暂无可保存的计划数据')
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
previewSaveLoading.value = true
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
await PlanApi.createBatch({ createReqVOList })
|
|
|
|
|
|
|
|
message.success('排产计划保存成功')
|
|
|
|
|
|
|
|
previewVisible.value = false
|
|
|
|
|
|
|
|
dialogVisible.value = false
|
|
|
|
|
|
|
|
await loadTaskList()
|
|
|
|
|
|
|
|
emit('success')
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
previewSaveLoading.value = false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
if (searchForm.sortRule === undefined) {
|
|
|
|
if (searchForm.sortRule === undefined) {
|
|
|
|
message.warning('请选择排产规则')
|
|
|
|
message.warning('请选择排产规则')
|
|
|
|
@ -891,4 +948,13 @@ defineExpose({ open })
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task .gantt_task_content) {
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task .gantt_task_content) {
|
|
|
|
color: #ffffff;
|
|
|
|
color: #ffffff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-history) {
|
|
|
|
|
|
|
|
background: #909399;
|
|
|
|
|
|
|
|
border-color: #909399;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.schedule-gantt-container :deep(.gantt_task_line.schedule-plan-task-history .gantt_task_content) {
|
|
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|
|