From 18b4399789c727d29a950a23301afeb4f3a42202 Mon Sep 17 00:00:00 2001 From: tzy <1042411602@qq.com> Date: Mon, 27 Jul 2026 15:40:42 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A5=E5=BA=8F?= =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=B4=BE=E5=B7=A5=E5=BE=85=E6=B4=BE=E6=95=B0?= =?UTF-8?q?=E9=87=8F=E4=B8=8E=E5=8D=A1=E7=89=87=E4=BF=A1=E6=81=AF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- src/api/orderProcessPlan.ts | 10 ++- src/views/biz/orderProcessPlan/board.vue | 66 ++++++++++---- .../components/ProcessCard.vue | 85 +++++++++++++++++-- src/views/biz/orderProcessPlan/index.vue | 32 +++++-- 4 files changed, 163 insertions(+), 30 deletions(-) diff --git a/src/api/orderProcessPlan.ts b/src/api/orderProcessPlan.ts index c53c3e1..9fdc400 100644 --- a/src/api/orderProcessPlan.ts +++ b/src/api/orderProcessPlan.ts @@ -88,6 +88,12 @@ export interface ProcessPlanItemVO { planFinishTime?: string + /** 计划开始(部分接口直接返回 beginTime) */ + beginTime?: string + + /** 计划结束(部分接口直接返回 endTime) */ + endTime?: string + actualStartTime?: string | null actualFinishTime?: string | null @@ -238,9 +244,9 @@ export function processItemToEntity( orderItemId, - beginTime: item.planStartTime, + beginTime: item.planStartTime || item.beginTime, - endTime: item.planFinishTime, + endTime: item.planFinishTime || item.endTime, procurement: item.procurement, diff --git a/src/views/biz/orderProcessPlan/board.vue b/src/views/biz/orderProcessPlan/board.vue index a2728f5..975c374 100644 --- a/src/views/biz/orderProcessPlan/board.vue +++ b/src/views/biz/orderProcessPlan/board.vue @@ -190,6 +190,11 @@ v-for="(proc, idx) in sortedProcessList(order.processList)" :key="proc.planId ?? idx" :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" :can-edit="hasPermission('biz:orderItem:edit')" :can-assign="hasPermission('biz:orderItem:assign')" @@ -246,6 +251,11 @@ v-for="(proc, idx) in (detailData.processList)" :key="proc.planId ?? idx" :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" :can-edit="hasPermission('biz:orderItem:edit')" :can-assign="hasPermission('biz:orderItem:assign')" @@ -329,6 +339,16 @@ {{dispatchform.quantity}} + + + 已完成: + {{dispatchform.completedQty ?? 0}} + + + 本次待派: + {{dispatchform.remainQty}} + + 开始时间: @@ -609,8 +629,10 @@ const dispatchmodal = ref(false) const dispatchLoading = ref(false) const dispatchformRef = ref() const dispatchform = reactive({ - id: '', name: '', beginTime: '', endTime: '', quantity: '',workCenterName:'', - list: [{ sectionId:'',deviceId:'', quantity: '' }], + id: '', name: '', beginTime: '', endTime: '', quantity: '', workCenterName: '', + completedQty: 0, + remainQty: 0, + list: [{ sectionId: '', deviceId: '', userList: '', quantity: '' }], }) const dispatchrules = {} @@ -1036,23 +1058,28 @@ async function handleSubmit() { function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) { 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 dispatchformRef.value?.restoreValidation() dispatchform.id = entity.id dispatchform.name = entity.name - dispatchform.beginTime = entity.beginTime - dispatchform.endTime = entity.endTime + // 工序计划时间优先,没有则用订单头 beginTime/endTime + dispatchform.beginTime = entity.beginTime || order?.beginTime || '' + dispatchform.endTime = entity.endTime || order?.endTime || '' + // quantity 保持工序计划总数,提交时不能改掉计划数量 dispatchform.quantity = entity.quantity + dispatchform.completedQty = completedQty + dispatchform.remainQty = remainQty dispatchform.orderItemId = entity.orderItemId dispatchform.sort = entity.sort dispatchform.workCenterName = entity.workCenterName - dispatchform.list = [{ sectionId:'',deviceId:'', quantity: '' }] - - + dispatchform.list = [{ sectionId: '', deviceId: '', userList: '', quantity: remainQty || '' }] } function addpgnum() { - dispatchform.list.push({ sectionId:'',deviceId:'', quantity: '' }) + dispatchform.list.push({ sectionId: '', deviceId: '', userList: '', quantity: '' }) } function deletenum(index: number) { @@ -1061,18 +1088,27 @@ function deletenum(index: number) { function dispatchSubmit() { let total = 0 - dispatchform.list.forEach((n: any) => { + dispatchform.list.forEach((n: any) => { total += Number(n.quantity) || 0 }) - - dispatchformRef.value?.validate((v: boolean) => { - if (v) return - if (total !== Number(dispatchform.quantity)) { - message.error('派工总数量需等于生产总数', { duration: 4000 }) + const remainQty = Number(dispatchform.remainQty) + if (remainQty <= 0) { + message.warning('当前工序已全部完成,无需再派工') + return + } + + 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 } - + dispatchLoading.value = true + // 提交时 quantity 仍传计划总数,避免把工序计划数量改成待派数 orderProcessPlanApi.assignWork(dispatchform).then(() => { message.success('派工成功') dispatchmodal.value = false diff --git a/src/views/biz/orderProcessPlan/components/ProcessCard.vue b/src/views/biz/orderProcessPlan/components/ProcessCard.vue index d4d0094..a8c1950 100644 --- a/src/views/biz/orderProcessPlan/components/ProcessCard.vue +++ b/src/views/biz/orderProcessPlan/components/ProcessCard.vue @@ -2,7 +2,13 @@
- {{ process.processName || '-' }} +
+ + {{ process.operNumber }} + {{ process.processName || '-' }} + + {{ materialCode }} +
{{ statusTag.label }}
@@ -39,22 +45,28 @@
+
+ 转入 + {{ process.transferInQty ?? 0 }} +
剩余物料 {{ remainQty }}
+
- 转下道 + 转出 {{ process.transferOutQty ?? 0 }}
+
生产订单{{ orderCode || '-' }}
工单号{{ process.workOrderCode || '-' }}
人员{{ personnel }}
-
车间{{ process.departmentName || '-' }}
+
车间{{ workshopText }}
工位{{ process.workCenterName || '-' }}
-
设备-
+
设备{{ deviceText }}
计划时间{{ planTimeText }}
实际开始{{ process.actualStartTime || '-' }}
@@ -110,6 +122,16 @@ import { PROCESS_STATUS_MAP, type ProcessPlanItemVO } from '@/api/orderProcessPl const props = defineProps<{ process: ProcessPlanItemVO + /** 物料编码(订单头) */ + materialCode?: string + /** 生产订单编号(订单头 orderCode) */ + orderCode?: string + /** 订单计划开始(订单头 beginTime,工序无计划时间时回退) */ + orderBeginTime?: string + /** 订单计划结束(订单头 endTime) */ + orderEndTime?: string + /** 生产车间(订单头 proWorkshop) */ + proWorkshop?: string isLast?: boolean canEdit?: boolean canAssign?: boolean @@ -171,15 +193,39 @@ const railColor = computed(() => { const personnel = computed(() => { if (props.process.assignByName) return props.process.assignByName 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 '-' }) +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 start = props.process.planStartTime - const end = props.process.planFinishTime + // 工序计划时间优先;没有则回退订单头 beginTime/endTime + 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 `${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 || '-' }) @@ -252,6 +298,29 @@ const planTimeText = computed(() => { 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 { display: flex; justify-content: center; diff --git a/src/views/biz/orderProcessPlan/index.vue b/src/views/biz/orderProcessPlan/index.vue index efdb07a..9f03e54 100644 --- a/src/views/biz/orderProcessPlan/index.vue +++ b/src/views/biz/orderProcessPlan/index.vue @@ -233,6 +233,16 @@ + + + + + + + + + + @@ -816,6 +826,8 @@ let dispatchform = reactive({ endTime:'', userid:'', quantity:'', + completedQty: 0, + remainQty: 0, list:[{ userId:'', quantity:'' @@ -866,17 +878,22 @@ function deletenum(index:any) { function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) { 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 dispatchformRef.value?.restoreValidation() dispatchform.id = entity.id dispatchform.name = entity.name - dispatchform.beginTime = entity.beginTime - dispatchform.endTime = entity.endTime + dispatchform.beginTime = entity.beginTime || order?.beginTime || '' + dispatchform.endTime = entity.endTime || order?.endTime || '' dispatchform.quantity = entity.quantity + dispatchform.completedQty = completedQty + dispatchform.remainQty = remainQty dispatchform.userid = '' dispatchform.list = [{ userId: '', - quantity: '', + quantity: remainQty || '', }] } @@ -885,10 +902,15 @@ function dispatchSubmit() { dispatchform.list.forEach((n:any) => { total = n.quantity*1+total }) + const remainQty = Number(dispatchform.remainQty) + if (remainQty <= 0) { + message.warning('当前工序已全部完成,无需再派工') + return + } dispatchformRef.value?.validate((v:any) => { if(!v){ - if(total != dispatchform.quantity){ - message.error('派工总数量需等于生产总数',{ + if(total != remainQty){ + message.error(`派工总数量需等于待派数量 ${remainQty}(计划 ${dispatchform.quantity},已完成 ${dispatchform.completedQty ?? 0})`,{ duration:4000 }) }else{ From fa3a7599d044488e910fc9a873f9986f6af61aee Mon Sep 17 00:00:00 2001 From: shaoleiliu-netizen123 <480188199@qq.com> Date: Fri, 31 Jul 2026 09:51:41 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=9D=E4=BF=AE=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mes-ui/src/api/concessionApply.ts | 82 ---------- mes-ui/src/api/maintenanceRecord.ts | 80 ---------- mes-ui/src/api/outsourcing.ts | 100 ------------- src/api/exceptionFilter.ts | 71 +++++++++ src/api/message.ts | 1 + src/components/ErrorReportModal.vue | 29 ++-- src/layout/index.vue | 13 -- .../views/biz/exceptionFilter}/index.vue | 141 ++++++++---------- src/views/biz/qualityItem/index.vue | 23 +-- 9 files changed, 160 insertions(+), 380 deletions(-) delete mode 100644 mes-ui/src/api/concessionApply.ts delete mode 100644 mes-ui/src/api/maintenanceRecord.ts delete mode 100644 mes-ui/src/api/outsourcing.ts create mode 100644 src/api/exceptionFilter.ts rename {mes-ui/src/views/biz/concessionApply => src/views/biz/exceptionFilter}/index.vue (67%) diff --git a/mes-ui/src/api/concessionApply.ts b/mes-ui/src/api/concessionApply.ts deleted file mode 100644 index 042db53..0000000 --- a/mes-ui/src/api/concessionApply.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { request } from '@/utils/request' - -// 让步接收申请表 类型定义 -export interface ConcessionApply { - id?: number - - qcId?: number - - concessionQty?: number - - applyRemark?: string - - applyContent?: string - - applyFile?: string - - applyUserId?: number - - deptId?: number - - instanceId?: string - - approveStatus?: number - - createTime?: string - - updateTime?: string - -} - -// 让步接收申请表 API -export const concessionApplyApi = { - // 分页查询 - page(params: { page: number; pageSize: number; id?: number }) { - return request({ url: '/biz/concessionApply/page', method: 'get', params }) - }, - - // 获取详情 - detail(id: string) { - return request({ url: `/biz/concessionApply/${id}`, method: 'get' }) - }, - - // 新增 - create(data: ConcessionApply) { - return request({ url: '/biz/concessionApply', method: 'post', data }) - }, - - // 修改 - update(data: ConcessionApply) { - return request({ url: '/biz/concessionApply', method: 'put', data }) - }, - - // 删除 - delete(ids: string[]) { - return request({ url: `/biz/concessionApply/${ids.join(',')}`, method: 'delete' }) - }, - - // 导出 - export(params?: { ids?: string[]; id?: number }) { - const p: Record = {} - if (params?.ids?.length) p.ids = params.ids.join(',') - if (params?.id !== undefined && params?.id !== null) p.id = params.id - return request({ url: `/biz/concessionApply/export`, method: 'get', params: p, responseType: 'blob' }) - }, - - // 导入 - importData(file: File) { - const formData = new FormData() - formData.append('file', file) - return request<{ success: number; fail: number; errors: string[] }>({ - url: `/biz/concessionApply/import`, - method: 'post', - data: formData, - headers: { 'Content-Type': 'multipart/form-data' } - }) - }, - - // 下载导入模板 - downloadTemplate() { - return request({ url: `/biz/concessionApply/template`, method: 'get', responseType: 'blob' }) - } -} diff --git a/mes-ui/src/api/maintenanceRecord.ts b/mes-ui/src/api/maintenanceRecord.ts deleted file mode 100644 index 3218c32..0000000 --- a/mes-ui/src/api/maintenanceRecord.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { request } from '@/utils/request' - -// MES设备维修保养记录表 类型定义 -export interface MaintenanceRecord { - recordId?: string - - equipmentId?: string - - recordType?: string - - itemContent?: string - - handleContent?: string - - executorId?: number - - startTime?: string - - endTime?: string - - recordStatus?: string - - createTime?: string - - updateTime?: string - -} - -// MES设备维修保养记录表 API -export const maintenanceRecordApi = { - // 分页查询 - page(params: { page: number; pageSize: number; recordId?: string }) { - return request({ url: '/biz/maintenanceRecord/page', method: 'get', params }) - }, - - // 获取详情 - detail(recordId: string) { - return request({ url: `/biz/maintenanceRecord/${recordId}`, method: 'get' }) - }, - - // 新增 - create(data: MaintenanceRecord) { - return request({ url: '/biz/maintenanceRecord', method: 'post', data }) - }, - - // 修改 - update(data: MaintenanceRecord) { - return request({ url: '/biz/maintenanceRecord', method: 'put', data }) - }, - - // 删除 - delete(recordIds: string[]) { - return request({ url: `/biz/maintenanceRecord/${recordIds.join(',')}`, method: 'delete' }) - }, - - // 导出 - export(params?: { ids?: string[]; recordId?: string }) { - const p: Record = {} - if (params?.ids?.length) p.ids = params.ids.join(',') - if (params?.recordId !== undefined && params?.recordId !== null) p.recordId = params.recordId - return request({ url: `/biz/maintenanceRecord/export`, method: 'get', params: p, responseType: 'blob' }) - }, - - // 导入 - importData(file: File) { - const formData = new FormData() - formData.append('file', file) - return request<{ success: number; fail: number; errors: string[] }>({ - url: `/biz/maintenanceRecord/import`, - method: 'post', - data: formData, - headers: { 'Content-Type': 'multipart/form-data' } - }) - }, - - // 下载导入模板 - downloadTemplate() { - return request({ url: `/biz/maintenanceRecord/template`, method: 'get', responseType: 'blob' }) - } -} diff --git a/mes-ui/src/api/outsourcing.ts b/mes-ui/src/api/outsourcing.ts deleted file mode 100644 index cd1e044..0000000 --- a/mes-ui/src/api/outsourcing.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { request } from '@/utils/request' - -// 委外记录表 类型定义 -export interface Outsourcing { - id?: number - - name?: string - - code?: string - - businessType?: number - - businessId?: number - - businessCode?: string - - orderItemId?: number - - quantity?: number - - supplierId?: number - - supplierName?: string - - unitPrice?: string - - totalAmount?: string - - beginPreparationTime?: string - - endPreparationTime?: string - - beginTime?: string - - endTime?: string - - remark?: string - - createTime?: string - - createBy?: string - - overdue?: number - -} - -// 委外记录表 API -export const outsourcingApi = { - // 分页查询 - page(params: { page: number; pageSize: number; id?: number; name?: string; businessType?: number }) { - return request({ url: '/biz/outsourcing/page', method: 'get', params }) - }, - - // 获取详情 - detail(id: string) { - return request({ url: `/biz/outsourcing/${id}`, method: 'get' }) - }, - - // 新增 - create(data: Outsourcing) { - return request({ url: '/biz/outsourcing', method: 'post', data }) - }, - - // 修改 - update(data: Outsourcing) { - return request({ url: '/biz/outsourcing', method: 'put', data }) - }, - - // 删除 - delete(ids: string[]) { - return request({ url: `/biz/outsourcing/${ids.join(',')}`, method: 'delete' }) - }, - - // 导出 - export(params?: { ids?: string[]; id?: number; name?: string; businessType?: number }) { - const p: Record = {} - if (params?.ids?.length) p.ids = params.ids.join(',') - if (params?.id !== undefined && params?.id !== null) p.id = params.id - if (params?.name !== undefined && params?.name !== null) p.name = params.name - if (params?.businessType !== undefined && params?.businessType !== null) p.businessType = params.businessType - return request({ url: `/biz/outsourcing/export`, method: 'get', params: p, responseType: 'blob' }) - }, - - // 导入 - importData(file: File) { - const formData = new FormData() - formData.append('file', file) - return request<{ success: number; fail: number; errors: string[] }>({ - url: `/biz/outsourcing/import`, - method: 'post', - data: formData, - headers: { 'Content-Type': 'multipart/form-data' } - }) - }, - - // 下载导入模板 - downloadTemplate() { - return request({ url: `/biz/outsourcing/template`, method: 'get', responseType: 'blob' }) - } -} diff --git a/src/api/exceptionFilter.ts b/src/api/exceptionFilter.ts new file mode 100644 index 0000000..eea0f55 --- /dev/null +++ b/src/api/exceptionFilter.ts @@ -0,0 +1,71 @@ +import { request } from '@/utils/request' + +// 异常过滤表 类型定义 +export interface ExceptionFilter { + id?: number + + title?: string + + filterCondition?: string + + description?: string + + status?: 0 + + deleted?: number + +} + +// 异常过滤表 API +export const exceptionFilterApi = { + // 分页查询 + page(params: { page: number; pageSize: number; id?: number; status?: number }) { + return request({ url: '/biz/exceptionFilter/page', method: 'get', params }) + }, + + // 获取详情 + detail(id: string) { + return request({ url: `/biz/exceptionFilter/${id}`, method: 'get' }) + }, + + // 新增 + create(data: ExceptionFilter) { + return request({ url: '/biz/exceptionFilter', method: 'post', data }) + }, + + // 修改 + update(data: ExceptionFilter) { + return request({ url: '/biz/exceptionFilter', method: 'put', data }) + }, + + // 删除 + delete(ids: string[]) { + return request({ url: `/biz/exceptionFilter/${ids.join(',')}`, method: 'delete' }) + }, + + // 导出 + export(params?: { ids?: string[]; id?: number; status?: number }) { + const p: Record = {} + if (params?.ids?.length) p.ids = params.ids.join(',') + if (params?.id !== undefined && params?.id !== null) p.id = params.id + if (params?.status !== undefined && params?.status !== null) p.status = params.status + return request({ url: `/biz/exceptionFilter/export`, method: 'get', params: p, responseType: 'blob' }) + }, + + // 导入 + importData(file: File) { + const formData = new FormData() + formData.append('file', file) + return request<{ success: number; fail: number; errors: string[] }>({ + url: `/biz/exceptionFilter/import`, + method: 'post', + data: formData, + headers: { 'Content-Type': 'multipart/form-data' } + }) + }, + + // 下载导入模板 + downloadTemplate() { + return request({ url: `/biz/exceptionFilter/template`, method: 'get', responseType: 'blob' }) + } +} diff --git a/src/api/message.ts b/src/api/message.ts index 1584360..ee64d78 100644 --- a/src/api/message.ts +++ b/src/api/message.ts @@ -19,6 +19,7 @@ export interface SysNotice { errorNotificationId?:number, filler?:number, filingStatus?:number, + deviceName?:string } export interface NoticeChannelOption { diff --git a/src/components/ErrorReportModal.vue b/src/components/ErrorReportModal.vue index 35d2b19..c41425d 100644 --- a/src/components/ErrorReportModal.vue +++ b/src/components/ErrorReportModal.vue @@ -2,7 +2,6 @@ import {onMounted, ref, watch} from "vue"; import { Notifications } from '@vicons/ionicons5' -import { ErrorNotification } from '@/api/errorNotification.ts' import {} from '@/api/system.ts' import {noticeApi, SysNotice} from '@/api/message' import type {FormInst} from "naive-ui"; @@ -12,7 +11,7 @@ const emit = defineEmits<{ const props = defineProps<{ show: boolean - errorNotifiaction:ErrorNotification, + notice:SysNotice, }>() @@ -72,7 +71,7 @@ watch(showModal, (val) => { async function handleSubmit() { try { await formRef.value?.validate() - formData.value.id = props.errorNotifiaction.noticeId + formData.value.id = props.notice.id formData.value.filingStatus = 1 //修改通知表 noticeApi.update({ @@ -114,7 +113,7 @@ async function handleSubmit() {