style:任务单排产字段调整

pull/1/head
黄伟杰 3 weeks ago
parent 062bdce1df
commit 93f84dd379

@ -9,6 +9,7 @@
:show-overflow-tooltip="true" :show-overflow-tooltip="true"
:stripe="true" :stripe="true"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@row-click="handleRowClick"
> >
<el-table-column type="selection" width="55" reserve-selection /> <el-table-column type="selection" width="55" reserve-selection />
<el-table-column <el-table-column
@ -53,11 +54,13 @@ const props = withDefaults(
title: string title: string
columns: TableColumn[] columns: TableColumn[]
fetchApi: (params: Record<string, any>) => Promise<{ list: any[]; total: number }> fetchApi: (params: Record<string, any>) => Promise<{ list: any[]; total: number }>
selectionType?: 'single' | 'multiple'
rowKey?: string rowKey?: string
pageSize?: number pageSize?: number
initialRows?: any[] initialRows?: any[]
}>(), }>(),
{ {
selectionType: 'multiple',
rowKey: 'id', rowKey: 'id',
pageSize: 10, pageSize: 10,
initialRows: () => [] initialRows: () => []
@ -79,6 +82,7 @@ const queryParams = reactive({
}) })
const selectedMap = ref(new Map<number | string, any>()) const selectedMap = ref(new Map<number | string, any>())
const syncingSelection = ref(false) const syncingSelection = ref(false)
const isSingleSelect = computed(() => props.selectionType === 'single')
const resolveRowKey = (row: Record<string, any>) => row[props.rowKey] const resolveRowKey = (row: Record<string, any>) => row[props.rowKey]
@ -115,6 +119,15 @@ const getList = async () => {
const handleSelectionChange = (rows: any[]) => { const handleSelectionChange = (rows: any[]) => {
if (syncingSelection.value) return if (syncingSelection.value) return
if (isSingleSelect.value) {
selectedMap.value.clear()
const latestRow = rows.length ? rows[rows.length - 1] : undefined
if (latestRow) {
selectedMap.value.set(resolveRowKey(latestRow), latestRow)
}
void refreshSelectionOnTable()
return
}
const pageIdSet = new Set(list.value.map((item) => resolveRowKey(item))) const pageIdSet = new Set(list.value.map((item) => resolveRowKey(item)))
pageIdSet.forEach((id) => { pageIdSet.forEach((id) => {
selectedMap.value.delete(id) selectedMap.value.delete(id)
@ -124,9 +137,26 @@ const handleSelectionChange = (rows: any[]) => {
}) })
} }
const handleRowClick = (row: any) => {
if (!isSingleSelect.value) return
const table = tableRef.value
if (!table) return
syncingSelection.value = true
try {
table.clearSelection()
table.toggleRowSelection(row, true)
} finally {
syncingSelection.value = false
}
selectedMap.value.clear()
selectedMap.value.set(resolveRowKey(row), row)
}
const open = async (rows?: any[]) => { const open = async (rows?: any[]) => {
selectedMap.value.clear() selectedMap.value.clear()
;(rows || props.initialRows).forEach((row) => { const initialRows = rows || props.initialRows
const nextRows = isSingleSelect.value ? initialRows.slice(0, 1) : initialRows
nextRows.forEach((row) => {
selectedMap.value.set(resolveRowKey(row), row) selectedMap.value.set(resolveRowKey(row), row)
}) })
queryParams.pageNo = 1 queryParams.pageNo = 1

@ -3484,6 +3484,7 @@ export default {
tableCodeColumn: 'Plan Code', tableCodeColumn: 'Plan Code',
tableProductColumn: 'Product', tableProductColumn: 'Product',
tableDeviceNameColumn: 'Device Name',
tableFeedingPipelineColumn: 'Production Line', tableFeedingPipelineColumn: 'Production Line',
tablePlanNumberColumn: 'Planned Qty', tablePlanNumberColumn: 'Planned Qty',
tableFinishNumberColumn: 'Finished Qty', tableFinishNumberColumn: 'Finished Qty',

@ -3321,6 +3321,7 @@ export default {
tableCodeColumn: '计划编码', tableCodeColumn: '计划编码',
tableProductColumn: '产品', tableProductColumn: '产品',
tableDeviceNameColumn: '设备名称',
tableFeedingPipelineColumn: '生产线', tableFeedingPipelineColumn: '生产线',
tablePlanNumberColumn: '计划数量', tablePlanNumberColumn: '计划数量',
tableFinishNumberColumn: '完工数量', tableFinishNumberColumn: '完工数量',

@ -4,7 +4,7 @@
ref="formRef" ref="formRef"
:model="formData" :model="formData"
:rules="formRules" :rules="formRules"
label-width="100px" label-width="110px"
v-loading="formLoading" v-loading="formLoading"
> >
<el-form-item :label="t('ProductionPlan.Plan.dialogTaskLabel')" prop="taskId"> <el-form-item :label="t('ProductionPlan.Plan.dialogTaskLabel')" prop="taskId">
@ -68,30 +68,8 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item :label="t('ProductionPlan.Plan.dialogFeedingPipelineLabel')" prop="feedingPipeline"> <el-form-item label="交货日期">
<el-tree-select <el-input :model-value="deliveryDateText" disabled />
v-model="formData.feedingPipeline"
:data="organizationTree"
:props="defaultProps"
check-strictly
default-expand-all
:placeholder="t('ProductionPlan.Plan.dialogFeedingPipelinePlaceholder')"
/>
</el-form-item>
<el-form-item :label="t('ProductionPlan.Plan.dialogWorkerLabel')" prop="workerId">
<el-select
v-model="formData.workerId"
clearable
filterable
:placeholder="t('ProductionPlan.Plan.dialogWorkerPlaceholder')"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
<!-- <el-form-item label="产品" prop="productId">--> <!-- <el-form-item label="产品" prop="productId">-->
<!-- <el-select--> <!-- <el-select-->
@ -110,6 +88,14 @@
<!-- />--> <!-- />-->
<!-- </el-select>--> <!-- </el-select>-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-form-item label="设备" prop="feedingPipeline">
<el-input
:model-value="deviceDisplayText"
placeholder="点击选择设备"
readonly
@click="openDeviceSelectDialog"
/>
</el-form-item>
<el-form-item :label="t('ProductionPlan.Plan.dialogPlanNumberLabel')" prop="planNumber"> <el-form-item :label="t('ProductionPlan.Plan.dialogPlanNumberLabel')" prop="planNumber">
<el-input v-model="formData.planNumber" /> <el-input v-model="formData.planNumber" />
</el-form-item> </el-form-item>
@ -145,6 +131,16 @@
class="!w-full" class="!w-full"
/> />
</el-form-item> </el-form-item>
<el-form-item label="最晚开工时间" prop="latestStartTime">
<el-date-picker
v-model="formData.latestStartTime"
type="date"
value-format="x"
:disabled-date="latestStartDisabledDate"
placeholder="请选择最晚开工时间"
class="!w-full"
/>
</el-form-item>
<!-- <el-form-item label="班别" prop="groupType"> <!-- <el-form-item label="班别" prop="groupType">
<el-radio-group v-model="formData.groupType"> <el-radio-group v-model="formData.groupType">
<el-radio <el-radio
@ -165,32 +161,35 @@
<el-button @click="dialogVisible = false">{{ t('ProductionPlan.Plan.dialogCancelButtonText') }}</el-button> <el-button @click="dialogVisible = false">{{ t('ProductionPlan.Plan.dialogCancelButtonText') }}</el-button>
</template> </template>
</Dialog> </Dialog>
<TableSelectDialog
ref="deviceSelectDialogRef"
title="选择设备"
:columns="deviceColumns"
:fetch-api="fetchDeviceLedgerPage"
selection-type="single"
row-key="id"
@confirm="handleDeviceSelectConfirm"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs'
import { PlanApi, PlanVO } from '@/api/mes/plan' import { PlanApi, PlanVO } from '@/api/mes/plan'
import * as UserApi from "@/api/system/user"; import { TaskApi, TaskDetailVO, TaskVO } from '@/api/mes/task'
import { TaskApi, TaskDetailVO, TaskVO} from "@/api/mes/task"; import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { ProductVO } from "@/api/erp/product/product"; import TableSelectDialog from '@/components/TableSelectDialog/TableSelectDialog.vue'
import { defaultProps, handleTree } from '@/utils/tree'; import { DICT_TYPE, getIntDictOptions } from "@/utils/dict";
import { OrganizationApi } from '@/api/mes/organization';
import {WorkTeamApi} from "@/api/mes/workteam";
import {DICT_TYPE, getIntDictOptions} from "@/utils/dict";
import { StockOutApi, StockOutVO } from '@/api/erp/stock/out'
/** 生产计划 表单 */ /** 生产计划 表单 */
defineOptions({ name: 'PlanForm' }) defineOptions({ name: 'PlanForm' })
const userList = ref<UserApi.UserVO[]>([]) //
const productList = ref<ProductVO[]>([]) //
const taskList = ref<TaskVO[]>([]) // const taskList = ref<TaskVO[]>([]) //
const taskDetailList = ref<TaskDetailVO[]>([]) // const taskDetailList = ref<TaskDetailVO[]>([]) //
const organizationTree = ref() // const deviceSelectDialogRef = ref()
const selectedDeviceRows = ref<DeviceLedgerVO[]>([])
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //
const editDisable = ref(false) //
const dialogVisible = ref(false) // const dialogVisible = ref(false) //
const dialogTitle = ref('') // const dialogTitle = ref('') //
const formLoading = ref(false) // 12 const formLoading = ref(false) // 12
@ -214,10 +213,61 @@ const formData = ref({
groupType: undefined, groupType: undefined,
isEnable: undefined, isEnable: undefined,
feedingPipeline: undefined, feedingPipeline: undefined,
feedingPipelineName: undefined,
workerId: undefined, workerId: undefined,
isPreProduction: undefined, isPreProduction: undefined,
isCode: undefined isCode: undefined,
latestStartTime: undefined,
finishDate: undefined
})
const deliveryDateText = computed(() => {
if (!formData.value.finishDate) return ''
const value = dayjs(formData.value.finishDate)
if (!value.isValid()) return String(formData.value.finishDate)
return value.format('YYYY-MM-DD')
}) })
const deviceDisplayText = computed(() => {
if (selectedDeviceRows.value.length) {
return selectedDeviceRows.value
.map((item: any) => item.deviceName || item.name || item.code || `ID:${item.id}`)
.join('、')
}
if (formData.value.feedingPipelineName) return String(formData.value.feedingPipelineName)
return ''
})
const deviceColumns = [
{ label: '设备编号', prop: 'deviceCode', minWidth: 140 },
{ label: '设备名称', prop: 'deviceName', minWidth: 160 },
{ label: '设备型号', prop: 'deviceModel', minWidth: 140 },
{ label: '所属车间', prop: 'workshop', minWidth: 140 }
]
const latestStartDisabledDate = (date: Date) => {
if (!formData.value.finishDate) return false
const deliveryDate = dayjs(formData.value.finishDate)
if (!deliveryDate.isValid()) return false
return dayjs(date).startOf('day').valueOf() > deliveryDate.startOf('day').valueOf()
}
const validateLatestStartTime = (_rule: any, value: any, callback: (error?: Error) => void) => {
if (!value) {
callback()
return
}
if (!formData.value.finishDate) {
callback()
return
}
const latestStart = dayjs(value)
const deliveryDate = dayjs(formData.value.finishDate)
if (!latestStart.isValid() || !deliveryDate.isValid()) {
callback()
return
}
if (latestStart.startOf('day').valueOf() > deliveryDate.startOf('day').valueOf()) {
callback(new Error('最晚开工时间不能晚于交货日期'))
return
}
callback()
}
const formRules = reactive({ const formRules = reactive({
taskDetailId: [{ required: true, message: t('ProductionPlan.Plan.validatorTaskDetailRequired'), trigger: 'blur' }], taskDetailId: [{ required: true, message: t('ProductionPlan.Plan.validatorTaskDetailRequired'), trigger: 'blur' }],
taskId: [{ required: true, message: t('ProductionPlan.Plan.validatorTaskRequired'), trigger: 'blur' }], taskId: [{ required: true, message: t('ProductionPlan.Plan.validatorTaskRequired'), trigger: 'blur' }],
@ -225,19 +275,59 @@ const formRules = reactive({
// reyaNumber: [{ required: true, message: t('ProductionPlan.Plan.validatorReyaNumberRequired'), trigger: 'blur' }], // reyaNumber: [{ required: true, message: t('ProductionPlan.Plan.validatorReyaNumberRequired'), trigger: 'blur' }],
planStartTime: [{ required: true, message: t('ProductionPlan.Plan.validatorPlanStartRequired'), trigger: 'blur' }], planStartTime: [{ required: true, message: t('ProductionPlan.Plan.validatorPlanStartRequired'), trigger: 'blur' }],
planEndTime: [{ required: true, message: t('ProductionPlan.Plan.validatorPlanEndRequired'), trigger: 'blur' }], planEndTime: [{ required: true, message: t('ProductionPlan.Plan.validatorPlanEndRequired'), trigger: 'blur' }],
feedingPipeline: [{ required: true, message: t('ProductionPlan.Plan.validatorFeedingPipelineRequired'), trigger: 'blur' }], feedingPipeline: [{ required: true, message: '请选择设备', trigger: 'change' }],
workerId: [{ required: true, message: t('ProductionPlan.Plan.validatorWorkerRequired'), trigger: 'blur' }],
isPreProduction: [{ required: true, message: t('ProductionPlan.Plan.validatorPreProductionRequired'), trigger: 'blur' }], isPreProduction: [{ required: true, message: t('ProductionPlan.Plan.validatorPreProductionRequired'), trigger: 'blur' }],
latestStartTime: [
{ required: true, message: '请选择最晚开工时间', trigger: 'blur' },
{ validator: validateLatestStartTime, trigger: 'change' }
]
}) })
const formRef = ref() // Ref const formRef = ref() // Ref
const fetchDeviceLedgerPage = (params: Record<string, any>) => {
console.log('11',taskDetailList.value[0])
return DeviceLedgerApi.getDeviceLedgerPage({
...params,
isScheduled: 1,
productId: taskDetailList.value[0].productId
})
}
const openDeviceSelectDialog = () => {
const rows = selectedDeviceRows.value.length
? selectedDeviceRows.value.map((item: any) => ({ ...item, id: Number(item.id) }))
: formData.value.feedingPipeline
? [
{
id: Number(formData.value.feedingPipeline),
deviceName: formData.value.feedingPipelineName
}
]
: []
deviceSelectDialogRef.value?.open(rows)
}
const handleDeviceSelectConfirm = (payload: { ids: (number | string)[]; rows: any[] }) => {
const row = payload.rows?.[0]
if (!row) return
const deviceId = Number(row.id)
if (!Number.isFinite(deviceId)) return
formData.value.feedingPipeline = deviceId
formData.value.feedingPipelineName = row.deviceName || row.name || row.code || `设备ID:${deviceId}`
selectedDeviceRows.value = [row]
}
const syncFinishDateByTaskDetail = () => {
const detail = taskDetailList.value.find((item: any) => Number(item.id) === Number(formData.value.taskDetailId))
formData.value.finishDate = detail?.finishDate || detail?.deliveryDate || undefined
}
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number, const open = async (type: string, id?: number,
taskId?: number, productId?: number, number?: number, taskDetailId?:string) => { taskId?: number, productId?: number, number?: number, taskDetailId?:string) => {
dialogVisible.value = true dialogVisible.value = true
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
formType.value = type formType.value = type
editDisable.value = false
resetForm() resetForm()
if(taskId) { if(taskId) {
formData.value.taskId = taskId formData.value.taskId = taskId
@ -246,6 +336,7 @@ const open = async (type: string, id?: number,
const taskDetails = taskDetailList.value.filter(item => item.id === taskDetailId) const taskDetails = taskDetailList.value.filter(item => item.id === taskDetailId)
if(taskDetails && taskDetails.length > 0 && taskDetails[0].id) { if(taskDetails && taskDetails.length > 0 && taskDetails[0].id) {
formData.value.taskDetailId = taskDetails[0].id formData.value.taskDetailId = taskDetails[0].id
formData.value.finishDate = (taskDetails[0] as any).finishDate || (taskDetails[0] as any).deliveryDate || undefined
} }
} }
} }
@ -255,27 +346,24 @@ const open = async (type: string, id?: number,
formData.value.planNumber = number formData.value.planNumber = number
formData.value.reyaNumber = number formData.value.reyaNumber = number
} }
if(type==='update'){
editDisable.value = true
}
// //
if (id) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
formData.value = await PlanApi.getPlan(id) formData.value = await PlanApi.getPlan(id)
if (formData.value.feedingPipeline) {
selectedDeviceRows.value = [
{
id: Number(formData.value.feedingPipeline),
deviceName: formData.value.feedingPipelineName
} as DeviceLedgerVO
]
}
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
} }
//
//userList.value = await UserApi.getSimpleUserList()
//
//productList.value = await ProductApi.getMesProductSimpleList()
//
taskList.value = await TaskApi.getPlanTaskList() taskList.value = await TaskApi.getPlanTaskList()
//
userList.value = await WorkTeamApi.getUserList("zhijiang", '')
await getOrganizationTree()
} }
defineExpose({ open }) // open defineExpose({ open }) // open
@ -322,29 +410,26 @@ const resetForm = () => {
remark: undefined, remark: undefined,
groupType: undefined, groupType: undefined,
isEnable: undefined, isEnable: undefined,
feedingPipeline: undefined,
feedingPipelineName: undefined,
isPreProduction: 0, isPreProduction: 0,
isCode: true isCode: true,
latestStartTime: undefined,
finishDate: undefined
} }
selectedDeviceRows.value = []
formRef.value?.resetFields() formRef.value?.resetFields()
} }
/** 任务单变化 */ /** 任务单变化 */
const handleTaskChange = async(e) => { const handleTaskChange = async() => {
taskDetailList.value =await TaskApi.getTaskDetailListByTaskId(formData.value.taskId) taskDetailList.value =await TaskApi.getTaskDetailListByTaskId(formData.value.taskId)
formData.value.taskDetailId = undefined
formData.value.finishDate = undefined
} }
/** 明细变化 */ /** 明细变化 */
const handleTaskDetailChange = async(e) => { const handleTaskDetailChange = async() => {
console.log(e) syncFinishDateByTaskDetail()
}
/** 获得产线工位树 */
const getOrganizationTree = async () => {
organizationTree.value = []
const req = {orgClass:'pipeline'}
const data = await OrganizationApi.getOrganizationList(req)
const root: Tree = { id: 0, name: '顶级组织', children: [] }
root.children = handleTree(data, 'id', 'parentId')
organizationTree.value.push(root)
} }
</script> </script>

