优化工序计划派工待派数量与卡片信息展示
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4c974947af
commit
18b4399789
@ -88,6 +88,12 @@ export interface ProcessPlanItemVO {
|
|||||||
|
|
||||||
planFinishTime?: string
|
planFinishTime?: string
|
||||||
|
|
||||||
|
/** 计划开始(部分接口直接返回 beginTime) */
|
||||||
|
beginTime?: string
|
||||||
|
|
||||||
|
/** 计划结束(部分接口直接返回 endTime) */
|
||||||
|
endTime?: string
|
||||||
|
|
||||||
actualStartTime?: string | null
|
actualStartTime?: string | null
|
||||||
|
|
||||||
actualFinishTime?: string | null
|
actualFinishTime?: string | null
|
||||||
@ -238,9 +244,9 @@ export function processItemToEntity(
|
|||||||
|
|
||||||
orderItemId,
|
orderItemId,
|
||||||
|
|
||||||
beginTime: item.planStartTime,
|
beginTime: item.planStartTime || item.beginTime,
|
||||||
|
|
||||||
endTime: item.planFinishTime,
|
endTime: item.planFinishTime || item.endTime,
|
||||||
|
|
||||||
procurement: item.procurement,
|
procurement: item.procurement,
|
||||||
|
|
||||||
|
|||||||
@ -190,6 +190,11 @@
|
|||||||
v-for="(proc, idx) in sortedProcessList(order.processList)"
|
v-for="(proc, idx) in sortedProcessList(order.processList)"
|
||||||
:key="proc.planId ?? idx"
|
:key="proc.planId ?? idx"
|
||||||
:process="proc"
|
:process="proc"
|
||||||
|
:material-code="order.materialCode"
|
||||||
|
:order-code="order.orderCode"
|
||||||
|
:order-begin-time="order.beginTime"
|
||||||
|
:order-end-time="order.endTime"
|
||||||
|
:pro-workshop="order.proWorkshop"
|
||||||
:is-last="idx === (order.processList?.length ?? 0) - 1"
|
:is-last="idx === (order.processList?.length ?? 0) - 1"
|
||||||
:can-edit="hasPermission('biz:orderItem:edit')"
|
:can-edit="hasPermission('biz:orderItem:edit')"
|
||||||
:can-assign="hasPermission('biz:orderItem:assign')"
|
:can-assign="hasPermission('biz:orderItem:assign')"
|
||||||
@ -246,6 +251,11 @@
|
|||||||
v-for="(proc, idx) in (detailData.processList)"
|
v-for="(proc, idx) in (detailData.processList)"
|
||||||
:key="proc.planId ?? idx"
|
:key="proc.planId ?? idx"
|
||||||
:process="proc"
|
:process="proc"
|
||||||
|
:material-code="detailData.materialCode"
|
||||||
|
:order-code="detailData.orderCode"
|
||||||
|
:order-begin-time="detailData.beginTime"
|
||||||
|
:order-end-time="detailData.endTime"
|
||||||
|
:pro-workshop="detailData.proWorkshop"
|
||||||
:is-last="idx === (detailData.processList?.length ?? 0) - 1"
|
:is-last="idx === (detailData.processList?.length ?? 0) - 1"
|
||||||
:can-edit="hasPermission('biz:orderItem:edit')"
|
:can-edit="hasPermission('biz:orderItem:edit')"
|
||||||
:can-assign="hasPermission('biz:orderItem:assign')"
|
:can-assign="hasPermission('biz:orderItem:assign')"
|
||||||
@ -329,6 +339,16 @@
|
|||||||
<span>{{dispatchform.quantity}}</span>
|
<span>{{dispatchform.quantity}}</span>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
|
<n-grid :cols="2">
|
||||||
|
<n-gi>
|
||||||
|
<span class="pgClass">已完成:</span>
|
||||||
|
<span>{{dispatchform.completedQty ?? 0}}</span>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<span class="pgClass">本次待派:</span>
|
||||||
|
<span style="color: #2080f0; font-weight: 600">{{dispatchform.remainQty}}</span>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
<n-grid :cols="2">
|
<n-grid :cols="2">
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<span class="pgClass">开始时间:</span>
|
<span class="pgClass">开始时间:</span>
|
||||||
@ -609,8 +629,10 @@ const dispatchmodal = ref(false)
|
|||||||
const dispatchLoading = ref(false)
|
const dispatchLoading = ref(false)
|
||||||
const dispatchformRef = ref()
|
const dispatchformRef = ref()
|
||||||
const dispatchform = reactive<any>({
|
const dispatchform = reactive<any>({
|
||||||
id: '', name: '', beginTime: '', endTime: '', quantity: '',workCenterName:'',
|
id: '', name: '', beginTime: '', endTime: '', quantity: '', workCenterName: '',
|
||||||
list: [{ sectionId:'',deviceId:'', quantity: '' }],
|
completedQty: 0,
|
||||||
|
remainQty: 0,
|
||||||
|
list: [{ sectionId: '', deviceId: '', userList: '', quantity: '' }],
|
||||||
})
|
})
|
||||||
const dispatchrules = {}
|
const dispatchrules = {}
|
||||||
|
|
||||||
@ -1036,23 +1058,28 @@ async function handleSubmit() {
|
|||||||
function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
|
function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
|
||||||
const entity = processItemToEntity(process, order?.orderItemId)
|
const entity = processItemToEntity(process, order?.orderItemId)
|
||||||
|
|
||||||
|
const planQty = Number(entity.quantity) || 0
|
||||||
|
const completedQty = Number(process.completedQty) || 0
|
||||||
|
const remainQty = Math.max(0, planQty - completedQty)
|
||||||
dispatchmodal.value = true
|
dispatchmodal.value = true
|
||||||
dispatchformRef.value?.restoreValidation()
|
dispatchformRef.value?.restoreValidation()
|
||||||
dispatchform.id = entity.id
|
dispatchform.id = entity.id
|
||||||
dispatchform.name = entity.name
|
dispatchform.name = entity.name
|
||||||
dispatchform.beginTime = entity.beginTime
|
// 工序计划时间优先,没有则用订单头 beginTime/endTime
|
||||||
dispatchform.endTime = entity.endTime
|
dispatchform.beginTime = entity.beginTime || order?.beginTime || ''
|
||||||
|
dispatchform.endTime = entity.endTime || order?.endTime || ''
|
||||||
|
// quantity 保持工序计划总数,提交时不能改掉计划数量
|
||||||
dispatchform.quantity = entity.quantity
|
dispatchform.quantity = entity.quantity
|
||||||
|
dispatchform.completedQty = completedQty
|
||||||
|
dispatchform.remainQty = remainQty
|
||||||
dispatchform.orderItemId = entity.orderItemId
|
dispatchform.orderItemId = entity.orderItemId
|
||||||
dispatchform.sort = entity.sort
|
dispatchform.sort = entity.sort
|
||||||
dispatchform.workCenterName = entity.workCenterName
|
dispatchform.workCenterName = entity.workCenterName
|
||||||
dispatchform.list = [{ sectionId:'',deviceId:'', quantity: '' }]
|
dispatchform.list = [{ sectionId: '', deviceId: '', userList: '', quantity: remainQty || '' }]
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addpgnum() {
|
function addpgnum() {
|
||||||
dispatchform.list.push({ sectionId:'',deviceId:'', quantity: '' })
|
dispatchform.list.push({ sectionId: '', deviceId: '', userList: '', quantity: '' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function deletenum(index: number) {
|
function deletenum(index: number) {
|
||||||
@ -1061,18 +1088,27 @@ function deletenum(index: number) {
|
|||||||
|
|
||||||
function dispatchSubmit() {
|
function dispatchSubmit() {
|
||||||
let total = 0
|
let total = 0
|
||||||
dispatchform.list.forEach((n: any) => {
|
dispatchform.list.forEach((n: any) => {
|
||||||
total += Number(n.quantity) || 0
|
total += Number(n.quantity) || 0
|
||||||
})
|
})
|
||||||
|
const remainQty = Number(dispatchform.remainQty)
|
||||||
dispatchformRef.value?.validate((v: boolean) => {
|
if (remainQty <= 0) {
|
||||||
if (v) return
|
message.warning('当前工序已全部完成,无需再派工')
|
||||||
if (total !== Number(dispatchform.quantity)) {
|
return
|
||||||
message.error('派工总数量需等于生产总数', { duration: 4000 })
|
}
|
||||||
|
|
||||||
|
dispatchformRef.value?.validate((errors: any) => {
|
||||||
|
// Naive UI:有 errors 表示校验失败
|
||||||
|
if (errors) return
|
||||||
|
if (total !== remainQty) {
|
||||||
|
message.error(`派工总数量需等于待派数量 ${remainQty}(计划 ${dispatchform.quantity},已完成 ${dispatchform.completedQty ?? 0})`, {
|
||||||
|
duration: 4000,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchLoading.value = true
|
dispatchLoading.value = true
|
||||||
|
// 提交时 quantity 仍传计划总数,避免把工序计划数量改成待派数
|
||||||
orderProcessPlanApi.assignWork(dispatchform).then(() => {
|
orderProcessPlanApi.assignWork(dispatchform).then(() => {
|
||||||
message.success('派工成功')
|
message.success('派工成功')
|
||||||
dispatchmodal.value = false
|
dispatchmodal.value = false
|
||||||
|
|||||||
@ -2,7 +2,13 @@
|
|||||||
<div class="process-card-wrap">
|
<div class="process-card-wrap">
|
||||||
<div class="process-card" :class="themeClass">
|
<div class="process-card" :class="themeClass">
|
||||||
<div class="card-head">
|
<div class="card-head">
|
||||||
<span class="card-title">{{ process.processName || '-' }}</span>
|
<div class="card-title-block">
|
||||||
|
<span class="card-title">
|
||||||
|
<em v-if="process.operNumber != null" class="card-oper">{{ process.operNumber }}</em>
|
||||||
|
{{ process.processName || '-' }}
|
||||||
|
</span>
|
||||||
|
<span v-if="materialCode" class="card-material">{{ materialCode }}</span>
|
||||||
|
</div>
|
||||||
<n-tag size="small" :bordered="false" :type="statusTag.type">{{ statusTag.label }}</n-tag>
|
<n-tag size="small" :bordered="false" :type="statusTag.type">{{ statusTag.label }}</n-tag>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -39,22 +45,28 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-flow">
|
<div class="card-flow">
|
||||||
|
<div class="flow-item">
|
||||||
|
<span>转入</span>
|
||||||
|
<strong>{{ process.transferInQty ?? 0 }}</strong>
|
||||||
|
</div>
|
||||||
<div class="flow-item">
|
<div class="flow-item">
|
||||||
<span>剩余物料</span>
|
<span>剩余物料</span>
|
||||||
<strong>{{ remainQty }}</strong>
|
<strong>{{ remainQty }}</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flow-item">
|
<div class="flow-item">
|
||||||
<span>转下道</span>
|
<span>转出</span>
|
||||||
<strong>{{ process.transferOutQty ?? 0 }}</strong>
|
<strong>{{ process.transferOutQty ?? 0 }}</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-meta">
|
<div class="card-meta">
|
||||||
|
<div class="meta-line"><span>生产订单</span><em>{{ orderCode || '-' }}</em></div>
|
||||||
<div class="meta-line"><span>工单号</span><em>{{ process.workOrderCode || '-' }}</em></div>
|
<div class="meta-line"><span>工单号</span><em>{{ process.workOrderCode || '-' }}</em></div>
|
||||||
<div class="meta-line"><span>人员</span><em>{{ personnel }}</em></div>
|
<div class="meta-line"><span>人员</span><em>{{ personnel }}</em></div>
|
||||||
<div class="meta-line"><span>车间</span><em>{{ process.departmentName || '-' }}</em></div>
|
<div class="meta-line"><span>车间</span><em>{{ workshopText }}</em></div>
|
||||||
<div class="meta-line"><span>工位</span><em>{{ process.workCenterName || '-' }}</em></div>
|
<div class="meta-line"><span>工位</span><em>{{ process.workCenterName || '-' }}</em></div>
|
||||||
<div class="meta-line"><span>设备</span><em>-</em></div>
|
<div class="meta-line"><span>设备</span><em>{{ deviceText }}</em></div>
|
||||||
<div class="meta-line"><span>计划时间</span><em>{{ planTimeText }}</em></div>
|
<div class="meta-line"><span>计划时间</span><em>{{ planTimeText }}</em></div>
|
||||||
<div class="meta-line"><span>实际开始</span><em>{{ process.actualStartTime || '-' }}</em></div>
|
<div class="meta-line"><span>实际开始</span><em>{{ process.actualStartTime || '-' }}</em></div>
|
||||||
</div>
|
</div>
|
||||||
@ -110,6 +122,16 @@ import { PROCESS_STATUS_MAP, type ProcessPlanItemVO } from '@/api/orderProcessPl
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
process: ProcessPlanItemVO
|
process: ProcessPlanItemVO
|
||||||
|
/** 物料编码(订单头) */
|
||||||
|
materialCode?: string
|
||||||
|
/** 生产订单编号(订单头 orderCode) */
|
||||||
|
orderCode?: string
|
||||||
|
/** 订单计划开始(订单头 beginTime,工序无计划时间时回退) */
|
||||||
|
orderBeginTime?: string
|
||||||
|
/** 订单计划结束(订单头 endTime) */
|
||||||
|
orderEndTime?: string
|
||||||
|
/** 生产车间(订单头 proWorkshop) */
|
||||||
|
proWorkshop?: string
|
||||||
isLast?: boolean
|
isLast?: boolean
|
||||||
canEdit?: boolean
|
canEdit?: boolean
|
||||||
canAssign?: boolean
|
canAssign?: boolean
|
||||||
@ -171,15 +193,39 @@ const railColor = computed(() => {
|
|||||||
const personnel = computed(() => {
|
const personnel = computed(() => {
|
||||||
if (props.process.assignByName) return props.process.assignByName
|
if (props.process.assignByName) return props.process.assignByName
|
||||||
const list = props.process.assignWorkList
|
const list = props.process.assignWorkList
|
||||||
if (list?.length) return `${list.length} 人派工`
|
if (list?.length) {
|
||||||
|
const names = list
|
||||||
|
.map((a: any) => a.userName || a.userId)
|
||||||
|
.filter(Boolean)
|
||||||
|
if (names.length) return names.join('、')
|
||||||
|
return `${list.length} 人派工`
|
||||||
|
}
|
||||||
return '-'
|
return '-'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const workshopText = computed(() => {
|
||||||
|
return props.process.departmentName || props.proWorkshop || '-'
|
||||||
|
})
|
||||||
|
|
||||||
|
const deviceText = computed(() => {
|
||||||
|
const list = props.process.assignWorkList as any[] | undefined
|
||||||
|
if (!list?.length) return '-'
|
||||||
|
const devices = list
|
||||||
|
.map((a) => a.deviceName || a.deviceId)
|
||||||
|
.filter(Boolean)
|
||||||
|
return devices.length ? [...new Set(devices)].join('、') : '-'
|
||||||
|
})
|
||||||
|
|
||||||
const planTimeText = computed(() => {
|
const planTimeText = computed(() => {
|
||||||
const start = props.process.planStartTime
|
// 工序计划时间优先;没有则回退订单头 beginTime/endTime
|
||||||
const end = props.process.planFinishTime
|
const start = props.process.planStartTime || props.process.beginTime || props.orderBeginTime
|
||||||
|
const end = props.process.planFinishTime || props.process.endTime || props.orderEndTime
|
||||||
if (!start && !end) return '-'
|
if (!start && !end) return '-'
|
||||||
if (start && end) return `${start.slice(0, 16)} ~ ${end.slice(11, 16)}`
|
if (start && end) {
|
||||||
|
const startText = start.length >= 16 ? start.slice(0, 16) : start
|
||||||
|
const endText = end.length >= 16 ? end.slice(11, 16) : end
|
||||||
|
return `${startText} ~ ${endText}`
|
||||||
|
}
|
||||||
return start || end || '-'
|
return start || end || '-'
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -252,6 +298,29 @@ const planTimeText = computed(() => {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-oper {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-right: 4px;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title-block {
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-material {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.85;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.card-progress {
|
.card-progress {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@ -233,6 +233,16 @@
|
|||||||
<n-input v-model:value="dispatchform.quantity" disabled />
|
<n-input v-model:value="dispatchform.quantity" disabled />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-form-item label="已完成">
|
||||||
|
<n-input :value="String(dispatchform.completedQty ?? 0)" disabled />
|
||||||
|
</n-form-item>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<n-form-item label="本次待派">
|
||||||
|
<n-input :value="String(dispatchform.remainQty ?? 0)" disabled />
|
||||||
|
</n-form-item>
|
||||||
|
</n-gi>
|
||||||
<n-gi>
|
<n-gi>
|
||||||
<n-form-item label="开始时间">
|
<n-form-item label="开始时间">
|
||||||
<n-input v-model:value="dispatchform.beginTime" disabled />
|
<n-input v-model:value="dispatchform.beginTime" disabled />
|
||||||
@ -816,6 +826,8 @@ let dispatchform = reactive<any>({
|
|||||||
endTime:'',
|
endTime:'',
|
||||||
userid:'',
|
userid:'',
|
||||||
quantity:'',
|
quantity:'',
|
||||||
|
completedQty: 0,
|
||||||
|
remainQty: 0,
|
||||||
list:[{
|
list:[{
|
||||||
userId:'',
|
userId:'',
|
||||||
quantity:''
|
quantity:''
|
||||||
@ -866,17 +878,22 @@ function deletenum(index:any) {
|
|||||||
|
|
||||||
function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
|
function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
|
||||||
const entity = processItemToEntity(process, order?.orderItemId)
|
const entity = processItemToEntity(process, order?.orderItemId)
|
||||||
|
const planQty = Number(entity.quantity) || 0
|
||||||
|
const completedQty = Number(process.completedQty) || 0
|
||||||
|
const remainQty = Math.max(0, planQty - completedQty)
|
||||||
dispatchmodal.value = true
|
dispatchmodal.value = true
|
||||||
dispatchformRef.value?.restoreValidation()
|
dispatchformRef.value?.restoreValidation()
|
||||||
dispatchform.id = entity.id
|
dispatchform.id = entity.id
|
||||||
dispatchform.name = entity.name
|
dispatchform.name = entity.name
|
||||||
dispatchform.beginTime = entity.beginTime
|
dispatchform.beginTime = entity.beginTime || order?.beginTime || ''
|
||||||
dispatchform.endTime = entity.endTime
|
dispatchform.endTime = entity.endTime || order?.endTime || ''
|
||||||
dispatchform.quantity = entity.quantity
|
dispatchform.quantity = entity.quantity
|
||||||
|
dispatchform.completedQty = completedQty
|
||||||
|
dispatchform.remainQty = remainQty
|
||||||
dispatchform.userid = ''
|
dispatchform.userid = ''
|
||||||
dispatchform.list = [{
|
dispatchform.list = [{
|
||||||
userId: '',
|
userId: '',
|
||||||
quantity: '',
|
quantity: remainQty || '',
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,10 +902,15 @@ function dispatchSubmit() {
|
|||||||
dispatchform.list.forEach((n:any) => {
|
dispatchform.list.forEach((n:any) => {
|
||||||
total = n.quantity*1+total
|
total = n.quantity*1+total
|
||||||
})
|
})
|
||||||
|
const remainQty = Number(dispatchform.remainQty)
|
||||||
|
if (remainQty <= 0) {
|
||||||
|
message.warning('当前工序已全部完成,无需再派工')
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatchformRef.value?.validate((v:any) => {
|
dispatchformRef.value?.validate((v:any) => {
|
||||||
if(!v){
|
if(!v){
|
||||||
if(total != dispatchform.quantity){
|
if(total != remainQty){
|
||||||
message.error('派工总数量需等于生产总数',{
|
message.error(`派工总数量需等于待派数量 ${remainQty}(计划 ${dispatchform.quantity},已完成 ${dispatchform.completedQty ?? 0})`,{
|
||||||
duration:4000
|
duration:4000
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user