-
{{ item.code }}
-
{{ item.itemName }}
+
+
+
+
+
任务编号:{{ selectedItem.code || '-' }}
+
任务名称:{{ selectedItem.name || '-' }}
+
工序:{{ selectedItem.processName || '-' }}
+
工作站:{{ selectedItem.workstationName || '-' }}
+
物料:{{ selectedItem.itemName || '-' }}
+
规格:{{ selectedItem.itemSpecification || '-' }}
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/mes/pro/task/data.ts b/apps/web-antd/src/views/mes/pro/task/data.ts
new file mode 100644
index 000000000..c29921b81
--- /dev/null
+++ b/apps/web-antd/src/views/mes/pro/task/data.ts
@@ -0,0 +1,112 @@
+import type { VbenFormSchema } from '#/adapter/form';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MesProTaskApi } from '#/api/mes/pro/task';
+
+import { markRaw } from 'vue';
+
+import { DICT_TYPE } from '@vben/constants';
+
+import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
+import { ProProcessSelect } from '#/views/mes/pro/process/components';
+import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
+
+/** 任务选择弹窗的搜索表单 */
+export function useTaskSelectGridFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'workOrderId',
+ label: '生产工单',
+ component: markRaw(ProWorkOrderSelect),
+ componentProps: {
+ allowClear: true,
+ placeholder: '请选择生产工单',
+ },
+ },
+ {
+ fieldName: 'processId',
+ label: '所属工序',
+ component: markRaw(ProProcessSelect),
+ componentProps: {
+ allowClear: true,
+ placeholder: '请选择工序',
+ },
+ },
+ {
+ fieldName: 'workstationId',
+ label: '工作站',
+ component: markRaw(MdWorkstationSelect),
+ componentProps: {
+ allowClear: true,
+ placeholder: '请选择工作站',
+ },
+ },
+ {
+ fieldName: 'code',
+ label: '任务编号',
+ component: 'Input',
+ componentProps: {
+ allowClear: true,
+ placeholder: '请输入任务编号',
+ },
+ },
+ {
+ fieldName: 'name',
+ label: '任务名称',
+ component: 'Input',
+ componentProps: {
+ allowClear: true,
+ placeholder: '请输入任务名称',
+ },
+ },
+ ];
+}
+
+/** 任务选择弹窗的字段 */
+export function useTaskSelectGridColumns(
+ multiple = false,
+): VxeTableGridOptions
['columns'] {
+ return [
+ { type: multiple ? 'checkbox' : 'radio', width: 50 },
+ { field: 'code', title: '任务编号', width: 180 },
+ { field: 'name', title: '任务名称', minWidth: 140 },
+ { field: 'workstationCode', title: '工作站编码', width: 140 },
+ { field: 'workstationName', title: '工作站名称', width: 140 },
+ { field: 'processName', title: '工序', width: 120 },
+ {
+ field: 'checkFlag',
+ title: '是否质检',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
+ },
+ },
+ { field: 'itemCode', title: '物料编码', width: 140 },
+ { field: 'itemName', title: '物料名称', width: 140 },
+ { field: 'itemSpecification', title: '规格型号', width: 120 },
+ { field: 'quantity', title: '排产数量', width: 100 },
+ { field: 'producedQuantity', title: '已生产数量', width: 110 },
+ {
+ field: 'startTime',
+ title: '开始生产时间',
+ width: 170,
+ formatter: 'formatDateTime',
+ },
+ { field: 'duration', title: '生产时长', width: 100 },
+ {
+ field: 'endTime',
+ title: '预计完成时间',
+ width: 170,
+ formatter: 'formatDateTime',
+ },
+ {
+ field: 'status',
+ title: '任务状态',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.MES_PRO_TASK_STATUS },
+ },
+ },
+ ];
+}
diff --git a/apps/web-antd/src/views/mes/utils/constants.ts b/apps/web-antd/src/views/mes/utils/constants.ts
index 2fd061dc6..668cf7240 100644
--- a/apps/web-antd/src/views/mes/utils/constants.ts
+++ b/apps/web-antd/src/views/mes/utils/constants.ts
@@ -166,10 +166,10 @@ export const MesProTaskStatusEnum = {
/** MES 生产报工状态枚举 */
export const MesProFeedbackStatusEnum = {
PREPARE: MesOrderStatusConstants.DRAFT,
- CONFIRMED: MesOrderStatusConstants.CONFIRMED,
APPROVING: MesOrderStatusConstants.APPROVING,
+ UNCHECK: MesOrderStatusConstants.APPROVED,
FINISHED: MesOrderStatusConstants.FINISHED,
- CANCELLED: MesOrderStatusConstants.CANCELLED,
+ CANCELED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 流转卡状态枚举 */
diff --git a/apps/web-ele/src/api/mes/pro/feedback/index.ts b/apps/web-ele/src/api/mes/pro/feedback/index.ts
new file mode 100644
index 000000000..21a988ba8
--- /dev/null
+++ b/apps/web-ele/src/api/mes/pro/feedback/index.ts
@@ -0,0 +1,113 @@
+import type { PageParam, PageResult } from '@vben/request';
+
+import { requestClient } from '#/api/request';
+
+export namespace MesProFeedbackApi {
+ /** MES 生产报工 */
+ export interface Feedback {
+ id?: number;
+ code?: string; // 报工单编号
+ type?: number; // 报工类型
+ channel?: string; // 报工途径
+ feedbackTime?: number; // 报工时间
+ workstationId?: number; // 工作站编号
+ workstationCode?: string; // 工作站编码
+ workstationName?: string; // 工作站名称
+ routeId?: number; // 工艺路线编号
+ routeCode?: string; // 工艺路线编码
+ processId?: number; // 工序编号
+ processCode?: string; // 工序编码
+ processName?: string; // 工序名称
+ checkFlag?: boolean; // 是否需要检验
+ workOrderId?: number; // 生产工单编号
+ workOrderCode?: string; // 工单编码
+ workOrderName?: string; // 工单名称
+ taskId?: number; // 生产任务编号
+ taskCode?: string; // 任务编码
+ itemId?: number; // 产品物料编号
+ itemCode?: string; // 物料编码
+ itemName?: string; // 物料名称
+ itemSpecification?: string; // 规格型号
+ unitMeasureId?: number; // 单位编号
+ unitMeasureName?: string; // 单位名称
+ expireDate?: number; // 过期日期
+ scheduledQuantity?: number; // 排产数量
+ feedbackQuantity?: number; // 本次报工数量
+ qualifiedQuantity?: number; // 合格品数量
+ unqualifiedQuantity?: number; // 不良品数量
+ uncheckQuantity?: number; // 待检测数量
+ laborScrapQuantity?: number; // 工废数量
+ materialScrapQuantity?: number; // 料废数量
+ otherScrapQuantity?: number; // 其他废品数量
+ feedbackUserId?: number; // 报工用户编号
+ feedbackUserNickname?: string; // 报工人昵称
+ approveUserId?: number; // 审核用户编号
+ approveUserNickname?: string; // 审核人昵称
+ status?: number; // 状态
+ remark?: string; // 备注
+ creator?: string; // 创建人
+ createTime?: number; // 创建时间
+ }
+
+ /** MES 生产报工分页查询参数 */
+ export interface PageParams extends PageParam {
+ code?: string;
+ type?: number;
+ workOrderId?: number;
+ itemId?: number;
+ feedbackUserId?: number;
+ creator?: string;
+ status?: number;
+ feedbackTime?: string[];
+ }
+}
+
+/** 查询生产报工分页 */
+export function getFeedbackPage(params: MesProFeedbackApi.PageParams) {
+ return requestClient.get>(
+ '/mes/pro/feedback/page',
+ { params },
+ );
+}
+
+/** 查询生产报工详情 */
+export function getFeedback(id: number) {
+ return requestClient.get(
+ `/mes/pro/feedback/get?id=${id}`,
+ );
+}
+
+/** 新增生产报工 */
+export function createFeedback(data: MesProFeedbackApi.Feedback) {
+ return requestClient.post('/mes/pro/feedback/create', data);
+}
+
+/** 修改生产报工 */
+export function updateFeedback(data: MesProFeedbackApi.Feedback) {
+ return requestClient.put('/mes/pro/feedback/update', data);
+}
+
+/** 删除生产报工 */
+export function deleteFeedback(id: number) {
+ return requestClient.delete(`/mes/pro/feedback/delete?id=${id}`);
+}
+
+/** 导出生产报工 Excel */
+export function exportFeedback(params: Partial) {
+ return requestClient.download('/mes/pro/feedback/export-excel', { params });
+}
+
+/** 提交生产报工 */
+export function submitFeedback(id: number) {
+ return requestClient.put(`/mes/pro/feedback/submit?id=${id}`);
+}
+
+/** 驳回生产报工 */
+export function rejectFeedback(id: number) {
+ return requestClient.put(`/mes/pro/feedback/reject?id=${id}`);
+}
+
+/** 审批生产报工(返回是否已审批完成) */
+export function approveFeedback(id: number) {
+ return requestClient.put(`/mes/pro/feedback/approve?id=${id}`);
+}
diff --git a/apps/web-ele/src/api/mes/pro/task/index.ts b/apps/web-ele/src/api/mes/pro/task/index.ts
new file mode 100644
index 000000000..d7bfd2f5e
--- /dev/null
+++ b/apps/web-ele/src/api/mes/pro/task/index.ts
@@ -0,0 +1,68 @@
+import type { PageParam, PageResult } from '@vben/request';
+
+import { requestClient } from '#/api/request';
+
+export namespace MesProTaskApi {
+ /** MES 生产任务 */
+ export interface Task {
+ id?: number;
+ code?: string; // 任务编码
+ name?: string; // 任务名称
+ workOrderId?: number; // 生产工单编号
+ workOrderCode?: string; // 工单编码
+ workOrderName?: string; // 工单名称
+ workstationId?: number; // 工作站编号
+ workstationCode?: string; // 工作站编码
+ workstationName?: string; // 工作站名称
+ routeId?: number; // 工艺路线编号
+ processId?: number; // 工序编号
+ processName?: string; // 工序名称
+ itemId?: number; // 产品物料编号
+ itemCode?: string; // 产品编码
+ itemName?: string; // 产品名称
+ itemSpecification?: string; // 规格型号
+ unitMeasureId?: number; // 单位编号
+ unitMeasureName?: string; // 单位名称
+ quantity?: number; // 排产数量
+ producedQuantity?: number; // 已生产数量
+ qualifyQuantity?: number; // 合格品数量
+ unqualifyQuantity?: number; // 不良品数量
+ changedQuantity?: number; // 调整数量
+ clientId?: number; // 客户编号
+ clientName?: string; // 客户名称
+ startTime?: number; // 开始生产时间
+ endTime?: number; // 结束生产时间
+ duration?: number; // 生产时长(工作日,1=8小时)
+ requestDate?: number; // 需求日期(从工单查)
+ finishDate?: number; // 完成日期
+ cancelDate?: number; // 取消日期
+ colorCode?: string; // 甘特图显示颜色
+ status?: number; // 任务状态
+ checkFlag?: boolean; // 是否质检(派生自工艺路线工序)
+ remark?: string; // 备注
+ }
+
+ /** MES 生产任务分页查询参数 */
+ export interface PageParams extends PageParam {
+ code?: string;
+ name?: string;
+ workOrderId?: number;
+ workstationId?: number;
+ itemId?: number;
+ statuses?: number[];
+ status?: number;
+ }
+}
+
+/** 查询生产任务分页 */
+export function getTaskPage(params: MesProTaskApi.PageParams) {
+ return requestClient.get>(
+ '/mes/pro/task/page',
+ { params },
+ );
+}
+
+/** 查询生产任务详情 */
+export function getTask(id: number) {
+ return requestClient.get(`/mes/pro/task/get?id=${id}`);
+}
diff --git a/apps/web-ele/src/api/mes/wm/itemconsume/line/index.ts b/apps/web-ele/src/api/mes/wm/itemconsume/line/index.ts
new file mode 100644
index 000000000..2a353b766
--- /dev/null
+++ b/apps/web-ele/src/api/mes/wm/itemconsume/line/index.ts
@@ -0,0 +1,37 @@
+import type { PageParam, PageResult } from '@vben/request';
+
+import { requestClient } from '#/api/request';
+
+export namespace MesWmItemConsumeLineApi {
+ /** MES 物料消耗行 */
+ export interface ItemConsumeLine {
+ id?: number;
+ feedbackId?: number; // 报工编号
+ itemId?: number; // 物料编号
+ itemCode?: string; // 物资编码
+ itemName?: string; // 物资名称
+ specification?: string; // 规格型号
+ unitId?: number; // 单位编号
+ unitName?: string; // 单位
+ quantity?: number; // 消耗数量
+ batchCode?: string; // 批次号
+ locationId?: number; // 库位编号
+ locationName?: string; // 库位名称
+ remark?: string; // 备注
+ }
+
+ /** MES 物料消耗行分页查询参数 */
+ export interface PageParams extends PageParam {
+ feedbackId?: number;
+ }
+}
+
+/** 查询物料消耗行分页 */
+export function getItemConsumeLinePage(
+ params: MesWmItemConsumeLineApi.PageParams,
+) {
+ return requestClient.get>(
+ '/mes/wm/item-consume-line/page',
+ { params },
+ );
+}
diff --git a/apps/web-ele/src/api/mes/wm/productproduce/line/index.ts b/apps/web-ele/src/api/mes/wm/productproduce/line/index.ts
new file mode 100644
index 000000000..ab3f49f29
--- /dev/null
+++ b/apps/web-ele/src/api/mes/wm/productproduce/line/index.ts
@@ -0,0 +1,37 @@
+import type { PageParam, PageResult } from '@vben/request';
+
+import { requestClient } from '#/api/request';
+
+export namespace MesWmProductProduceLineApi {
+ /** MES 产品产出行 */
+ export interface ProductProduceLine {
+ id?: number;
+ feedbackId?: number; // 报工编号
+ itemId?: number; // 物料编号
+ itemCode?: string; // 物资编码
+ itemName?: string; // 物资名称
+ specification?: string; // 规格型号
+ unitMeasureId?: number; // 单位编号
+ unitMeasureName?: string; // 单位
+ quantity?: number; // 产出数量
+ batchCode?: string; // 批次号
+ qualityStatus?: number; // 质量状态
+ locationId?: number; // 库位编号
+ locationName?: string; // 库位名称
+ remark?: string; // 备注
+ }
+
+ /** MES 产品产出行分页查询参数 */
+ export interface PageParams extends PageParam {
+ feedbackId?: number;
+ }
+}
+
+/** 查询产品产出行分页 */
+export function getProductProduceLinePage(
+ params: MesWmProductProduceLineApi.PageParams,
+) {
+ return requestClient.get<
+ PageResult
+ >('/mes/wm/product-produce-line/page', { params });
+}
diff --git a/apps/web-ele/src/views/mes/pro/feedback/data.ts b/apps/web-ele/src/views/mes/pro/feedback/data.ts
new file mode 100644
index 000000000..21a677ff5
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/feedback/data.ts
@@ -0,0 +1,589 @@
+import type { VbenFormApi, VbenFormSchema } from '#/adapter/form';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MesProFeedbackApi } from '#/api/mes/pro/feedback';
+import type { MesProTaskApi } from '#/api/mes/pro/task';
+
+import { h, markRaw } from 'vue';
+
+import { DICT_TYPE } from '@vben/constants';
+import { getDictOptions } from '@vben/hooks';
+
+import { ElButton } from 'element-plus';
+
+import { generateAutoCode } from '#/api/mes/md/autocode/record';
+import { getRouteProcessByRouteAndProcess } from '#/api/mes/pro/route/process';
+import { getSimpleUserList } from '#/api/system/user';
+import { getRangePickerDefaultProps } from '#/utils';
+import { MdItemSelect } from '#/views/mes/md/item/components';
+import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
+import { ProTaskSelect } from '#/views/mes/pro/task/components';
+import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
+import {
+ MesAutoCodeRuleCode,
+ MesProTaskStatusEnum,
+ MesProWorkOrderStatusEnum,
+} from '#/views/mes/utils/constants';
+
+/** 生产报工表单类型 */
+export type FormType = 'approve' | 'create' | 'detail' | 'submit' | 'update';
+
+/** 列表的搜索表单 */
+export function useGridFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'code',
+ label: '报工单号',
+ component: 'Input',
+ componentProps: {
+ clearable: true,
+ placeholder: '请输入报工单号',
+ },
+ },
+ {
+ fieldName: 'type',
+ label: '报工类型',
+ component: 'Select',
+ componentProps: {
+ clearable: true,
+ options: getDictOptions(DICT_TYPE.MES_PRO_FEEDBACK_TYPE, 'number'),
+ placeholder: '请选择报工类型',
+ },
+ },
+ {
+ fieldName: 'workOrderId',
+ label: '生产工单',
+ component: markRaw(ProWorkOrderSelect),
+ componentProps: {
+ clearable: true,
+ placeholder: '请选择工单',
+ },
+ },
+ {
+ fieldName: 'itemId',
+ label: '产品物料',
+ component: markRaw(MdItemSelect),
+ componentProps: {
+ clearable: true,
+ placeholder: '请选择产品物料',
+ },
+ },
+ {
+ fieldName: 'feedbackUserId',
+ label: '报工人',
+ component: 'ApiSelect',
+ componentProps: {
+ api: getSimpleUserList,
+ clearable: true,
+ labelField: 'nickname',
+ placeholder: '请选择报工人',
+ valueField: 'id',
+ },
+ },
+ {
+ fieldName: 'creator',
+ label: '记录人',
+ component: 'ApiSelect',
+ componentProps: {
+ api: getSimpleUserList,
+ clearable: true,
+ labelField: 'nickname',
+ placeholder: '请选择记录人',
+ valueField: 'id',
+ },
+ },
+ {
+ fieldName: 'status',
+ label: '状态',
+ component: 'Select',
+ componentProps: {
+ clearable: true,
+ options: getDictOptions(DICT_TYPE.MES_PRO_FEEDBACK_STATUS, 'number'),
+ placeholder: '请选择状态',
+ },
+ },
+ {
+ fieldName: 'feedbackTime',
+ label: '报工时间',
+ component: 'RangePicker',
+ componentProps: {
+ ...getRangePickerDefaultProps(),
+ clearable: true,
+ },
+ },
+ ];
+}
+
+/** 列表的字段 */
+export function useGridColumns(): VxeTableGridOptions['columns'] {
+ return [
+ {
+ field: 'code',
+ title: '报工单号',
+ width: 160,
+ slots: { default: 'code' },
+ },
+ {
+ field: 'type',
+ title: '报工类型',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.MES_PRO_FEEDBACK_TYPE },
+ },
+ },
+ { field: 'workstationName', title: '工作站', width: 120 },
+ { field: 'processName', title: '工序', width: 100 },
+ { field: 'workOrderCode', title: '生产工单编码', width: 160 },
+ { field: 'itemCode', title: '产品物料编码', width: 120 },
+ { field: 'itemName', title: '产品物料名称', minWidth: 140 },
+ { field: 'itemSpecification', title: '规格型号', width: 120 },
+ { field: 'unitMeasureName', title: '单位', width: 80 },
+ { field: 'feedbackQuantity', title: '报工数量', width: 100 },
+ { field: 'feedbackUserNickname', title: '报工人', width: 100 },
+ {
+ field: 'feedbackTime',
+ title: '报工时间',
+ width: 180,
+ formatter: 'formatDateTime',
+ },
+ { field: 'approveUserNickname', title: '审核人', width: 100 },
+ {
+ field: 'status',
+ title: '状态',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.MES_PRO_FEEDBACK_STATUS },
+ },
+ },
+ {
+ title: '操作',
+ width: 240,
+ fixed: 'right',
+ slots: { default: 'actions' },
+ },
+ ];
+}
+
+/**
+ * 新增/编辑/提交/审批/详情生产报工的表单
+ *
+ * - create / update:录入报工主体信息和数量
+ * - submit / approve / detail:主体字段只读
+ *
+ * 数量区域根据 `checkFlag` 和 `unqualifiedQuantity` 动态显示:
+ * - 非质检工序:报工数量 = 合格 + 不良;不良 > 0 时再展开工废/料废/其他废品
+ * - 质检工序:只填报工数量(视为待检数量)
+ */
+export function useFormSchema(
+ formType: FormType,
+ formApi?: VbenFormApi,
+): VbenFormSchema[] {
+ const isHeaderReadonly = ['approve', 'detail', 'submit'].includes(formType);
+ return [
+ {
+ fieldName: 'id',
+ component: 'Input',
+ dependencies: { triggerFields: [''], show: () => false },
+ },
+ {
+ fieldName: 'checkFlag',
+ component: 'Input',
+ dependencies: { triggerFields: [''], show: () => false },
+ defaultValue: true,
+ },
+ {
+ fieldName: 'routeId',
+ component: 'Input',
+ dependencies: { triggerFields: [''], show: () => false },
+ },
+ {
+ fieldName: 'processId',
+ component: 'Input',
+ dependencies: { triggerFields: [''], show: () => false },
+ },
+ {
+ fieldName: 'itemId',
+ component: 'Input',
+ dependencies: { triggerFields: [''], show: () => false },
+ },
+ {
+ fieldName: 'code',
+ label: '报工单号',
+ component: 'Input',
+ componentProps: {
+ disabled: isHeaderReadonly,
+ placeholder: '请输入报工单号',
+ },
+ rules: 'required',
+ suffix: () =>
+ h(
+ ElButton,
+ {
+ disabled: isHeaderReadonly,
+ type: 'default',
+ onClick: async () => {
+ const code = await generateAutoCode(
+ MesAutoCodeRuleCode.PRO_FEEDBACK_CODE,
+ );
+ await formApi?.setFieldValue('code', code);
+ },
+ },
+ { default: () => '生成' },
+ ),
+ },
+ {
+ fieldName: 'type',
+ label: '报工类型',
+ component: 'Select',
+ componentProps: {
+ disabled: isHeaderReadonly,
+ options: getDictOptions(DICT_TYPE.MES_PRO_FEEDBACK_TYPE, 'number'),
+ placeholder: '请选择报工类型',
+ },
+ rules: 'required',
+ },
+ {
+ fieldName: 'workOrderId',
+ label: '生产工单',
+ component: markRaw(ProWorkOrderSelect),
+ componentProps: {
+ disabled: isHeaderReadonly,
+ placeholder: '请选择工单',
+ status: MesProWorkOrderStatusEnum.CONFIRMED,
+ // 工单变更:清空任务及任务带出的产品信息、数量区域控制位
+ onChange: async () => {
+ await formApi?.setValues({
+ checkFlag: true,
+ itemCode: undefined,
+ itemId: undefined,
+ itemName: undefined,
+ itemSpecification: undefined,
+ processId: undefined,
+ routeId: undefined,
+ taskId: undefined,
+ unitMeasureName: undefined,
+ workstationId: undefined,
+ });
+ },
+ },
+ rules: 'selectRequired',
+ },
+ {
+ fieldName: 'taskId',
+ label: '生产任务',
+ component: markRaw(ProTaskSelect),
+ dependencies: {
+ triggerFields: ['workOrderId', 'workstationId'],
+ componentProps: (values) => ({
+ disabled: isHeaderReadonly || !values.workOrderId,
+ placeholder: values.workOrderId ? '请选择任务' : '请先选择工单',
+ statuses: [MesProTaskStatusEnum.PREPARE],
+ workOrderId: values.workOrderId,
+ workstationId: values.workstationId,
+ }),
+ },
+ // 任务变更:自动填充关联字段、产品信息、checkFlag
+ componentProps: {
+ onChange: async (task?: MesProTaskApi.Task) => {
+ if (!task) {
+ return;
+ }
+ await formApi?.setValues({
+ itemCode: task.itemCode,
+ itemId: task.itemId,
+ itemName: task.itemName,
+ itemSpecification: task.itemSpecification,
+ processId: task.processId,
+ routeId: task.routeId,
+ unitMeasureName: task.unitMeasureName,
+ workstationId: task.workstationId,
+ });
+ // 工艺路线工序的 checkFlag 决定数量区域展示
+ if (task.routeId && task.processId) {
+ try {
+ const routeProcess = await getRouteProcessByRouteAndProcess(
+ task.routeId,
+ task.processId,
+ );
+ await formApi?.setFieldValue(
+ 'checkFlag',
+ routeProcess?.checkFlag ?? false,
+ );
+ } catch {
+ await formApi?.setFieldValue('checkFlag', true);
+ }
+ }
+ },
+ },
+ rules: 'selectRequired',
+ },
+ {
+ fieldName: 'workstationId',
+ label: '工作站',
+ component: markRaw(MdWorkstationSelect),
+ componentProps: {
+ disabled: isHeaderReadonly,
+ placeholder: '请选择工作站',
+ },
+ rules: 'selectRequired',
+ },
+ {
+ fieldName: 'itemCode',
+ label: '产品编码',
+ component: 'Input',
+ componentProps: { disabled: true },
+ dependencies: {
+ triggerFields: ['itemCode'],
+ show: (values) => !!values.itemCode,
+ },
+ },
+ {
+ fieldName: 'itemName',
+ label: '产品名称',
+ component: 'Input',
+ componentProps: { disabled: true },
+ dependencies: {
+ triggerFields: ['itemCode'],
+ show: (values) => !!values.itemCode,
+ },
+ },
+ {
+ fieldName: 'unitMeasureName',
+ label: '单位',
+ component: 'Input',
+ componentProps: { disabled: true },
+ dependencies: {
+ triggerFields: ['itemCode'],
+ show: (values) => !!values.itemCode,
+ },
+ },
+ {
+ fieldName: 'itemSpecification',
+ label: '规格',
+ component: 'Input',
+ componentProps: { disabled: true },
+ dependencies: {
+ triggerFields: ['itemCode'],
+ show: (values) => !!values.itemCode,
+ },
+ },
+ {
+ fieldName: 'feedbackQuantity',
+ label: '报工数量',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ },
+ dependencies: {
+ triggerFields: ['checkFlag'],
+ // 非质检工序时,报工数量 = 合格 + 不良,禁用直接编辑
+ componentProps: (values) => ({
+ class: '!w-full',
+ controlsPosition: 'right',
+ disabled: !values.checkFlag,
+ min: 0,
+ placeholder: '请输入报工数量',
+ precision: 2,
+ }),
+ },
+ rules: 'required',
+ },
+ {
+ fieldName: 'qualifiedQuantity',
+ label: '合格品数量',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ // 合格/不良变更,自动累计为报工数量
+ onChange: async () => {
+ const values = await formApi?.getValues();
+ await formApi?.setFieldValue(
+ 'feedbackQuantity',
+ (values?.qualifiedQuantity || 0) +
+ (values?.unqualifiedQuantity || 0),
+ );
+ },
+ },
+ defaultValue: 0,
+ dependencies: {
+ triggerFields: ['checkFlag'],
+ show: (values) => !values.checkFlag,
+ },
+ },
+ {
+ fieldName: 'unqualifiedQuantity',
+ label: '不良品数量',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ // 合格/不良变更,自动累计为报工数量
+ onChange: async () => {
+ const values = await formApi?.getValues();
+ await formApi?.setFieldValue(
+ 'feedbackQuantity',
+ (values?.qualifiedQuantity || 0) +
+ (values?.unqualifiedQuantity || 0),
+ );
+ },
+ },
+ defaultValue: 0,
+ dependencies: {
+ triggerFields: ['checkFlag'],
+ show: (values) => !values.checkFlag,
+ },
+ },
+ {
+ fieldName: 'laborScrapQuantity',
+ label: '工废数量',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ // 废品分类变更,自动累计为不良品数量及报工数量
+ onChange: async () => {
+ const values = await formApi?.getValues();
+ const unqualified =
+ (values?.laborScrapQuantity || 0) +
+ (values?.materialScrapQuantity || 0) +
+ (values?.otherScrapQuantity || 0);
+ await formApi?.setValues({
+ feedbackQuantity:
+ (values?.qualifiedQuantity || 0) + unqualified,
+ unqualifiedQuantity: unqualified,
+ });
+ },
+ },
+ defaultValue: 0,
+ dependencies: {
+ triggerFields: ['checkFlag', 'unqualifiedQuantity'],
+ show: (values) =>
+ !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
+ },
+ },
+ {
+ fieldName: 'materialScrapQuantity',
+ label: '料废数量',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ // 废品分类变更,自动累计为不良品数量及报工数量
+ onChange: async () => {
+ const values = await formApi?.getValues();
+ const unqualified =
+ (values?.laborScrapQuantity || 0) +
+ (values?.materialScrapQuantity || 0) +
+ (values?.otherScrapQuantity || 0);
+ await formApi?.setValues({
+ feedbackQuantity:
+ (values?.qualifiedQuantity || 0) + unqualified,
+ unqualifiedQuantity: unqualified,
+ });
+ },
+ },
+ defaultValue: 0,
+ dependencies: {
+ triggerFields: ['checkFlag', 'unqualifiedQuantity'],
+ show: (values) =>
+ !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
+ },
+ },
+ {
+ fieldName: 'otherScrapQuantity',
+ label: '其他废品',
+ component: 'InputNumber',
+ componentProps: {
+ class: '!w-full',
+ controlsPosition: 'right',
+ min: 0,
+ precision: 2,
+ // 废品分类变更,自动累计为不良品数量及报工数量
+ onChange: async () => {
+ const values = await formApi?.getValues();
+ const unqualified =
+ (values?.laborScrapQuantity || 0) +
+ (values?.materialScrapQuantity || 0) +
+ (values?.otherScrapQuantity || 0);
+ await formApi?.setValues({
+ feedbackQuantity:
+ (values?.qualifiedQuantity || 0) + unqualified,
+ unqualifiedQuantity: unqualified,
+ });
+ },
+ },
+ defaultValue: 0,
+ dependencies: {
+ triggerFields: ['checkFlag', 'unqualifiedQuantity'],
+ show: (values) =>
+ !values.checkFlag && (values.unqualifiedQuantity || 0) > 0,
+ },
+ },
+ {
+ fieldName: 'feedbackUserId',
+ label: '报工人',
+ component: 'ApiSelect',
+ componentProps: {
+ api: getSimpleUserList,
+ clearable: true,
+ disabled: isHeaderReadonly,
+ labelField: 'nickname',
+ placeholder: '请选择报工人',
+ valueField: 'id',
+ },
+ rules: 'selectRequired',
+ },
+ {
+ fieldName: 'feedbackTime',
+ label: '报工时间',
+ component: 'DatePicker',
+ componentProps: {
+ class: '!w-full',
+ disabled: isHeaderReadonly,
+ format: 'YYYY-MM-DD HH:mm:ss',
+ placeholder: '请选择报工时间',
+ type: 'datetime',
+ valueFormat: 'x',
+ },
+ rules: 'required',
+ },
+ {
+ fieldName: 'approveUserId',
+ label: '审核人',
+ component: 'ApiSelect',
+ componentProps: {
+ api: getSimpleUserList,
+ clearable: true,
+ disabled: isHeaderReadonly,
+ labelField: 'nickname',
+ placeholder: '请选择审核人',
+ valueField: 'id',
+ },
+ rules: 'selectRequired',
+ },
+ {
+ fieldName: 'remark',
+ label: '备注',
+ component: 'Textarea',
+ formItemClass: 'col-span-3',
+ componentProps: {
+ autosize: { maxRows: 3, minRows: 2 },
+ disabled: formType === 'detail',
+ placeholder: '请输入备注',
+ },
+ },
+ ];
+}
diff --git a/apps/web-ele/src/views/mes/pro/feedback/index.vue b/apps/web-ele/src/views/mes/pro/feedback/index.vue
new file mode 100644
index 000000000..ef65e4629
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/feedback/index.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.code }}
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/feedback/modules/form.vue b/apps/web-ele/src/views/mes/pro/feedback/modules/form.vue
new file mode 100644
index 000000000..da61a777f
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/feedback/modules/form.vue
@@ -0,0 +1,319 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('common.submit') }}
+
+
+
+
+ 通过
+
+
+
+
+ 不通过
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/feedback/modules/item-consume-list.vue b/apps/web-ele/src/views/mes/pro/feedback/modules/item-consume-list.vue
new file mode 100644
index 000000000..5aa78254f
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/feedback/modules/item-consume-list.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/feedback/modules/product-produce-list.vue b/apps/web-ele/src/views/mes/pro/feedback/modules/product-produce-list.vue
new file mode 100644
index 000000000..17ac88995
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/feedback/modules/product-produce-list.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/task/components/index.ts b/apps/web-ele/src/views/mes/pro/task/components/index.ts
new file mode 100644
index 000000000..3847bb912
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/task/components/index.ts
@@ -0,0 +1,2 @@
+export { default as ProTaskSelectDialog } from './pro-task-select-dialog.vue';
+export { default as ProTaskSelect } from './pro-task-select.vue';
diff --git a/apps/web-ele/src/views/mes/pro/task/components/pro-task-select-dialog.vue b/apps/web-ele/src/views/mes/pro/task/components/pro-task-select-dialog.vue
new file mode 100644
index 000000000..3e43fc9ad
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/task/components/pro-task-select-dialog.vue
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/task/components/pro-task-select.vue b/apps/web-ele/src/views/mes/pro/task/components/pro-task-select.vue
new file mode 100644
index 000000000..99af6c290
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/task/components/pro-task-select.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
任务编号:{{ selectedItem.code || '-' }}
+
任务名称:{{ selectedItem.name || '-' }}
+
工序:{{ selectedItem.processName || '-' }}
+
工作站:{{ selectedItem.workstationName || '-' }}
+
物料:{{ selectedItem.itemName || '-' }}
+
规格:{{ selectedItem.itemSpecification || '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-ele/src/views/mes/pro/task/data.ts b/apps/web-ele/src/views/mes/pro/task/data.ts
new file mode 100644
index 000000000..1e1cc70a2
--- /dev/null
+++ b/apps/web-ele/src/views/mes/pro/task/data.ts
@@ -0,0 +1,112 @@
+import type { VbenFormSchema } from '#/adapter/form';
+import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MesProTaskApi } from '#/api/mes/pro/task';
+
+import { markRaw } from 'vue';
+
+import { DICT_TYPE } from '@vben/constants';
+
+import { MdWorkstationSelect } from '#/views/mes/md/workstation/components';
+import { ProProcessSelect } from '#/views/mes/pro/process/components';
+import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components';
+
+/** 任务选择弹窗的搜索表单 */
+export function useTaskSelectGridFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'workOrderId',
+ label: '生产工单',
+ component: markRaw(ProWorkOrderSelect),
+ componentProps: {
+ clearable: true,
+ placeholder: '请选择生产工单',
+ },
+ },
+ {
+ fieldName: 'processId',
+ label: '所属工序',
+ component: markRaw(ProProcessSelect),
+ componentProps: {
+ clearable: true,
+ placeholder: '请选择工序',
+ },
+ },
+ {
+ fieldName: 'workstationId',
+ label: '工作站',
+ component: markRaw(MdWorkstationSelect),
+ componentProps: {
+ clearable: true,
+ placeholder: '请选择工作站',
+ },
+ },
+ {
+ fieldName: 'code',
+ label: '任务编号',
+ component: 'Input',
+ componentProps: {
+ clearable: true,
+ placeholder: '请输入任务编号',
+ },
+ },
+ {
+ fieldName: 'name',
+ label: '任务名称',
+ component: 'Input',
+ componentProps: {
+ clearable: true,
+ placeholder: '请输入任务名称',
+ },
+ },
+ ];
+}
+
+/** 任务选择弹窗的字段 */
+export function useTaskSelectGridColumns(
+ multiple = false,
+): VxeTableGridOptions['columns'] {
+ return [
+ { type: multiple ? 'checkbox' : 'radio', width: 50 },
+ { field: 'code', title: '任务编号', width: 180 },
+ { field: 'name', title: '任务名称', minWidth: 140 },
+ { field: 'workstationCode', title: '工作站编码', width: 140 },
+ { field: 'workstationName', title: '工作站名称', width: 140 },
+ { field: 'processName', title: '工序', width: 120 },
+ {
+ field: 'checkFlag',
+ title: '是否质检',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
+ },
+ },
+ { field: 'itemCode', title: '物料编码', width: 140 },
+ { field: 'itemName', title: '物料名称', width: 140 },
+ { field: 'itemSpecification', title: '规格型号', width: 120 },
+ { field: 'quantity', title: '排产数量', width: 100 },
+ { field: 'producedQuantity', title: '已生产数量', width: 110 },
+ {
+ field: 'startTime',
+ title: '开始生产时间',
+ width: 170,
+ formatter: 'formatDateTime',
+ },
+ { field: 'duration', title: '生产时长', width: 100 },
+ {
+ field: 'endTime',
+ title: '预计完成时间',
+ width: 170,
+ formatter: 'formatDateTime',
+ },
+ {
+ field: 'status',
+ title: '任务状态',
+ width: 100,
+ cellRender: {
+ name: 'CellDict',
+ props: { type: DICT_TYPE.MES_PRO_TASK_STATUS },
+ },
+ },
+ ];
+}
diff --git a/apps/web-ele/src/views/mes/utils/constants.ts b/apps/web-ele/src/views/mes/utils/constants.ts
index 2fd061dc6..668cf7240 100644
--- a/apps/web-ele/src/views/mes/utils/constants.ts
+++ b/apps/web-ele/src/views/mes/utils/constants.ts
@@ -166,10 +166,10 @@ export const MesProTaskStatusEnum = {
/** MES 生产报工状态枚举 */
export const MesProFeedbackStatusEnum = {
PREPARE: MesOrderStatusConstants.DRAFT,
- CONFIRMED: MesOrderStatusConstants.CONFIRMED,
APPROVING: MesOrderStatusConstants.APPROVING,
+ UNCHECK: MesOrderStatusConstants.APPROVED,
FINISHED: MesOrderStatusConstants.FINISHED,
- CANCELLED: MesOrderStatusConstants.CANCELLED,
+ CANCELED: MesOrderStatusConstants.CANCELLED,
} as const;
/** MES 流转卡状态枚举 */