@ -165,7 +165,7 @@
<el-table-column :label="t('ProductionPlan.Plan.tableCodeColumn')" align="center" prop="code" min-width="180px" sortable/> <el-table-column :label="t('ProductionPlan.Plan.tableCodeColumn')" align="center" prop="code" min-width="180px" sortable/>
<el-table-column :label="t('ProductionPlan.Plan.tableProductColumn')" align="center" prop="productName" min-width="200px" sortable/> <el-table-column :label="t('ProductionPlan.Plan.tableProductColumn')" align="center" prop="productName" min-width="200px" sortable/>
<!-- <el-table-column label="任务单" align="center" prop="taskCode" min-width="150px" sortable />--> <!-- <el-table-column label="任务单" align="center" prop="taskCode" min-width="150px" sortable />-->
<el-table-column :label="t('ProductionPlan.Plan.tableFeedingPipelineColumn')" align="center" prop="feedingPipelineName" sortable /> <el-table-column :label="t('ProductionPlan.Plan.tableDeviceNameColumn')" align="center" prop="deviceName" sortable />
<el-table-column :label="t('ProductionPlan.Plan.tablePlanNumberColumn')" align="center" prop="planNumber" sortable/> <el-table-column :label="t('ProductionPlan.Plan.tablePlanNumberColumn')" align="center" prop="planNumber" sortable/>
<el-table-column :label="t('ProductionPlan.Plan.tableFinishNumberColumn')" align="center" prop="wangongNumber" sortable/> <el-table-column :label="t('ProductionPlan.Plan.tableFinishNumberColumn')" align="center" prop="wangongNumber" sortable/>
<el-table-column :label="t('ProductionPlan.Plan.tablePassRateColumn')" align="center" prop="passRate" sortable/> <el-table-column :label="t('ProductionPlan.Plan.tablePassRateColumn')" align="center" prop="passRate" sortable/>

