|
|
|
@ -1,23 +1,23 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<Dialog v-model="dialogVisible" title="排产" width="80%" destroy-on-close align-center>
|
|
|
|
<Dialog v-model="dialogVisible" :title="t('ProductionPlan.TaskSummary.scheduleDialogTitle')" :initialFullscreen="true" destroy-on-close>
|
|
|
|
<div class="flex items-center gap-20px mb-16px">
|
|
|
|
<div class="flex items-center gap-20px mb-16px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span>排产规则</span>
|
|
|
|
<span>{{ t('ProductionPlan.TaskSummary.scheduleRuleLabel') }}</span>
|
|
|
|
<el-select v-model="searchForm.sortRule" class="!w-220px" clearable>
|
|
|
|
<el-select v-model="searchForm.sortRule" class="!w-220px" clearable>
|
|
|
|
<el-option v-for="item in scheduleRuleOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
<el-option v-for="item in scheduleRuleOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span>产能来源</span>
|
|
|
|
<span>{{ t('ProductionPlan.TaskSummary.capacitySourceLabel') }}</span>
|
|
|
|
<el-select v-model="searchForm.capacityType" class="!w-220px">
|
|
|
|
<el-select v-model="searchForm.capacityType" class="!w-220px">
|
|
|
|
<el-option v-for="item in capacityTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
<el-option v-for="item in capacityTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
</el-select>
|
|
|
|
</el-select>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span class="text-red-500">*</span>
|
|
|
|
<span>生产时间安排</span>
|
|
|
|
<span>{{ t('ProductionPlan.TaskSummary.workTimeLabel') }}</span>
|
|
|
|
<el-time-picker
|
|
|
|
<el-time-picker
|
|
|
|
v-model="searchForm.workTimeRange"
|
|
|
|
v-model="searchForm.workTimeRange"
|
|
|
|
is-range
|
|
|
|
is-range
|
|
|
|
@ -30,52 +30,53 @@
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<span>是否跳过节假日</span>
|
|
|
|
<span>{{ t('ProductionPlan.TaskSummary.skipHolidayLabel') }}</span>
|
|
|
|
<el-switch v-model="searchForm.skipHoliday" />
|
|
|
|
<el-switch v-model="searchForm.skipHoliday" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<el-button type="primary" :loading="submitLoading" @click="handleSubmit" class="ml-auto">{{ t('ProductionPlan.TaskSummary.confirmScheduleButton') }}</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="border border-solid border-gray-200 rounded p-16px mt-16px">
|
|
|
|
<div class="border border-solid border-gray-200 rounded p-16px mt-16px">
|
|
|
|
<el-form :inline="true" :model="searchForm" label-width="90px" class="-mb-8px">
|
|
|
|
<el-form :inline="true" :model="searchForm" label-width="90px" class="-mb-8px">
|
|
|
|
<el-form-item label="任务单编码">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.scheduleFormCodeLabel')">
|
|
|
|
<el-input v-model="searchForm.code" placeholder="请输入" clearable class="!w-200px" />
|
|
|
|
<el-input v-model="searchForm.code" :placeholder="t('ProductionPlan.TaskSummary.scheduleFormCodePlaceholder')" clearable class="!w-200px" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="下达日期">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.scheduleFormOrderDateLabel')">
|
|
|
|
<el-date-picker
|
|
|
|
<el-date-picker
|
|
|
|
v-model="searchForm.orderDate"
|
|
|
|
v-model="searchForm.orderDate"
|
|
|
|
type="daterange"
|
|
|
|
type="daterange"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
:start-placeholder="t('ProductionPlan.TaskSummary.startDatePlaceholder')"
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
:end-placeholder="t('ProductionPlan.TaskSummary.endDatePlaceholder')"
|
|
|
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
|
class="!w-260px"
|
|
|
|
class="!w-260px"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="交货日期">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.scheduleFormDeliveryDateLabel')">
|
|
|
|
<el-date-picker
|
|
|
|
<el-date-picker
|
|
|
|
v-model="searchForm.deliveryDate"
|
|
|
|
v-model="searchForm.deliveryDate"
|
|
|
|
type="daterange"
|
|
|
|
type="daterange"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
start-placeholder="开始日期"
|
|
|
|
:start-placeholder="t('ProductionPlan.TaskSummary.startDatePlaceholder')"
|
|
|
|
end-placeholder="结束日期"
|
|
|
|
:end-placeholder="t('ProductionPlan.TaskSummary.endDatePlaceholder')"
|
|
|
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
|
|
|
class="!w-260px"
|
|
|
|
class="!w-260px"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="备注">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.scheduleFormRemarkLabel')">
|
|
|
|
<el-input v-model="searchForm.remark" placeholder="请输入" clearable class="!w-220px" />
|
|
|
|
<el-input v-model="searchForm.remark" :placeholder="t('ProductionPlan.TaskSummary.scheduleFormRemarkPlaceholder')" clearable class="!w-220px" />
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="库存任务">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.scheduleFormInventoryTaskLabel')">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<div class="flex items-center gap-8px">
|
|
|
|
<el-switch v-model="searchForm.inventoryTaskSchedule" />
|
|
|
|
<el-switch v-model="searchForm.inventoryTaskSchedule" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-form-item>
|
|
|
|
<el-button type="primary" @click="handleSearch">
|
|
|
|
<el-button type="primary" @click="handleSearch">
|
|
|
|
<Icon icon="ep:search" class="mr-5px" /> 查询
|
|
|
|
<Icon icon="ep:search" class="mr-5px" /> {{ t('ProductionPlan.TaskSummary.scheduleFormSearchButton') }}
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
<el-button @click="handleReset">
|
|
|
|
<el-button @click="handleReset">
|
|
|
|
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
|
|
|
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('ProductionPlan.TaskSummary.scheduleFormResetButton') }}
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
@ -110,7 +111,7 @@
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.tableScheduleCompletedColumn')" align="center">
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.tableScheduleCompletedColumn')" align="center">
|
|
|
|
<template #default="scope">
|
|
|
|
<template #default="scope">
|
|
|
|
<el-tag :type="scope.row.isScheduled ? 'success' : 'info'">{{ scope.row.isScheduled ? '是' : '否' }}</el-tag>
|
|
|
|
<el-tag :type="scope.row.isScheduled ? 'success' : 'info'">{{ scope.row.isScheduled ? t('ProductionPlan.TaskSummary.scheduleYesLabel') : t('ProductionPlan.TaskSummary.scheduleNoLabel') }}</el-tag>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableIsUrgentColumn')" align="center" prop="isUrgent" sortable>
|
|
|
|
<el-table-column :label="t('ProductionPlan.Task.tableIsUrgentColumn')" align="center" prop="isUrgent" sortable>
|
|
|
|
@ -150,7 +151,7 @@
|
|
|
|
@select="handleDetailSelect"
|
|
|
|
@select="handleDetailSelect"
|
|
|
|
@select-all="handleDetailSelectAll"
|
|
|
|
@select-all="handleDetailSelectAll"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-table-column type="selection" width="55" :reserve-selection="true" align="center" />
|
|
|
|
<el-table-column type="selection" width="55" :reserve-selection="true" align="center" :selectable="isDetailRowSelectable" />
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableTaskCodeColumn')" align="center" prop="taskCode" sortable width="200px"/>
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableTaskCodeColumn')" align="center" prop="taskCode" sortable width="200px"/>
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableProductCodeColumn')" align="center" prop="barCode" sortable />
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableProductCodeColumn')" align="center" prop="barCode" sortable />
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableProductNameColumn')" align="center" prop="productName" sortable />
|
|
|
|
<el-table-column :label="t('ProductionPlan.TaskSummary.detailTableProductNameColumn')" align="center" prop="productName" sortable />
|
|
|
|
@ -170,17 +171,13 @@
|
|
|
|
{{ t('ProductionPlan.TaskSummary.detailActionMaterialLabel') }}
|
|
|
|
{{ t('ProductionPlan.TaskSummary.detailActionMaterialLabel') }}
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
<el-button link type="primary" @click="openDeviceRelationDialog(scope.row)">
|
|
|
|
<el-button link type="primary" @click="openDeviceRelationDialog(scope.row)">
|
|
|
|
关联设备
|
|
|
|
{{ t('ProductionPlan.TaskSummary.relateDeviceButton') }}
|
|
|
|
</el-button>
|
|
|
|
</el-button>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table-column>
|
|
|
|
</el-table>
|
|
|
|
</el-table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
|
|
|
|
|
|
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</Dialog>
|
|
|
|
</Dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<TaskSchedulePreviewDialog
|
|
|
|
<TaskSchedulePreviewDialog
|
|
|
|
@ -189,26 +186,26 @@
|
|
|
|
@saved="handlePreviewSaved"
|
|
|
|
@saved="handlePreviewSaved"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<Dialog v-model="deviceRelationDialogVisible" title="关联设备" width="520px">
|
|
|
|
<Dialog v-model="deviceRelationDialogVisible" :title="t('ProductionPlan.TaskSummary.deviceRelationDialogTitle')" width="520px">
|
|
|
|
<el-form :model="deviceRelationForm" label-width="90px" v-loading="deviceRelationLoading">
|
|
|
|
<el-form :model="deviceRelationForm" label-width="90px" v-loading="deviceRelationLoading">
|
|
|
|
<el-form-item label="关联设备">
|
|
|
|
<el-form-item :label="t('ProductionPlan.TaskSummary.deviceRelationLabel')">
|
|
|
|
<el-input
|
|
|
|
<el-input
|
|
|
|
:model-value="deviceRelationDisplayText"
|
|
|
|
:model-value="deviceRelationDisplayText"
|
|
|
|
placeholder="点击选择设备"
|
|
|
|
:placeholder="t('ProductionPlan.TaskSummary.deviceRelationPlaceholder')"
|
|
|
|
readonly
|
|
|
|
readonly
|
|
|
|
@click="openDeviceSelectDialog"
|
|
|
|
@click="openDeviceSelectDialog"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
|
|
<template #footer>
|
|
|
|
<el-button type="primary" :loading="deviceRelationSaving" @click="submitDeviceRelation">保存</el-button>
|
|
|
|
<el-button type="primary" :loading="deviceRelationSaving" @click="submitDeviceRelation">{{ t('ProductionPlan.TaskSummary.deviceRelationSaveButton') }}</el-button>
|
|
|
|
<el-button @click="deviceRelationDialogVisible = false">取消</el-button>
|
|
|
|
<el-button @click="deviceRelationDialogVisible = false">{{ t('ProductionPlan.TaskSummary.deviceRelationCancelButton') }}</el-button>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
</Dialog>
|
|
|
|
</Dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<TableSelectDialog
|
|
|
|
<TableSelectDialog
|
|
|
|
ref="deviceSelectDialogRef"
|
|
|
|
ref="deviceSelectDialogRef"
|
|
|
|
title="选择设备"
|
|
|
|
:title="t('ProductionPlan.TaskSummary.selectDeviceDialogTitle')"
|
|
|
|
:columns="deviceColumns"
|
|
|
|
:columns="deviceColumns"
|
|
|
|
:fetch-api="fetchDeviceLedgerPage"
|
|
|
|
:fetch-api="fetchDeviceLedgerPage"
|
|
|
|
row-key="id"
|
|
|
|
row-key="id"
|
|
|
|
@ -256,28 +253,28 @@ const deviceRelationForm = reactive({
|
|
|
|
devices: [] as { id: number; name: string }[]
|
|
|
|
devices: [] as { id: number; name: string }[]
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const deviceColumns = [
|
|
|
|
const deviceColumns = computed(() => [
|
|
|
|
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.deviceColumnCode'), prop: 'deviceCode', minWidth: 140 },
|
|
|
|
{ label: '设备名称', prop: 'deviceName', minWidth: 160 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.deviceColumnName'), prop: 'deviceName', minWidth: 160 },
|
|
|
|
{ label: '设备型号', prop: 'deviceModel', minWidth: 140 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.deviceColumnModel'), prop: 'deviceModel', minWidth: 140 },
|
|
|
|
{ label: '所属车间', prop: 'workshop', minWidth: 140 }
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.deviceColumnWorkshop'), prop: 'workshop', minWidth: 140 }
|
|
|
|
]
|
|
|
|
])
|
|
|
|
const deviceRelationDisplayText = computed(() => {
|
|
|
|
const deviceRelationDisplayText = computed(() => {
|
|
|
|
if (!deviceRelationForm.devices.length) return ''
|
|
|
|
if (!deviceRelationForm.devices.length) return ''
|
|
|
|
if (!selectedDeviceRows.value.length) return deviceRelationForm.devices.map((item) => item.name).join('、')
|
|
|
|
if (!selectedDeviceRows.value.length) return deviceRelationForm.devices.map((item) => item.name).join('、')
|
|
|
|
return selectedDeviceRows.value.map((item) => item.deviceName || item.name || item.code || `ID:${item.id}`).join('、')
|
|
|
|
return selectedDeviceRows.value.map((item) => item.deviceName || item.name || item.code || `ID:${item.id}`).join('、')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const scheduleRuleOptions = [
|
|
|
|
const scheduleRuleOptions = computed(() => [
|
|
|
|
{ label: '订单优先级', value: 2 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.scheduleRulePriority'), value: 2 },
|
|
|
|
{ label: '产品类别顺序', value: 3 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.scheduleRuleCategory'), value: 3 },
|
|
|
|
{ label: '订单交期优先', value: 4 }
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.scheduleRuleDelivery'), value: 4 }
|
|
|
|
]
|
|
|
|
])
|
|
|
|
const capacityTypeOptions = [
|
|
|
|
const capacityTypeOptions = computed(() => [
|
|
|
|
{ label: '额定产能', value: 1 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.capacityTypeRated'), value: 1 },
|
|
|
|
{ label: '每日报工平均值', value: 2 },
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.capacityTypeDailyAvg'), value: 2 },
|
|
|
|
{ label: '数据采集产能', value: 3 }
|
|
|
|
{ label: t('ProductionPlan.TaskSummary.capacityTypeDataCollection'), value: 3 }
|
|
|
|
]
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
const searchForm = reactive({
|
|
|
|
const searchForm = reactive({
|
|
|
|
inventoryTaskSchedule: false,
|
|
|
|
inventoryTaskSchedule: false,
|
|
|
|
@ -387,7 +384,7 @@ const loadTaskList = async () => {
|
|
|
|
orderDate: searchForm.orderDate,
|
|
|
|
orderDate: searchForm.orderDate,
|
|
|
|
deliveryDate: searchForm.deliveryDate,
|
|
|
|
deliveryDate: searchForm.deliveryDate,
|
|
|
|
remark: searchForm.remark || undefined,
|
|
|
|
remark: searchForm.remark || undefined,
|
|
|
|
taskType: searchForm.inventoryTaskSchedule ? '库存任务' : undefined
|
|
|
|
taskType: searchForm.inventoryTaskSchedule ? t('ProductionPlan.TaskSummary.inventoryTaskType') : undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const data = await TaskApi.getPlanTaskPage(params)
|
|
|
|
const data = await TaskApi.getPlanTaskPage(params)
|
|
|
|
taskList.value = data?.list ?? []
|
|
|
|
taskList.value = data?.list ?? []
|
|
|
|
@ -452,7 +449,10 @@ const handleCurrentTaskChange = async (row: any) => {
|
|
|
|
const parentIsSelected = taskTableRef.value?.getSelectionRows()?.some((t: any) => t.id === row.id)
|
|
|
|
const parentIsSelected = taskTableRef.value?.getSelectionRows()?.some((t: any) => t.id === row.id)
|
|
|
|
if (parentIsSelected) {
|
|
|
|
if (parentIsSelected) {
|
|
|
|
detailList.value.forEach(child => {
|
|
|
|
detailList.value.forEach(child => {
|
|
|
|
detailTableRef.value?.toggleRowSelection(child, true)
|
|
|
|
const unplanNumber = child.number - child.planNumber
|
|
|
|
|
|
|
|
if (unplanNumber > 0) {
|
|
|
|
|
|
|
|
detailTableRef.value?.toggleRowSelection(child, true)
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
@ -472,12 +472,15 @@ const handleTaskSelect = async (selection: any[], row: any) => {
|
|
|
|
await handleCurrentTaskChange(row)
|
|
|
|
await handleCurrentTaskChange(row)
|
|
|
|
const childList = allDetailsMap.value[row.id] || []
|
|
|
|
const childList = allDetailsMap.value[row.id] || []
|
|
|
|
if (childList.length === 0) {
|
|
|
|
if (childList.length === 0) {
|
|
|
|
message.warning(`任务单 ${row.code} 无任务明细数据,无法勾选`)
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.taskNoDetailWarning', { code: row.code }))
|
|
|
|
taskTableRef.value?.toggleRowSelection(row, false)
|
|
|
|
taskTableRef.value?.toggleRowSelection(row, false)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
detailList.value.forEach((child) => {
|
|
|
|
detailList.value.forEach((child) => {
|
|
|
|
detailTableRef.value?.toggleRowSelection(child, true)
|
|
|
|
const unplanNumber = child.number - child.planNumber
|
|
|
|
|
|
|
|
if (unplanNumber > 0) {
|
|
|
|
|
|
|
|
detailTableRef.value?.toggleRowSelection(child, true)
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -510,15 +513,18 @@ const handleTaskSelectAll = async (selection: any[]) => {
|
|
|
|
taskTableRef.value?.toggleRowSelection(row, false)
|
|
|
|
taskTableRef.value?.toggleRowSelection(row, false)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
childList.forEach((child) => {
|
|
|
|
childList.forEach((child) => {
|
|
|
|
const rowInView = detailList.value.find(d => d.id === child.id)
|
|
|
|
const unplanNumber = child.number - child.planNumber
|
|
|
|
if (rowInView) {
|
|
|
|
if (unplanNumber > 0) {
|
|
|
|
detailTableRef.value?.toggleRowSelection(rowInView, true)
|
|
|
|
const rowInView = detailList.value.find(d => d.id === child.id)
|
|
|
|
|
|
|
|
if (rowInView) {
|
|
|
|
|
|
|
|
detailTableRef.value?.toggleRowSelection(rowInView, true)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasEmptyChild) {
|
|
|
|
if (hasEmptyChild) {
|
|
|
|
message.warning('部分任务单无明细数据,已自动取消勾选')
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.partialTaskNoDetailWarning'))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
detailTableRef.value?.clearSelection()
|
|
|
|
detailTableRef.value?.clearSelection()
|
|
|
|
@ -531,10 +537,13 @@ const handleTaskSelectAll = async (selection: any[]) => {
|
|
|
|
const handleDetailSelect = (selection: any[], row: any) => {
|
|
|
|
const handleDetailSelect = (selection: any[], row: any) => {
|
|
|
|
const taskId = row.taskId
|
|
|
|
const taskId = row.taskId
|
|
|
|
const childList = allDetailsMap.value[taskId] || []
|
|
|
|
const childList = allDetailsMap.value[taskId] || []
|
|
|
|
|
|
|
|
const selectableChildren = childList.filter(child => {
|
|
|
|
|
|
|
|
const unplanNumber = child.number - child.planNumber
|
|
|
|
|
|
|
|
return unplanNumber > 0
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// check if all children for this task are selected
|
|
|
|
const allChildrenSelected = selectableChildren.length > 0 && selectableChildren.every(child => selection.some(sel => sel.id === child.id))
|
|
|
|
const allChildrenSelected = childList.every(child => selection.some(sel => sel.id === child.id))
|
|
|
|
const noChildrenSelected = selectableChildren.every(child => !selection.some(sel => sel.id === child.id))
|
|
|
|
const noChildrenSelected = childList.every(child => !selection.some(sel => sel.id === child.id))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const parentTask = taskList.value.find(task => task.id === taskId)
|
|
|
|
const parentTask = taskList.value.find(task => task.id === taskId)
|
|
|
|
if (parentTask) {
|
|
|
|
if (parentTask) {
|
|
|
|
@ -551,14 +560,16 @@ const handleDetailSelectAll = (selection: any[]) => {
|
|
|
|
|
|
|
|
|
|
|
|
const taskId = currentTask.value.id
|
|
|
|
const taskId = currentTask.value.id
|
|
|
|
const childList = allDetailsMap.value[taskId] || []
|
|
|
|
const childList = allDetailsMap.value[taskId] || []
|
|
|
|
|
|
|
|
const selectableChildren = childList.filter(child => {
|
|
|
|
|
|
|
|
const unplanNumber = child.number - child.planNumber
|
|
|
|
|
|
|
|
return unplanNumber > 0
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const parentTask = taskList.value.find(task => task.id === taskId)
|
|
|
|
const parentTask = taskList.value.find(task => task.id === taskId)
|
|
|
|
if (parentTask) {
|
|
|
|
if (parentTask) {
|
|
|
|
// if any child in current view is selected, consider it an intent to select parent (if not all were selected)
|
|
|
|
|
|
|
|
// selection will contain all selected items across pages, so we need to filter for current view's task
|
|
|
|
|
|
|
|
const currentViewSelection = selection.filter(sel => sel.taskId === taskId)
|
|
|
|
const currentViewSelection = selection.filter(sel => sel.taskId === taskId)
|
|
|
|
|
|
|
|
|
|
|
|
if (currentViewSelection.length === childList.length && childList.length > 0) {
|
|
|
|
if (selectableChildren.length > 0 && currentViewSelection.length === selectableChildren.length) {
|
|
|
|
taskTableRef.value?.toggleRowSelection(parentTask, true)
|
|
|
|
taskTableRef.value?.toggleRowSelection(parentTask, true)
|
|
|
|
} else if (currentViewSelection.length === 0) {
|
|
|
|
} else if (currentViewSelection.length === 0) {
|
|
|
|
taskTableRef.value?.toggleRowSelection(parentTask, false)
|
|
|
|
taskTableRef.value?.toggleRowSelection(parentTask, false)
|
|
|
|
@ -568,6 +579,11 @@ const handleDetailSelectAll = (selection: any[]) => {
|
|
|
|
|
|
|
|
|
|
|
|
const isTaskRowSelectable = () => !taskTableBusy.value && !detailLoading.value
|
|
|
|
const isTaskRowSelectable = () => !taskTableBusy.value && !detailLoading.value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isDetailRowSelectable = (row: any) => {
|
|
|
|
|
|
|
|
const unplanNumber = row.number - row.planNumber
|
|
|
|
|
|
|
|
return unplanNumber > 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const handleSearch = async () => {
|
|
|
|
const handleSearch = async () => {
|
|
|
|
queryParams.pageNo = 1
|
|
|
|
queryParams.pageNo = 1
|
|
|
|
await loadTaskList()
|
|
|
|
await loadTaskList()
|
|
|
|
@ -589,7 +605,7 @@ const handleReset = async () => {
|
|
|
|
|
|
|
|
|
|
|
|
const openTaskItemNeed = (row: any) => {
|
|
|
|
const openTaskItemNeed = (row: any) => {
|
|
|
|
if (!row?.id) return
|
|
|
|
if (!row?.id) return
|
|
|
|
itemNeedRef.value.open('task', '任务单-' + (row?.code ?? ''), row.id)
|
|
|
|
itemNeedRef.value.open('task', t('ProductionPlan.TaskSummary.taskItemNeedPrefix') + (row?.code ?? ''), row.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const openProductItemNeed = (row: any) => {
|
|
|
|
const openProductItemNeed = (row: any) => {
|
|
|
|
@ -599,7 +615,7 @@ const openProductItemNeed = (row: any) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const openDeviceRelationDialog = async (row: any) => {
|
|
|
|
const openDeviceRelationDialog = async (row: any) => {
|
|
|
|
if (!row?.productId) {
|
|
|
|
if (!row?.productId) {
|
|
|
|
message.warning('当前明细没有关联产品,无法设置设备')
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.detailNoProductWarning'))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
currentDeviceRelationRow.value = row
|
|
|
|
currentDeviceRelationRow.value = row
|
|
|
|
@ -613,7 +629,7 @@ const openDeviceRelationDialog = async (row: any) => {
|
|
|
|
(productData as any).devices ?? (productData as any).deviceIds,
|
|
|
|
(productData as any).devices ?? (productData as any).deviceIds,
|
|
|
|
(productData as any).deviceList,
|
|
|
|
(productData as any).deviceList,
|
|
|
|
['name', 'deviceName', 'code'],
|
|
|
|
['name', 'deviceName', 'code'],
|
|
|
|
'设备'
|
|
|
|
t('ProductionPlan.TaskSummary.deviceColumnName')
|
|
|
|
)
|
|
|
|
)
|
|
|
|
deviceRelationForm.productId = Number(row.productId)
|
|
|
|
deviceRelationForm.productId = Number(row.productId)
|
|
|
|
deviceRelationForm.devices = devices
|
|
|
|
deviceRelationForm.devices = devices
|
|
|
|
@ -635,7 +651,7 @@ const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: an
|
|
|
|
if (!Number.isFinite(id)) return undefined
|
|
|
|
if (!Number.isFinite(id)) return undefined
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
id,
|
|
|
|
id,
|
|
|
|
name: item.deviceName || item.name || item.code || `设备ID:${id}`
|
|
|
|
name: item.deviceName || item.name || item.code || `${t('ProductionPlan.TaskSummary.deviceColumnName')}ID:${id}`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.filter((item): item is { id: number; name: string } => Boolean(item))
|
|
|
|
.filter((item): item is { id: number; name: string } => Boolean(item))
|
|
|
|
@ -658,7 +674,7 @@ const submitDeviceRelation = async () => {
|
|
|
|
currentData.molds ?? currentData.moldIds,
|
|
|
|
currentData.molds ?? currentData.moldIds,
|
|
|
|
currentData.moldList,
|
|
|
|
currentData.moldList,
|
|
|
|
['name', 'code'],
|
|
|
|
['name', 'code'],
|
|
|
|
'模具'
|
|
|
|
t('ProductionPlan.TaskSummary.deviceColumnName')
|
|
|
|
)
|
|
|
|
)
|
|
|
|
const payload: any = {
|
|
|
|
const payload: any = {
|
|
|
|
...currentData,
|
|
|
|
...currentData,
|
|
|
|
@ -669,7 +685,7 @@ const submitDeviceRelation = async () => {
|
|
|
|
delete payload.molds
|
|
|
|
delete payload.molds
|
|
|
|
await ProductApi.updateProduct(payload)
|
|
|
|
await ProductApi.updateProduct(payload)
|
|
|
|
await refreshDetailListAfterDeviceSaved()
|
|
|
|
await refreshDetailListAfterDeviceSaved()
|
|
|
|
message.success('关联设备已保存')
|
|
|
|
message.success(t('ProductionPlan.TaskSummary.deviceRelationSaved'))
|
|
|
|
deviceRelationDialogVisible.value = false
|
|
|
|
deviceRelationDialogVisible.value = false
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
deviceRelationSaving.value = false
|
|
|
|
deviceRelationSaving.value = false
|
|
|
|
@ -686,28 +702,32 @@ const hasValue = (value: unknown) => value !== null && value !== undefined && va
|
|
|
|
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
if (searchForm.sortRule === undefined) {
|
|
|
|
if (searchForm.sortRule === undefined) {
|
|
|
|
message.warning('请选择排产规则')
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.selectScheduleRuleWarning'))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (searchForm.capacityType === undefined) {
|
|
|
|
if (searchForm.capacityType === undefined) {
|
|
|
|
message.warning('请选择产能来源')
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.selectCapacitySourceWarning'))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const [workStartTime, workEndTime] = Array.isArray(searchForm.workTimeRange) ? searchForm.workTimeRange : []
|
|
|
|
const [workStartTime, workEndTime] = Array.isArray(searchForm.workTimeRange) ? searchForm.workTimeRange : []
|
|
|
|
if (!workStartTime || !workEndTime) {
|
|
|
|
if (!workStartTime || !workEndTime) {
|
|
|
|
message.warning('请选择生产时间安排')
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.selectWorkTimeWarning'))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const selectedRows = detailTableRef.value?.getSelectionRows() || []
|
|
|
|
const selectedRows = detailTableRef.value?.getSelectionRows() || []
|
|
|
|
if (selectedRows.length === 0) {
|
|
|
|
const filteredRows = selectedRows.filter((row: any) => {
|
|
|
|
message.warning('至少选一个任务单汇总明细的数据')
|
|
|
|
const unplanNumber = row.number - row.planNumber
|
|
|
|
|
|
|
|
return unplanNumber > 0
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
if (filteredRows.length === 0) {
|
|
|
|
|
|
|
|
message.warning(t('ProductionPlan.TaskSummary.selectDetailWarning'))
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
submitLoading.value = true
|
|
|
|
submitLoading.value = true
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
console.log(selectedRows)
|
|
|
|
console.log(filteredRows)
|
|
|
|
const createReqVO = selectedRows.map((row: any) => {
|
|
|
|
const createReqVO = filteredRows.map((row: any) => {
|
|
|
|
const planNumber = row.number - row.planNumber > 0 ? row.number - row.planNumber : 0
|
|
|
|
const planNumber = row.number - row.planNumber > 0 ? row.number - row.planNumber : 0
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
// PlanForm fields
|
|
|
|
// PlanForm fields
|
|
|
|
@ -745,7 +765,7 @@ const handleSubmit = async () => {
|
|
|
|
? (scheduleResult as any).data
|
|
|
|
? (scheduleResult as any).data
|
|
|
|
: []
|
|
|
|
: []
|
|
|
|
previewScheduleList.value = scheduleData
|
|
|
|
previewScheduleList.value = scheduleData
|
|
|
|
message.success('排产已提交')
|
|
|
|
message.success(t('ProductionPlan.TaskSummary.scheduleSubmitted'))
|
|
|
|
previewVisible.value = true
|
|
|
|
previewVisible.value = true
|
|
|
|
emit('success')
|
|
|
|
emit('success')
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
|