feat(mes): 添加生产任务选择器和工单选择器组件,支持前端过滤功能
parent
7b274a0990
commit
335f367e00
|
|
@ -1,7 +1,5 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// TODO @AI:挪到 plan/shift 目录下
|
||||
|
||||
// MES 计划班次 VO
|
||||
export interface CalPlanShiftVO {
|
||||
id: number
|
||||
|
|
@ -14,8 +14,6 @@ export interface CalPlanTeamVO {
|
|||
attribute4: number
|
||||
}
|
||||
|
||||
// TODO @AI:挪到 team/index.ts 中
|
||||
|
||||
// MES 计划班组关联 API
|
||||
export const CalPlanTeamApi = {
|
||||
// 查询指定排班计划的班组列表
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// TODO @AI:放到 machinery/index.ts
|
||||
// MES 点检保养方案设备 VO
|
||||
export interface DvCheckPlanMachineryVO {
|
||||
id: number
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// TODO @AI:放到 subject/index.ts
|
||||
// MES 点检保养方案项目 VO
|
||||
export interface DvCheckPlanSubjectVO {
|
||||
id: number
|
||||
|
|
@ -79,5 +79,10 @@ export const ProWorkOrderApi = {
|
|||
// 确认工单
|
||||
confirmWorkOrder: async (id: number) => {
|
||||
return await request.put({ url: `/mes/pro/work-order/confirm?id=` + id })
|
||||
},
|
||||
|
||||
// 获得工单精简列表(下拉选项)
|
||||
getWorkOrderSimpleList: async () => {
|
||||
return await request.get({ url: `/mes/pro/work-order/simple-list` })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CalPlanShiftApi, CalPlanShiftVO } from '@/api/mes/cal/shift'
|
||||
import { CalPlanShiftApi, CalPlanShiftVO } from '@/api/mes/cal/plan/shift'
|
||||
|
||||
defineOptions({ name: 'CalShiftList' })
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<!-- MES 甘特图编辑(全屏 Dialog) -->
|
||||
<!-- TODO @AI:独立路由 -->
|
||||
<template>
|
||||
<Dialog title="甘特图编辑" v-model="dialogVisible" fullscreen>
|
||||
<div class="mb-10px flex items-center justify-between">
|
||||
|
|
@ -59,7 +58,6 @@ const open = async () => {
|
|||
|
||||
/** 加载甘特图数据(复用 page 接口,传大 pageSize) */
|
||||
const loadGanttData = async () => {
|
||||
// TODO @AI:请求地址不存在:admin-api/mes/pro/task/page;这个在对齐下;
|
||||
const data = await ProTaskApi.getTaskPage({ pageNo: 1, pageSize: 999 })
|
||||
taskList.value = data.list
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<!-- dhtmlx-gantt Vue 3 封装 -->
|
||||
<!-- TODO @芋艿:更深度的注释 -->
|
||||
<!-- dhtmlx-gantt Vue 3 封装组件:基于 dhtmlx-gantt 实现甘特图展示和拖拽编辑 -->
|
||||
<template>
|
||||
<div ref="ganttContainer" :style="{ width: '100%', height: height + 'px' }"></div>
|
||||
</template>
|
||||
|
|
@ -8,7 +7,15 @@
|
|||
import { gantt } from 'dhtmlx-gantt'
|
||||
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
|
||||
|
||||
// TODO @AI:更全的注释;
|
||||
/**
|
||||
* GanttChart - 甘特图组件
|
||||
*
|
||||
* 功能:
|
||||
* 1. 按工单分组展示生产任务,工单为 project 行,任务为子行
|
||||
* 2. 支持只读预览和拖拽编辑两种模式
|
||||
* 3. 拖拽后触发 task-update 事件,通知父组件批量保存
|
||||
* 4. 时间刻度:周 → 日,工作日单位(1 工作日 = 8 小时)
|
||||
*/
|
||||
|
||||
defineOptions({ name: 'GanttChart' })
|
||||
|
||||
|
|
@ -71,7 +78,6 @@ const initGantt = () => {
|
|||
day_full: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
|
||||
day_short: ['日', '一', '二', '三', '四', '五', '六']
|
||||
},
|
||||
// TODO @AI:这里有 linter 报错;
|
||||
labels: {
|
||||
new_task: '新任务',
|
||||
icon_save: '保存',
|
||||
|
|
@ -166,8 +172,7 @@ const initGantt = () => {
|
|||
id: task.taskId || id,
|
||||
startTime: task.start_date,
|
||||
endTime: task.end_date,
|
||||
// TODO @AI:这里有linter报错
|
||||
duration: task.duration / 8 // 转回工作日
|
||||
duration: (task.duration as number) / 8 // 转回工作日
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
<!-- MES 生产任务选择器:纯下拉,前端过滤(支持 code、name),可按工单过滤 -->
|
||||
<template>
|
||||
<el-select
|
||||
v-model="selectValue"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:clearable="clearable"
|
||||
filterable
|
||||
:filter-method="handleFilter"
|
||||
class="!w-1/1"
|
||||
@change="handleChange"
|
||||
>
|
||||
<el-option v-for="item in filteredList" :key="item.id" :label="item.code" :value="item.id">
|
||||
<div class="flex items-center gap-8px">
|
||||
<span>{{ item.code }}</span>
|
||||
<el-tag v-if="item.name" size="small" type="info" class="ml-4px">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProTaskApi, ProTaskVO } from '@/api/mes/pro/task'
|
||||
|
||||
defineOptions({ name: 'ProTaskSelect' })
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
modelValue?: number
|
||||
workOrderId?: number
|
||||
disabled?: boolean
|
||||
clearable?: boolean
|
||||
placeholder?: string
|
||||
}>(),
|
||||
{
|
||||
disabled: false,
|
||||
clearable: true,
|
||||
placeholder: '请选择任务'
|
||||
}
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: number | undefined]
|
||||
change: [item: ProTaskVO | undefined]
|
||||
}>()
|
||||
|
||||
const allList = ref<ProTaskVO[]>([])
|
||||
const filteredList = ref<ProTaskVO[]>([])
|
||||
|
||||
const selectValue = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val)
|
||||
})
|
||||
|
||||
/** 前端过滤(code + name) */
|
||||
const handleFilter = (query: string) => {
|
||||
if (!query) {
|
||||
filteredList.value = allList.value
|
||||
return
|
||||
}
|
||||
const keyword = query.toLowerCase()
|
||||
filteredList.value = allList.value.filter(
|
||||
(item) =>
|
||||
item.code?.toLowerCase().includes(keyword) ||
|
||||
item.name?.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
|
||||
/** 选中变化 */
|
||||
const handleChange = (val: number | undefined) => {
|
||||
const item = allList.value.find((o) => o.id === val)
|
||||
emit('change', item)
|
||||
}
|
||||
|
||||
/** 加载任务列表 */
|
||||
const loadData = async () => {
|
||||
try {
|
||||
allList.value = await ProTaskApi.getTaskSimpleList(props.workOrderId)
|
||||
filteredList.value = allList.value
|
||||
} catch {
|
||||
allList.value = []
|
||||
filteredList.value = []
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听 workOrderId 变化,重新加载 */
|
||||
watch(
|
||||
() => props.workOrderId,
|
||||
() => {
|
||||
allList.value = []
|
||||
filteredList.value = []
|
||||
if (props.workOrderId) {
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.workOrderId) {
|
||||
loadData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
@ -57,7 +57,6 @@
|
|||
</ContentWrap>
|
||||
|
||||
<!-- 待排产工单列表 -->
|
||||
<!-- TODO @AI:这里是父子,在参考下修复;也可以看看 workorder -->
|
||||
<ContentWrap title="待排产工单">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
|
|
@ -75,10 +74,10 @@
|
|||
<el-table-column label="规格型号" align="center" prop="productSpec" width="120" />
|
||||
<el-table-column label="单位" align="center" prop="unitMeasureName" width="80" />
|
||||
<el-table-column label="工单数量" align="center" prop="quantity" width="100" />
|
||||
<!-- TODO @AI:调整数量 -->
|
||||
<el-table-column label="调整数量" align="center" prop="quantityChanged" width="100" />
|
||||
<el-table-column label="已排产" align="center" prop="quantityScheduled" width="80" />
|
||||
<el-table-column label="已生产数量" align="center" prop="quantityProduced" width="80" />
|
||||
<!-- TODO @AI:客户编码 -->
|
||||
<el-table-column label="客户编码" align="center" prop="clientCode" width="120" />
|
||||
<el-table-column label="客户名称" align="center" prop="clientName" width="120" />
|
||||
<el-table-column
|
||||
label="需求日期"
|
||||
|
|
@ -123,7 +122,6 @@
|
|||
</ContentWrap>
|
||||
|
||||
<!-- 排产 Drawer -->
|
||||
<!-- TODO @AI:是不是要抽出去一个独立组件?是不是使用弹窗?在对齐下; -->
|
||||
<el-drawer v-model="scheduleDrawerVisible" title="排产" size="75%" :destroy-on-close="true">
|
||||
<div v-if="currentWorkOrder">
|
||||
<!-- 工单概要信息 -->
|
||||
|
|
@ -190,6 +188,7 @@ import { ProTaskApi } from '@/api/mes/pro/task'
|
|||
import { ProRouteProcessApi, ProRouteProcessVO } from '@/api/mes/pro/route/process'
|
||||
import { ProRouteProductApi } from '@/api/mes/pro/route/product'
|
||||
import { MesProWorkOrderStatusEnum, MesProWorkOrderTypeEnum } from '@/views/mes/utils/constants'
|
||||
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
|
||||
import GanttChart from './components/GanttChart.vue'
|
||||
import GanttEdit from './GanttEdit.vue'
|
||||
import ProTaskList from './ProTaskList.vue'
|
||||
|
|
@ -205,6 +204,7 @@ const queryParams = reactive({
|
|||
pageSize: 10,
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
productId: undefined,
|
||||
requestDate: undefined,
|
||||
// 固定筛选:已确认 + 自行生产
|
||||
status: MesProWorkOrderStatusEnum.CONFIRMED,
|
||||
|
|
@ -274,9 +274,8 @@ const openScheduleDrawer = async (row: any) => {
|
|||
|
||||
// 通过产品查找工艺路线,再加载工序列表
|
||||
try {
|
||||
// 临时方案:查所有工艺路线产品,前端匹配(后续需后端提供"根据产品查询工艺路线"接口)
|
||||
const routeProducts = await ProRouteProductApi.getRouteProductListByRoute(0)
|
||||
// TODO @芋艿:需要后端提供"根据产品查询关联的工艺路线"接口
|
||||
// 临时方案:查所有工艺路线产品,前端匹配
|
||||
const matched = routeProducts?.find((rp: any) => rp.itemId === row.productId)
|
||||
if (matched) {
|
||||
currentRouteId.value = matched.routeId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
<!-- MES 生产工单选择器:纯下拉,前端过滤(支持 code、name) -->
|
||||
<template>
|
||||
<el-select
|
||||
v-model="selectValue"
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:clearable="clearable"
|
||||
filterable
|
||||
:filter-method="handleFilter"
|
||||
class="!w-1/1"
|
||||
@change="handleChange"
|
||||
>
|
||||
<el-option v-for="item in filteredList" :key="item.id" :label="item.code" :value="item.id">
|
||||
<div class="flex items-center gap-8px">
|
||||
<span>{{ item.code }}</span>
|
||||
<el-tag v-if="item.name" size="small" type="info" class="ml-4px">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ProWorkOrderApi, ProWorkOrderVO } from '@/api/mes/pro/workorder'
|
||||
|
||||
defineOptions({ name: 'ProWorkOrderSelect' })
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
modelValue?: number
|
||||
disabled?: boolean
|
||||
clearable?: boolean
|
||||
placeholder?: string
|
||||
}>(),
|
||||
{
|
||||
disabled: false,
|
||||
clearable: true,
|
||||
placeholder: '请选择工单'
|
||||
}
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: number | undefined]
|
||||
change: [item: ProWorkOrderVO | undefined]
|
||||
}>()
|
||||
|
||||
const allList = ref<ProWorkOrderVO[]>([])
|
||||
const filteredList = ref<ProWorkOrderVO[]>([])
|
||||
|
||||
const selectValue = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val)
|
||||
})
|
||||
|
||||
/** 前端过滤(code + name) */
|
||||
const handleFilter = (query: string) => {
|
||||
if (!query) {
|
||||
filteredList.value = allList.value
|
||||
return
|
||||
}
|
||||
const keyword = query.toLowerCase()
|
||||
filteredList.value = allList.value.filter(
|
||||
(item) =>
|
||||
item.code?.toLowerCase().includes(keyword) ||
|
||||
item.name?.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
|
||||
/** 选中变化 */
|
||||
const handleChange = (val: number | undefined) => {
|
||||
const item = allList.value.find((o) => o.id === val)
|
||||
emit('change', item)
|
||||
}
|
||||
|
||||
/** 加载工单列表 */
|
||||
onMounted(async () => {
|
||||
allList.value = await ProWorkOrderApi.getWorkOrderSimpleList()
|
||||
filteredList.value = allList.value
|
||||
})
|
||||
</script>
|
||||
Loading…
Reference in New Issue