@ -483,7 +483,6 @@ const handleSubmit = async () => {
isCode: true, isCode: true,
planStartTime: new Date().getTime(), planStartTime: new Date().getTime(),
planEndTime: new Date().getTime(), planEndTime: new Date().getTime(),
reyaNumber: planNumber,
productCode: row.barCode, productCode: row.barCode,
// Image fields // Image fields

@ -74,7 +74,7 @@ v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" hi
:formatter="dateFormatter2" sortable /> :formatter="dateFormatter2" sortable />
<el-table-column <el-table-column
:label="t('ProductionPlan.TaskSummary.tableDeliveryDateColumn')" align="center" :label="t('ProductionPlan.TaskSummary.tableDeliveryDateColumn')" align="center"
prop="deliveryDate" :formatter="dateFormatter2" sortable /> prop="deliveryDate" :formatter="deliveryDateFormatter" sortable />
<el-table-column :label="t('ProductionPlan.TaskSummary.tableStatusColumn')" align="center" prop="status" sortable> <el-table-column :label="t('ProductionPlan.TaskSummary.tableStatusColumn')" align="center" prop="status" sortable>
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.MES_TASK_STATUS" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.MES_TASK_STATUS" :value="scope.row.status" />
@ -158,6 +158,10 @@ const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // const exportLoading = ref(false) //
const { push } = useRouter() const { push } = useRouter()
const taskScheduleDialogRef = ref() const taskScheduleDialogRef = ref()
const deliveryDateFormatter = (_row: any, _column: any, value: any) => {
if (value) return dateFormatter2(_row, _column, value)
return dateFormatter2(_row, _column, _row?.finishDate)
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true

Loading…
Cancel
Save