diff --git a/src/components/Dialog/src/Dialog.vue b/src/components/Dialog/src/Dialog.vue index a1eb550c..854ebfe3 100644 --- a/src/components/Dialog/src/Dialog.vue +++ b/src/components/Dialog/src/Dialog.vue @@ -9,13 +9,14 @@ const props = defineProps({ modelValue: propTypes.bool.def(false), title: propTypes.string.def('Dialog'), fullscreen: propTypes.bool.def(true), + initialFullscreen: propTypes.bool.def(false), width: propTypes.oneOfType([String, Number]).def('40%'), - scroll: propTypes.bool.def(false), // 是否开启滚动条。如果是的话,按照 maxHeight 设置最大高度 + scroll: propTypes.bool.def(false), maxHeight: propTypes.oneOfType([String, Number]).def('400px') }) const getBindValue = computed(() => { - const delArr: string[] = ['fullscreen', 'title', 'maxHeight', 'appendToBody'] + const delArr: string[] = ['fullscreen', 'initialFullscreen', 'title', 'maxHeight', 'appendToBody'] const attrs = useAttrs() const obj = { ...attrs, ...props } for (const key in obj) { @@ -26,7 +27,7 @@ const getBindValue = computed(() => { return obj }) -const isFullscreen = ref(false) +const isFullscreen = ref(props.initialFullscreen) const toggleFull = () => { isFullscreen.value = !unref(isFullscreen) diff --git a/src/locales/en.ts b/src/locales/en.ts index 4769f483..6781d569 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -2737,6 +2737,7 @@ export default { sampleMethod: 'Sampling Method', val: 'Value', item: 'Related Items', + product: 'Related Products', remark: 'Remark', createTime: 'Create Time', operate: 'Operate', @@ -2750,6 +2751,8 @@ export default { placeholderSampleMethod: 'Please select sampling method', placeholderVal: 'Please input value', placeholderItem: 'Please select inspection items', + placeholderProduct: 'Please select related products', + selectProductDialogTitle: 'Select Related Products', placeholderRemark: 'Please input remark', placeholderCreateTimeStart: 'Start Date', placeholderCreateTimeEnd: 'End Date', @@ -3313,7 +3316,8 @@ export default { detailDialogBoxingDatePlaceholder: 'Select boxing date', detailDialogArriveDateLabel: 'Arrival Date', detailDialogArriveDatePlaceholder: 'Select arrival date', - detailDialogRemarkLabel: 'Remark:', + detailDialogRemarkLabel: 'Remark', + detailDialogRemarkPlaceholder: 'Please enter remark', detailDialogSubmitButtonText: 'Confirm', detailDialogCancelButtonText: 'Cancel', @@ -3470,7 +3474,55 @@ export default { validatorPlanFormTaskIdRequired: 'Task order can not be empty', validatorPlanFormPlanNumberRequired: 'Quantity can not be empty', validatorPlanFormPlanStartTimeRequired: 'Plan start time can not be empty', - validatorPlanFormPlanEndTimeRequired: 'Plan end time can not be empty' + validatorPlanFormPlanEndTimeRequired: 'Plan end time can not be empty', + + scheduleDialogTitle: 'Schedule', + scheduleRuleLabel: 'Schedule Rule', + capacitySourceLabel: 'Capacity Source', + workTimeLabel: 'Work Time', + skipHolidayLabel: 'Skip Holidays', + confirmScheduleButton: 'Confirm Schedule', + scheduleFormCodeLabel: 'Task Order Code', + scheduleFormCodePlaceholder: 'Please input', + scheduleFormOrderDateLabel: 'Order Date', + scheduleFormDeliveryDateLabel: 'Delivery Date', + scheduleFormRemarkLabel: 'Remark', + scheduleFormRemarkPlaceholder: 'Please input', + scheduleFormInventoryTaskLabel: 'Inventory Task', + scheduleFormSearchButton: 'Search', + scheduleFormResetButton: 'Reset', + scheduleYesLabel: 'Yes', + scheduleNoLabel: 'No', + relateDeviceButton: 'Relate Device', + deviceRelationDialogTitle: 'Relate Device', + deviceRelationLabel: 'Related Device', + deviceRelationPlaceholder: 'Click to select device', + deviceRelationSaveButton: 'Save', + deviceRelationCancelButton: 'Cancel', + selectDeviceDialogTitle: 'Select Device', + deviceColumnCode: 'Device Code', + deviceColumnName: 'Device Name', + deviceColumnModel: 'Device Model', + deviceColumnWorkshop: 'Workshop', + scheduleRulePriority: 'Order Priority', + scheduleRuleCategory: 'Product Category Order', + scheduleRuleDelivery: 'Delivery Date Priority', + capacityTypeRated: 'Rated Capacity', + capacityTypeDailyAvg: 'Daily Report Average', + capacityTypeDataCollection: 'Data Collection Capacity', + inventoryTaskType: 'Inventory Task', + taskNoDetailWarning: 'Task order {code} has no detail data, cannot be selected', + partialTaskNoDetailWarning: 'Some task orders have no detail data, selection has been automatically cancelled', + taskItemNeedPrefix: 'Task Order-', + detailNoProductWarning: 'Current detail has no related product, cannot set device', + deviceRelationSaved: 'Device relation saved', + selectScheduleRuleWarning: 'Please select a schedule rule', + selectCapacitySourceWarning: 'Please select a capacity source', + selectWorkTimeWarning: 'Please select work time', + selectDetailWarning: 'Please select at least one task summary detail', + scheduleSubmitted: 'Schedule submitted', + startDatePlaceholder: 'Start Date', + endDatePlaceholder: 'End Date' }, Plan: { diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index e64a15fd..5a47a5ce 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -2245,6 +2245,7 @@ export default { sampleMethod: '抽检方式', val: '值', item: '关联项目', + product: '关联产品', remark: '备注', createTime: '创建时间', operate: '操作', @@ -2258,6 +2259,8 @@ export default { placeholderSampleMethod: '请选择抽检方式', placeholderVal: '请输入值', placeholderItem: '请选择检验项目', + placeholderProduct: '请选择关联产品', + selectProductDialogTitle: '选择关联产品', placeholderRemark: '请输入备注', placeholderCreateTimeStart: '开始日期', placeholderCreateTimeEnd: '结束日期', @@ -3159,7 +3162,8 @@ export default { detailDialogBoxingDatePlaceholder: '选择装柜日期', detailDialogArriveDateLabel: '到达日期', detailDialogArriveDatePlaceholder: '选择到达日期', - detailDialogRemarkLabel: '备注:', + detailDialogRemarkLabel: '备注', + detailDialogRemarkPlaceholder: '请输入备注', detailDialogSubmitButtonText: '确 定', detailDialogCancelButtonText: '取 消', @@ -3314,7 +3318,55 @@ export default { validatorPlanFormTaskIdRequired: '任务单不能为空', validatorPlanFormPlanNumberRequired: '数量不能为空', validatorPlanFormPlanStartTimeRequired: '计划开始时间不能为空', - validatorPlanFormPlanEndTimeRequired: '计划结束时间不能为空' + validatorPlanFormPlanEndTimeRequired: '计划结束时间不能为空', + + scheduleDialogTitle: '排产', + scheduleRuleLabel: '排产规则', + capacitySourceLabel: '产能来源', + workTimeLabel: '生产时间安排', + skipHolidayLabel: '是否跳过节假日', + confirmScheduleButton: '确认排产', + scheduleFormCodeLabel: '任务单编码', + scheduleFormCodePlaceholder: '请输入', + scheduleFormOrderDateLabel: '下达日期', + scheduleFormDeliveryDateLabel: '交货日期', + scheduleFormRemarkLabel: '备注', + scheduleFormRemarkPlaceholder: '请输入', + scheduleFormInventoryTaskLabel: '库存任务', + scheduleFormSearchButton: '查询', + scheduleFormResetButton: '重置', + scheduleYesLabel: '是', + scheduleNoLabel: '否', + relateDeviceButton: '关联设备', + deviceRelationDialogTitle: '关联设备', + deviceRelationLabel: '关联设备', + deviceRelationPlaceholder: '点击选择设备', + deviceRelationSaveButton: '保存', + deviceRelationCancelButton: '取消', + selectDeviceDialogTitle: '选择设备', + deviceColumnCode: '设备编号', + deviceColumnName: '设备名称', + deviceColumnModel: '设备型号', + deviceColumnWorkshop: '所属车间', + scheduleRulePriority: '订单优先级', + scheduleRuleCategory: '产品类别顺序', + scheduleRuleDelivery: '订单交期优先', + capacityTypeRated: '额定产能', + capacityTypeDailyAvg: '每日报工平均值', + capacityTypeDataCollection: '数据采集产能', + inventoryTaskType: '库存任务', + taskNoDetailWarning: '任务单 {code} 无任务明细数据,无法勾选', + partialTaskNoDetailWarning: '部分任务单无明细数据,已自动取消勾选', + taskItemNeedPrefix: '任务单-', + detailNoProductWarning: '当前明细没有关联产品,无法设置设备', + deviceRelationSaved: '关联设备已保存', + selectScheduleRuleWarning: '请选择排产规则', + selectCapacitySourceWarning: '请选择产能来源', + selectWorkTimeWarning: '请选择生产时间安排', + selectDetailWarning: '至少选一个任务单汇总明细的数据', + scheduleSubmitted: '排产已提交', + startDatePlaceholder: '开始日期', + endDatePlaceholder: '结束日期' }, Plan: { moduleName: '生产计划', diff --git a/src/views/erp/product/product/ProductForm.vue b/src/views/erp/product/product/ProductForm.vue index d8c4fd79..2377a44b 100644 --- a/src/views/erp/product/product/ProductForm.vue +++ b/src/views/erp/product/product/ProductForm.vue @@ -87,7 +87,7 @@ /> --> - + + + + + + + {{ dict.label }} + + + @@ -340,7 +340,7 @@ const deviceColumns = [ { label: '设备编号', prop: 'deviceCode', minWidth: 140 }, { label: '设备名称', prop: 'deviceName', minWidth: 160 }, { label: '设备型号', prop: 'deviceModel', minWidth: 140 }, - { label: '所属车间', prop: 'workshop', minWidth: 140 } + { label: '所属车间', prop: 'workshopName', minWidth: 140 } ] const moldColumns = [ { label: '模具编码', prop: 'code', minWidth: 140 }, @@ -351,7 +351,8 @@ const moldColumns = [ const fetchDeviceLedgerPage = (params: Record) => { return DeviceLedgerApi.getDeviceLedgerPage({ ...params, - isScheduled: 1 + isScheduled: 1, + deviceStatus: 0 }) } const openDeviceSelectDialog = () => { diff --git a/src/views/mes/bom/components/BomDetailForm.vue b/src/views/mes/bom/components/BomDetailForm.vue index 66de58bf..012910db 100644 --- a/src/views/mes/bom/components/BomDetailForm.vue +++ b/src/views/mes/bom/components/BomDetailForm.vue @@ -17,6 +17,7 @@ clearable filterable :placeholder="t('FactoryModeling.ProductBOM.detailMaterialPlaceholder')" + @change="(val) => handleProductChange(val, row)" > { + if (productId) { + const product = productList.value.find((item) => item.id === productId) + row.unitId = product?.unitId ?? undefined + } else { + row.unitId = undefined + } +} + /** 新增按钮操作 */ const handleAdd = () => { const row = { diff --git a/src/views/mes/bom/index.vue b/src/views/mes/bom/index.vue index de13d7ad..8e3c1677 100644 --- a/src/views/mes/bom/index.vue +++ b/src/views/mes/bom/index.vue @@ -241,6 +241,6 @@ const handleExport = async () => { onMounted(async () => { await getList() // 加载产品、 - productList.value = await ProductApi.getProductSimpleList() + productList.value = await ProductApi.getMesProductSimpleList() }) diff --git a/src/views/mes/feedingrecord/FeedingRecordForm.vue b/src/views/mes/feedingrecord/FeedingRecordForm.vue index 250607e2..3e51495f 100644 --- a/src/views/mes/feedingrecord/FeedingRecordForm.vue +++ b/src/views/mes/feedingrecord/FeedingRecordForm.vue @@ -323,7 +323,7 @@ const handleQuery = async(planId : number) => { data.value = await PlanApi.getPlan(planId) //console.log(data.value) list.value = await ItemRequisitionApi.getItemRequisitionDetailListByItemRequisitionId(data.value.requisitionId) - recordData.value = list.value + recordData.value = list.value.map((item) => ({ ...item, weight: item.weight ?? 0 })) to.value = list.total } diff --git a/src/views/mes/ganttChart/index.vue b/src/views/mes/ganttChart/index.vue index 5215c8d6..8c39ac95 100644 --- a/src/views/mes/ganttChart/index.vue +++ b/src/views/mes/ganttChart/index.vue @@ -12,6 +12,11 @@ class="!w-360px" /> + + + + + 查询 重置 @@ -21,7 +26,7 @@
- +
@@ -68,7 +73,20 @@ const buildDefaultRange = () => { const queryRange = ref(buildDefaultRange()) const queryParams = reactive({ startTime: queryRange.value[0], - endTime: queryRange.value[1] + endTime: queryRange.value[1], + deviceIds: [] as (string | number)[] +}) + +const deviceOptions = computed(() => + scheduleList.value.map((device) => ({ + label: device.deviceName, + value: device.deviceId + })) +) + +const filteredList = computed(() => { + if (!queryParams.deviceIds.length) return scheduleList.value + return scheduleList.value.filter((device) => queryParams.deviceIds.includes(device.deviceId)) }) const getList = async () => { diff --git a/src/views/mes/plan/index.vue b/src/views/mes/plan/index.vue index a3d53824..d6a679a4 100644 --- a/src/views/mes/plan/index.vue +++ b/src/views/mes/plan/index.vue @@ -59,7 +59,7 @@ - + @@ -282,7 +282,7 @@ const productList = ref([]) // 产品列表 const taskList = ref([]) // 列表 /** 生产计划 列表 */ defineOptions({ name: 'Plan' }) -const activeName = ref('1') // 列表 tab +const activeName = ref('') // 列表 tab const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 diff --git a/src/views/mes/task/components/TaskDetailForm.vue b/src/views/mes/task/components/TaskDetailForm.vue index bd65e5ea..734b17b1 100644 --- a/src/views/mes/task/components/TaskDetailForm.vue +++ b/src/views/mes/task/components/TaskDetailForm.vue @@ -64,24 +64,13 @@
- - - - - - - - @@ -94,7 +83,7 @@ /> - + + + + + + + + + + + + - - - - @@ -180,7 +177,7 @@ const formRules = reactive({ unitId: [{ required: true, message: t('ProductionPlan.Task.validatorDetailUnitIdRequired'), trigger: 'blur' }], taskId: [{ required: true, message: t('ProductionPlan.Task.validatorDetailTaskIdRequired'), trigger: 'blur' }], number: [{ required: true, message: t('ProductionPlan.Task.validatorDetailNumberRequired'), trigger: 'blur' }], - packageSize: [{ required: true, message: t('ProductionPlan.Task.validatorDetailPackageSizeRequired'), trigger: 'blur' }], + packageSize: [], finishDate: [{ validator: validateFinishDate, trigger: ['change', 'blur'] }] }) const formRef = ref() // 表单 Ref @@ -241,6 +238,22 @@ const submitForm = async () => { } } +/** 监听数量和每包数量变化,自动计算打包数量 */ +watch( + () => [formData.value.number, formData.value.packageSize], + ([number, packageSize]) => { + if (!number && number !== 0) { + formData.value.packageNumber = undefined + return + } + if (!packageSize || packageSize === 0) { + formData.value.packageNumber = number + } else { + formData.value.packageNumber = Math.ceil(number / packageSize) + } + } +) + /** 处理产品变更 */ const onChangeProduct = (productId) => { const product = productList.value.find((item) => item.id === productId) diff --git a/src/views/mes/task/components/TaskDetailList.vue b/src/views/mes/task/components/TaskDetailList.vue index c0c7dd33..51b33a68 100644 --- a/src/views/mes/task/components/TaskDetailList.vue +++ b/src/views/mes/task/components/TaskDetailList.vue @@ -54,6 +54,7 @@ 排产 --> +
+
+
+
计划信息
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/mes/tasksummary/components/TaskScheduleDialog.vue b/src/views/mes/tasksummary/components/TaskScheduleDialog.vue index 64740eff..73eb984b 100644 --- a/src/views/mes/tasksummary/components/TaskScheduleDialog.vue +++ b/src/views/mes/tasksummary/components/TaskScheduleDialog.vue @@ -1,23 +1,23 @@ - - + - + [ + { label: t('ProductionPlan.TaskSummary.deviceColumnCode'), prop: 'deviceCode', minWidth: 140 }, + { label: t('ProductionPlan.TaskSummary.deviceColumnName'), prop: 'deviceName', minWidth: 160 }, + { label: t('ProductionPlan.TaskSummary.deviceColumnModel'), prop: 'deviceModel', minWidth: 140 }, + { label: t('ProductionPlan.TaskSummary.deviceColumnWorkshop'), prop: 'workshop', minWidth: 140 } +]) const deviceRelationDisplayText = computed(() => { if (!deviceRelationForm.devices.length) return '' 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('、') }) -const scheduleRuleOptions = [ - { label: '订单优先级', value: 2 }, - { label: '产品类别顺序', value: 3 }, - { label: '订单交期优先', value: 4 } -] -const capacityTypeOptions = [ - { label: '额定产能', value: 1 }, - { label: '每日报工平均值', value: 2 }, - { label: '数据采集产能', value: 3 } -] +const scheduleRuleOptions = computed(() => [ + { label: t('ProductionPlan.TaskSummary.scheduleRulePriority'), value: 2 }, + { label: t('ProductionPlan.TaskSummary.scheduleRuleCategory'), value: 3 }, + { label: t('ProductionPlan.TaskSummary.scheduleRuleDelivery'), value: 4 } +]) +const capacityTypeOptions = computed(() => [ + { label: t('ProductionPlan.TaskSummary.capacityTypeRated'), value: 1 }, + { label: t('ProductionPlan.TaskSummary.capacityTypeDailyAvg'), value: 2 }, + { label: t('ProductionPlan.TaskSummary.capacityTypeDataCollection'), value: 3 } +]) const searchForm = reactive({ inventoryTaskSchedule: false, @@ -387,7 +384,7 @@ const loadTaskList = async () => { orderDate: searchForm.orderDate, deliveryDate: searchForm.deliveryDate, remark: searchForm.remark || undefined, - taskType: searchForm.inventoryTaskSchedule ? '库存任务' : undefined + taskType: searchForm.inventoryTaskSchedule ? t('ProductionPlan.TaskSummary.inventoryTaskType') : undefined } const data = await TaskApi.getPlanTaskPage(params) 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) if (parentIsSelected) { 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) const childList = allDetailsMap.value[row.id] || [] if (childList.length === 0) { - message.warning(`任务单 ${row.code} 无任务明细数据,无法勾选`) + message.warning(t('ProductionPlan.TaskSummary.taskNoDetailWarning', { code: row.code })) taskTableRef.value?.toggleRowSelection(row, false) return } detailList.value.forEach((child) => { - detailTableRef.value?.toggleRowSelection(child, true) + const unplanNumber = child.number - child.planNumber + if (unplanNumber > 0) { + detailTableRef.value?.toggleRowSelection(child, true) + } }) return } @@ -510,15 +513,18 @@ const handleTaskSelectAll = async (selection: any[]) => { taskTableRef.value?.toggleRowSelection(row, false) } else { childList.forEach((child) => { - const rowInView = detailList.value.find(d => d.id === child.id) - if (rowInView) { - detailTableRef.value?.toggleRowSelection(rowInView, true) + const unplanNumber = child.number - child.planNumber + if (unplanNumber > 0) { + const rowInView = detailList.value.find(d => d.id === child.id) + if (rowInView) { + detailTableRef.value?.toggleRowSelection(rowInView, true) + } } }) } } if (hasEmptyChild) { - message.warning('部分任务单无明细数据,已自动取消勾选') + message.warning(t('ProductionPlan.TaskSummary.partialTaskNoDetailWarning')) } } else { detailTableRef.value?.clearSelection() @@ -531,10 +537,13 @@ const handleTaskSelectAll = async (selection: any[]) => { const handleDetailSelect = (selection: any[], row: any) => { const taskId = row.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 = childList.every(child => selection.some(sel => sel.id === child.id)) - const noChildrenSelected = childList.every(child => !selection.some(sel => sel.id === child.id)) + const allChildrenSelected = selectableChildren.length > 0 && selectableChildren.every(child => selection.some(sel => sel.id === child.id)) + const noChildrenSelected = selectableChildren.every(child => !selection.some(sel => sel.id === child.id)) const parentTask = taskList.value.find(task => task.id === taskId) if (parentTask) { @@ -551,14 +560,16 @@ const handleDetailSelectAll = (selection: any[]) => { const taskId = currentTask.value.id 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) 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) - if (currentViewSelection.length === childList.length && childList.length > 0) { + if (selectableChildren.length > 0 && currentViewSelection.length === selectableChildren.length) { taskTableRef.value?.toggleRowSelection(parentTask, true) } else if (currentViewSelection.length === 0) { taskTableRef.value?.toggleRowSelection(parentTask, false) @@ -568,6 +579,11 @@ const handleDetailSelectAll = (selection: any[]) => { const isTaskRowSelectable = () => !taskTableBusy.value && !detailLoading.value +const isDetailRowSelectable = (row: any) => { + const unplanNumber = row.number - row.planNumber + return unplanNumber > 0 +} + const handleSearch = async () => { queryParams.pageNo = 1 await loadTaskList() @@ -589,7 +605,7 @@ const handleReset = async () => { const openTaskItemNeed = (row: any) => { 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) => { @@ -599,7 +615,7 @@ const openProductItemNeed = (row: any) => { } const openDeviceRelationDialog = async (row: any) => { if (!row?.productId) { - message.warning('当前明细没有关联产品,无法设置设备') + message.warning(t('ProductionPlan.TaskSummary.detailNoProductWarning')) return } currentDeviceRelationRow.value = row @@ -613,7 +629,7 @@ const openDeviceRelationDialog = async (row: any) => { (productData as any).devices ?? (productData as any).deviceIds, (productData as any).deviceList, ['name', 'deviceName', 'code'], - '设备' + t('ProductionPlan.TaskSummary.deviceColumnName') ) deviceRelationForm.productId = Number(row.productId) deviceRelationForm.devices = devices @@ -635,7 +651,7 @@ const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: an if (!Number.isFinite(id)) return undefined return { 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)) @@ -658,7 +674,7 @@ const submitDeviceRelation = async () => { currentData.molds ?? currentData.moldIds, currentData.moldList, ['name', 'code'], - '模具' + t('ProductionPlan.TaskSummary.deviceColumnName') ) const payload: any = { ...currentData, @@ -669,7 +685,7 @@ const submitDeviceRelation = async () => { delete payload.molds await ProductApi.updateProduct(payload) await refreshDetailListAfterDeviceSaved() - message.success('关联设备已保存') + message.success(t('ProductionPlan.TaskSummary.deviceRelationSaved')) deviceRelationDialogVisible.value = false } finally { deviceRelationSaving.value = false @@ -686,28 +702,32 @@ const hasValue = (value: unknown) => value !== null && value !== undefined && va const handleSubmit = async () => { if (searchForm.sortRule === undefined) { - message.warning('请选择排产规则') + message.warning(t('ProductionPlan.TaskSummary.selectScheduleRuleWarning')) return } if (searchForm.capacityType === undefined) { - message.warning('请选择产能来源') + message.warning(t('ProductionPlan.TaskSummary.selectCapacitySourceWarning')) return } const [workStartTime, workEndTime] = Array.isArray(searchForm.workTimeRange) ? searchForm.workTimeRange : [] if (!workStartTime || !workEndTime) { - message.warning('请选择生产时间安排') + message.warning(t('ProductionPlan.TaskSummary.selectWorkTimeWarning')) return } const selectedRows = detailTableRef.value?.getSelectionRows() || [] - if (selectedRows.length === 0) { - message.warning('至少选一个任务单汇总明细的数据') + const filteredRows = selectedRows.filter((row: any) => { + const unplanNumber = row.number - row.planNumber + return unplanNumber > 0 + }) + if (filteredRows.length === 0) { + message.warning(t('ProductionPlan.TaskSummary.selectDetailWarning')) return } submitLoading.value = true try { - console.log(selectedRows) - const createReqVO = selectedRows.map((row: any) => { + console.log(filteredRows) + const createReqVO = filteredRows.map((row: any) => { const planNumber = row.number - row.planNumber > 0 ? row.number - row.planNumber : 0 return { // PlanForm fields @@ -745,7 +765,7 @@ const handleSubmit = async () => { ? (scheduleResult as any).data : [] previewScheduleList.value = scheduleData - message.success('排产已提交') + message.success(t('ProductionPlan.TaskSummary.scheduleSubmitted')) previewVisible.value = true emit('success') } finally { diff --git a/src/views/mes/tasksummary/components/TaskSchedulePreviewDialog.vue b/src/views/mes/tasksummary/components/TaskSchedulePreviewDialog.vue index fc6e0dee..32402548 100644 --- a/src/views/mes/tasksummary/components/TaskSchedulePreviewDialog.vue +++ b/src/views/mes/tasksummary/components/TaskSchedulePreviewDialog.vue @@ -1,6 +1,6 @@