✨ feat(mes): 优化生产任务保存请求和验证逻辑
调整生产任务保存请求的字段为可选,简化编辑时的请求参数。更新任务验证逻辑,确保在更新时只校验存在的字段,提升用户体验和代码可维护性。同时,新增甘特图编辑页面,支持批量保存任务修改。pull/871/MERGE
parent
98c8b9a5cf
commit
0a0cd5f165
|
|
@ -127,43 +127,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/mes',
|
||||
component: Layout,
|
||||
name: 'MesWmRouter',
|
||||
meta: {
|
||||
hidden: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'wm/warehouse/location',
|
||||
component: () => import('@/views/mes/wm/warehouse/location/index.vue'),
|
||||
name: 'MesWmLocation',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: '',
|
||||
title: '库区设置',
|
||||
activeMenu: '/mes/wm/warehouse'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'wm/warehouse/area',
|
||||
component: () => import('@/views/mes/wm/warehouse/area/index.vue'),
|
||||
name: 'MesWmArea',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: '',
|
||||
title: '库位设置',
|
||||
activeMenu: '/mes/wm/warehouse'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/codegen',
|
||||
component: Layout,
|
||||
|
|
@ -270,6 +233,16 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
noTagsView: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/views/Error/404.vue'),
|
||||
name: '',
|
||||
meta: {
|
||||
title: '404',
|
||||
hidden: true,
|
||||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bpm',
|
||||
component: Layout,
|
||||
|
|
@ -730,16 +703,6 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/views/Error/404.vue'),
|
||||
name: '',
|
||||
meta: {
|
||||
title: '404',
|
||||
hidden: true,
|
||||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/iot',
|
||||
component: Layout,
|
||||
|
|
@ -782,6 +745,55 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
component: () => import('@/views/iot/ota/firmware/detail/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/mes',
|
||||
component: Layout,
|
||||
name: 'MesWmRouter',
|
||||
meta: {
|
||||
hidden: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'wm/warehouse/location',
|
||||
component: () => import('@/views/mes/wm/warehouse/location/index.vue'),
|
||||
name: 'MesWmLocation',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: '',
|
||||
title: '库区设置',
|
||||
activeMenu: '/mes/wm/warehouse'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'wm/warehouse/area',
|
||||
component: () => import('@/views/mes/wm/warehouse/area/index.vue'),
|
||||
name: 'MesWmArea',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: '',
|
||||
title: '库位设置',
|
||||
activeMenu: '/mes/wm/warehouse'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'pro/task/gantt-edit',
|
||||
component: () => import('@/views/mes/pro/task/edit/index.vue'),
|
||||
name: 'MesProTaskGanttEdit',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: '',
|
||||
title: '甘特图编辑',
|
||||
activeMenu: '/mes/pro/task'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -64,10 +64,16 @@ const initGantt = () => {
|
|||
gantt.config.show_progress = true // KTG 无显式设置,但 gantt 默认会渲染 progress。保留:确保进度条显示
|
||||
gantt.config.open_tree_initially = true // 初始展开树结构。KTG 也有:open_tree_initially = true
|
||||
gantt.config.auto_types = false // 禁止自动升级为 project。KTG 也有:auto_types = false
|
||||
gantt.config.drag_resize = false // 禁止调整任务持续时间
|
||||
gantt.config.drag_move = false // 禁止拖动任务
|
||||
gantt.config.drag_progress = false // 禁止拖动进度条。KTG 也有:drag_progress = false
|
||||
// 注:xml_date 是旧版写法,等价于 date_format(已在上方设置)
|
||||
gantt.config.drag_resize = false // 禁止调整任务持续时间
|
||||
gantt.config.drag_progress = false // 禁止拖动进度条
|
||||
|
||||
// lightbox 弹窗配置:只保留时间编辑,去掉描述编辑和删除按钮
|
||||
gantt.config.lightbox.sections = [
|
||||
{ name: 'time', type: 'duration', map_to: 'auto' }
|
||||
]
|
||||
gantt.config.buttons_left = ['gantt_save_btn']
|
||||
gantt.config.buttons_right = ['gantt_cancel_btn']
|
||||
|
||||
// 时间刻度:周 > 日 > 8小时
|
||||
const weekScaleTemplate = (date: Date) => {
|
||||
|
|
@ -131,19 +137,18 @@ const initGantt = () => {
|
|||
}
|
||||
return ''
|
||||
}
|
||||
gantt.templates.task_cell_class = () => '' // KTG 无此配置。保留:防止 gantt 添加默认样式类
|
||||
gantt.templates.timeline_cell_class = () => '' // 防止 gantt 添加默认样式类
|
||||
gantt.templates.task_row_class = () => '' // KTG 无此配置。保留:防止 gantt 添加默认样式类
|
||||
|
||||
// 事件监听
|
||||
// KTG 用 onAfterTaskUpdate 收集修改 id;这里用 onAfterTaskDrag 直接 emit 结构化数据,更完善
|
||||
// 编辑事件监听(通过 lightbox 弹窗编辑后触发)
|
||||
if (!props.readonly) {
|
||||
gantt.attachEvent('onAfterTaskDrag', (id: string | number) => {
|
||||
gantt.attachEvent('onAfterTaskUpdate', (id: string | number) => {
|
||||
const task = gantt.getTask(id)
|
||||
emit('task-update', {
|
||||
id: task.originalId || id,
|
||||
startTime: task.start_date,
|
||||
endTime: task.end_date,
|
||||
duration: (task.duration as number) / 8 // 转回工作日
|
||||
duration: task.duration
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
<!-- MES 甘特图编辑(全屏 Dialog) -->
|
||||
<!-- MES 甘特图编辑 -->
|
||||
<template>
|
||||
<Dialog title="甘特图编辑" v-model="dialogVisible" fullscreen>
|
||||
<ContentWrap>
|
||||
<div class="mb-10px flex items-center justify-between">
|
||||
<span class="text-14px text-gray-500">
|
||||
拖拽任务条可调整开始时间和时长,修改后点击"批量保存"
|
||||
</span>
|
||||
<span class="text-14px text-gray-500">双击任务条可编辑开始时间和时长,修改后点击"批量保存"</span>
|
||||
<div>
|
||||
<el-badge :value="pendingCount" :hidden="pendingCount === 0" class="mr-10px">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSave"
|
||||
:loading="saving"
|
||||
:loading="formLoading"
|
||||
:disabled="pendingCount === 0"
|
||||
>
|
||||
批量保存
|
||||
|
|
@ -20,57 +18,44 @@
|
|||
</div>
|
||||
</div>
|
||||
<GanttChart
|
||||
ref="ganttRef"
|
||||
:tasks="taskList"
|
||||
:readonly="false"
|
||||
:height="ganttHeight"
|
||||
@task-update="handleTaskUpdate"
|
||||
/>
|
||||
</Dialog>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProTaskApi, ProTaskVO } from '@/api/mes/pro/task'
|
||||
import GanttChart from './components/GanttChart.vue'
|
||||
import { ProTaskApi } from '@/api/mes/pro/task'
|
||||
import GanttChart from '../components/GanttChart.vue'
|
||||
|
||||
defineOptions({ name: 'GanttEdit' })
|
||||
defineOptions({ name: 'MesProTaskGanttEdit' })
|
||||
|
||||
const message = useMessage()
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const taskList = ref<ProTaskVO[]>([])
|
||||
const saving = ref(false)
|
||||
const ganttRef = ref()
|
||||
const formLoading = ref(false) // 提交的按钮禁用
|
||||
const taskList = ref<any[]>([]) // 甘特图任务数据
|
||||
|
||||
/** 待保存的修改 Map<taskId, changeData> */
|
||||
const pendingChanges = ref(new Map<number, any>())
|
||||
const pendingCount = computed(() => pendingChanges.value.size)
|
||||
const pendingChanges = ref(new Map<number, any>()) // 待保存的修改 Map<taskId, changeData>
|
||||
const pendingCount = computed(() => pendingChanges.value.size) // 待保存数量
|
||||
const ganttHeight = computed(() => window.innerHeight - 180) // 甘特图高度
|
||||
|
||||
/** 甘特图高度 = 视口高度 - 顶栏 - 操作栏 */
|
||||
const ganttHeight = computed(() => window.innerHeight - 140)
|
||||
|
||||
/** 打开 */
|
||||
const open = async () => {
|
||||
dialogVisible.value = true
|
||||
pendingChanges.value = new Map()
|
||||
await loadGanttData()
|
||||
}
|
||||
|
||||
/** 加载甘特图数据(复用 page 接口,传大 pageSize) */
|
||||
/** 加载甘特图数据 */
|
||||
const loadGanttData = async () => {
|
||||
const data = await ProTaskApi.getTaskPage({ pageNo: 1, pageSize: 999 })
|
||||
taskList.value = data.list
|
||||
taskList.value = await ProTaskApi.getGanttTaskList({})
|
||||
}
|
||||
|
||||
/** 拖拽变更回调 */
|
||||
/** 任务编辑回调 */
|
||||
const handleTaskUpdate = (change: any) => {
|
||||
pendingChanges.value.set(change.id, change)
|
||||
}
|
||||
|
||||
/** 批量保存 */
|
||||
const handleSave = async () => {
|
||||
if (pendingChanges.value.size === 0) return
|
||||
saving.value = true
|
||||
if (pendingChanges.value.size === 0) {
|
||||
return
|
||||
}
|
||||
formLoading.value = true
|
||||
try {
|
||||
const promises = Array.from(pendingChanges.value.values()).map((change) =>
|
||||
ProTaskApi.updateTask({
|
||||
|
|
@ -83,9 +68,10 @@ const handleSave = async () => {
|
|||
await Promise.all(promises)
|
||||
message.success(`已保存 ${pendingChanges.value.size} 条修改`)
|
||||
pendingChanges.value = new Map()
|
||||
// 重新加载数据
|
||||
await loadGanttData()
|
||||
} finally {
|
||||
saving.value = false
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,5 +81,8 @@ const handleRefresh = async () => {
|
|||
await loadGanttData()
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await loadGanttData()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -149,10 +149,7 @@
|
|||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 排产对话框(工单详情 + 工序步骤 + 任务列表) -->
|
||||
<WorkOrderForm2 ref="formRef" />
|
||||
<!-- 甘特图编辑 Dialog -->
|
||||
<GanttEdit ref="ganttEditRef" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
@ -165,7 +162,6 @@ import { MesProWorkOrderStatusEnum, MesProWorkOrderTypeEnum } from '@/views/mes/
|
|||
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
|
||||
import MdClientSelect from '@/views/mes/md/client/components/MdClientSelect.vue'
|
||||
import GanttChart from './components/GanttChart.vue'
|
||||
import GanttEdit from './GanttEdit.vue'
|
||||
import WorkOrderForm2 from './WorkOrderForm2.vue'
|
||||
|
||||
defineOptions({ name: 'MesProTask' })
|
||||
|
|
@ -245,11 +241,10 @@ const handleFinish = async (id: number) => {
|
|||
} catch {}
|
||||
}
|
||||
|
||||
// TODO @芋艿:后续可以考虑把甘特图预览和编辑合并成一个组件,统一管理甘特图数据和刷新逻辑;
|
||||
/** 打开甘特图编辑弹窗 */
|
||||
const ganttEditRef = ref()
|
||||
/** 打开甘特图编辑页面 */
|
||||
const { push } = useRouter()
|
||||
const openGanttEdit = () => {
|
||||
ganttEditRef.value.open()
|
||||
push({ name: 'MesProTaskGanttEdit' })
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue