pull/871/MERGE
YunaiV 2026-02-21 11:15:00 +08:00
parent 170b9e0857
commit eab4883204
2 changed files with 120 additions and 86 deletions

View File

@ -1,6 +1,5 @@
<!-- MES 生产报工表单 --> <!-- MES 生产报工表单 -->
<template> <template>
<!-- TODO @AI一行 3 -->
<Dialog :title="dialogTitle" v-model="dialogVisible" width="960px"> <Dialog :title="dialogTitle" v-model="dialogVisible" width="960px">
<el-form <el-form
ref="formRef" ref="formRef"
@ -9,14 +8,14 @@
label-width="120px" label-width="120px"
v-loading="formLoading" v-loading="formLoading"
> >
<el-row> <!-- 基本信息 -->
<el-col :span="12"> <el-row :gutter="20">
<!-- TODO @AI生成前端处理参考别的模块 --> <el-col :span="8">
<el-form-item label="报工单号" prop="code"> <el-form-item label="报工单号" prop="code">
<el-input v-model="formData.code" disabled placeholder="自动生成" /> <el-input v-model="formData.code" disabled placeholder="自动生成" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="8">
<el-form-item label="报工类型" prop="type"> <el-form-item label="报工类型" prop="type">
<el-select <el-select
v-model="formData.type" v-model="formData.type"
@ -33,10 +32,8 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="8">
<el-row> <!-- TODO @芋艿报告途径是不是非必须 -->
<!-- TODO @芋艿报告途径是不是非必须 -->
<el-col :span="12">
<el-form-item label="报工途径" prop="channel"> <el-form-item label="报工途径" prop="channel">
<el-select <el-select
v-model="formData.channel" v-model="formData.channel"
@ -53,20 +50,11 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="批次号" prop="batchCode">
<el-input
v-model="formData.batchCode"
placeholder="请输入批次号"
:disabled="isDetail"
/>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- 工单选择 --> <!-- 工单 / 任务 / 工作站 -->
<!-- TODO @AI生产工单 select --> <!-- TODO @AI生产工单 select -->
<el-row> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="8">
<el-form-item label="生产工单" prop="workOrderId"> <el-form-item label="生产工单" prop="workOrderId">
<el-select <el-select
v-model="formData.workOrderId" v-model="formData.workOrderId"
@ -74,7 +62,7 @@
remote remote
reserve-keyword reserve-keyword
:remote-method="searchWorkOrder" :remote-method="searchWorkOrder"
placeholder="请搜索工单编码/名称" placeholder="请搜索工单编码"
:disabled="isDetail" :disabled="isDetail"
class="!w-1/1" class="!w-1/1"
@change="handleWorkOrderChange" @change="handleWorkOrderChange"
@ -88,7 +76,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="8">
<el-form-item label="生产任务" prop="taskId"> <el-form-item label="生产任务" prop="taskId">
<el-select <el-select
v-model="formData.taskId" v-model="formData.taskId"
@ -110,11 +98,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="8">
<!-- 工作站 / 工序任务选中后自动填充也支持手动选择 -->
<!-- TODO @AI工作站 select -->
<el-row>
<el-col :span="12">
<el-form-item label="工作站" prop="workstationId"> <el-form-item label="工作站" prop="workstationId">
<el-select <el-select
v-model="formData.workstationId" v-model="formData.workstationId"
@ -135,36 +119,27 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- TODO @AI生产任务 select --> </el-row>
<el-col :span="12"> <!-- 工序 / 批次号 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="工序" prop="processId"> <el-form-item label="工序" prop="processId">
<el-input v-model="processDisplay" disabled placeholder="由任务自动带入" /> <el-input v-model="processDisplay" disabled placeholder="由任务自动带入" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="8">
<!-- 物料 / 单位 / 工艺路线自动填充只读 --> <el-form-item label="批次号" prop="batchCode">
<!-- TODO 下面的 itemDisplayscheduledQuantity 不需要 --> <el-input
<el-row> v-model="formData.batchCode"
<el-col :span="12"> placeholder="请输入批次号"
<el-form-item label="产品物料" prop="itemId"> :disabled="isDetail"
<el-input v-model="itemDisplay" disabled placeholder="由任务自动带入" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排产数量" prop="scheduledQuantity">
<el-input-number
v-model="formData.scheduledQuantity"
:min="0"
:precision="2"
disabled
class="!w-1/1"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<!-- 数量区域 --> <!-- 数量区域 -->
<el-divider content-position="left">报工数量</el-divider> <el-divider content-position="left">报工数量</el-divider>
<el-row> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<el-form-item label="报工数量" prop="feedbackQuantity"> <el-form-item label="报工数量" prop="feedbackQuantity">
<el-input-number <el-input-number
@ -215,7 +190,7 @@
</el-row> </el-row>
<!-- 废品分类不良品>0 时展开 --> <!-- 废品分类不良品>0 时展开 -->
<!-- TODO @芋艿在评审下 --> <!-- TODO @芋艿在评审下 -->
<el-row v-if="formData.unqualifiedQuantity > 0"> <el-row :gutter="20" v-if="formData.unqualifiedQuantity > 0">
<el-col :span="8"> <el-col :span="8">
<el-form-item label="工废数量"> <el-form-item label="工废数量">
<el-input-number <el-input-number
@ -250,8 +225,27 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<!-- TODO @AI报工人报工时间审批人 --> <!-- TODO @AI报工人报工时间审批人select 模式 -->
<el-row> <!-- 报工人 / 报工时间 / 审核人仅编辑/详情模式展示 -->
<el-row :gutter="20" v-if="formData.id">
<el-col :span="8">
<el-form-item label="报工人">
<el-input :model-value="formData.feedbackUserNickname" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="报工时间">
<el-input :model-value="formData.feedbackTime" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="审核人">
<el-input :model-value="formData.approveUserNickname" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 备注 -->
<el-row :gutter="20">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input <el-input
@ -277,8 +271,6 @@ import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback' import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback'
import { ProWorkOrderApi } from '@/api/mes/pro/workorder' import { ProWorkOrderApi } from '@/api/mes/pro/workorder'
// TODO @AI
defineOptions({ name: 'FeedbackForm' }) defineOptions({ name: 'FeedbackForm' })
const { t } = useI18n() const { t } = useI18n()
@ -289,8 +281,9 @@ const dialogTitle = ref('')
const formLoading = ref(false) const formLoading = ref(false)
const formType = ref('') // 'create' | 'update' | 'detail' const formType = ref('') // 'create' | 'update' | 'detail'
const formData = ref({ const formData = ref<Record<string, any>>({
id: undefined, id: undefined,
code: undefined,
type: undefined, type: undefined,
channel: undefined, channel: undefined,
workstationId: undefined, workstationId: undefined,
@ -302,7 +295,6 @@ const formData = ref({
unitMeasureId: undefined, unitMeasureId: undefined,
expireDate: undefined, expireDate: undefined,
batchCode: undefined, batchCode: undefined,
scheduledQuantity: 0,
feedbackQuantity: 0, feedbackQuantity: 0,
qualifiedQuantity: 0, qualifiedQuantity: 0,
unqualifiedQuantity: 0, unqualifiedQuantity: 0,
@ -311,7 +303,10 @@ const formData = ref({
materialScrapQuantity: 0, materialScrapQuantity: 0,
otherScrapQuantity: 0, otherScrapQuantity: 0,
remark: undefined, remark: undefined,
code: undefined // RespVO
feedbackUserNickname: undefined,
feedbackTime: undefined,
approveUserNickname: undefined
}) })
const formRules = reactive({ const formRules = reactive({
@ -329,9 +324,8 @@ const isDetail = computed(() => formType.value === 'detail')
/** 是否需要检验checkFlag */ /** 是否需要检验checkFlag */
const checkFlag = ref(false) const checkFlag = ref(false)
/** 显示字段(只读) */ /** 工序显示(只读) */
const processDisplay = ref('') const processDisplay = ref('')
const itemDisplay = ref('')
// ==================== ==================== // ==================== ====================
@ -362,23 +356,19 @@ const searchTask = async (query: string) => {
/** 搜索工作站 */ /** 搜索工作站 */
const searchWorkstation = async (query: string) => { const searchWorkstation = async (query: string) => {
if (!query) return if (!query) return
// 使 API
// TODO @ API // TODO @ API
workstationOptions.value = [] workstationOptions.value = []
} }
/** 工单变更 */ /** 工单变更:清空任务相关字段 */
const handleWorkOrderChange = (workOrderId: number) => { const handleWorkOrderChange = () => {
//
formData.value.taskId = undefined formData.value.taskId = undefined
formData.value.routeId = undefined formData.value.routeId = undefined
formData.value.processId = undefined formData.value.processId = undefined
formData.value.itemId = undefined formData.value.itemId = undefined
formData.value.unitMeasureId = undefined formData.value.unitMeasureId = undefined
formData.value.workstationId = undefined formData.value.workstationId = undefined
formData.value.scheduledQuantity = 0
processDisplay.value = '' processDisplay.value = ''
itemDisplay.value = ''
taskOptions.value = [] taskOptions.value = []
checkFlag.value = false checkFlag.value = false
} }
@ -392,12 +382,31 @@ const handleTaskChange = (taskId: number) => {
formData.value.itemId = task.itemId formData.value.itemId = task.itemId
formData.value.unitMeasureId = task.unitMeasureId formData.value.unitMeasureId = task.unitMeasureId
formData.value.workstationId = task.workstationId formData.value.workstationId = task.workstationId
formData.value.scheduledQuantity = task.quantity
processDisplay.value = task.processCode ? task.processCode + ' - ' + task.processName : '' processDisplay.value = task.processCode ? task.processCode + ' - ' + task.processName : ''
itemDisplay.value = task.itemCode ? task.itemCode + ' - ' + task.itemName : ''
// TODO @ checkFlag routeProcess // TODO @ checkFlag routeProcess
} }
// ==================== ====================
/** 生成报工单编号(前端生成) */
const generateCode = () => {
const now = new Date()
const pad = (n: number) => n.toString().padStart(2, '0')
const dateStr =
now.getFullYear().toString() +
pad(now.getMonth() + 1) +
pad(now.getDate()) +
pad(now.getHours()) +
pad(now.getMinutes()) +
pad(now.getSeconds())
const random = Math.floor(Math.random() * 1000)
.toString()
.padStart(3, '0')
return 'FB' + dateStr + random
}
// ==================== ====================
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
dialogVisible.value = true dialogVisible.value = true
@ -407,12 +416,11 @@ const open = async (type: string, id?: number) => {
if (id) { if (id) {
formLoading.value = true formLoading.value = true
try { try {
const data = (await ProFeedbackApi.getFeedback(id)) as any const data = await ProFeedbackApi.getFeedback(id)
formData.value = data formData.value = data as any
// //
processDisplay.value = data.processCode ? data.processCode + ' - ' + data.processName : '' processDisplay.value = data.processCode ? data.processCode + ' - ' + data.processName : ''
itemDisplay.value = data.itemCode ? data.itemCode + ' - ' + data.itemName : '' checkFlag.value = (data as any).checkFlag || false
checkFlag.value = data.checkFlag || false
// select // select
if (data.workOrderId) { if (data.workOrderId) {
workOrderOptions.value = [ workOrderOptions.value = [
@ -430,6 +438,9 @@ const open = async (type: string, id?: number) => {
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
} else {
//
formData.value.code = generateCode()
} }
} }
@ -460,6 +471,7 @@ const submitForm = async () => {
const resetForm = () => { const resetForm = () => {
formData.value = { formData.value = {
id: undefined, id: undefined,
code: undefined,
type: undefined, type: undefined,
channel: undefined, channel: undefined,
workstationId: undefined, workstationId: undefined,
@ -471,7 +483,6 @@ const resetForm = () => {
unitMeasureId: undefined, unitMeasureId: undefined,
expireDate: undefined, expireDate: undefined,
batchCode: undefined, batchCode: undefined,
scheduledQuantity: 0,
feedbackQuantity: 0, feedbackQuantity: 0,
qualifiedQuantity: 0, qualifiedQuantity: 0,
unqualifiedQuantity: 0, unqualifiedQuantity: 0,
@ -480,13 +491,14 @@ const resetForm = () => {
materialScrapQuantity: 0, materialScrapQuantity: 0,
otherScrapQuantity: 0, otherScrapQuantity: 0,
remark: undefined, remark: undefined,
code: undefined feedbackUserNickname: undefined,
feedbackTime: undefined,
approveUserNickname: undefined
} }
workOrderOptions.value = [] workOrderOptions.value = []
taskOptions.value = [] taskOptions.value = []
workstationOptions.value = [] workstationOptions.value = []
processDisplay.value = '' processDisplay.value = ''
itemDisplay.value = ''
checkFlag.value = false checkFlag.value = false
formRef.value?.resetFields() formRef.value?.resetFields()
} }

View File

@ -33,15 +33,25 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- TODO @AIselect --> <!-- TODO @AIselect增加一个 workOrder select 组件 -->
<el-form-item label="工单编号" prop="workOrderId"> <el-form-item label="生产工单" prop="workOrderId">
<el-input <el-select
v-model="queryParams.workOrderId" v-model="queryParams.workOrderId"
placeholder="请输入工单编号" filterable
remote
reserve-keyword
:remote-method="searchWorkOrder"
placeholder="请搜索工单编码"
clearable clearable
@keyup.enter="handleQuery"
class="!w-240px" class="!w-240px"
/> >
<el-option
v-for="item in workOrderOptions"
:key="item.id"
:label="item.code"
:value="item.id"
/>
</el-select>
</el-form-item> </el-form-item>
<!-- TODO @AI产品物料 select --> <!-- TODO @AI产品物料 select -->
<!-- TODO @AI报工人 select --> <!-- TODO @AI报工人 select -->
@ -136,21 +146,24 @@
link link
type="primary" type="primary"
@click="openForm('update', scope.row.id)" @click="openForm('update', scope.row.id)"
v-hasPermi="['mes:pro-feedback:update']"> v-hasPermi="['mes:pro-feedback:update']"
>
编辑 编辑
</el-button> </el-button>
<el-button <el-button
link link
type="success" type="success"
@click="handleSubmit(scope.row.id)" @click="handleSubmit(scope.row.id)"
v-hasPermi="['mes:pro-feedback:update']"> v-hasPermi="['mes:pro-feedback:update']"
>
提交 提交
</el-button> </el-button>
<el-button <el-button
link link
type="danger" type="danger"
@click="handleDelete(scope.row.id)" @click="handleDelete(scope.row.id)"
v-hasPermi="['mes:pro-feedback:delete']"> v-hasPermi="['mes:pro-feedback:delete']"
>
删除 删除
</el-button> </el-button>
</template> </template>
@ -160,14 +173,16 @@
link link
type="warning" type="warning"
@click="handleReject(scope.row.id)" @click="handleReject(scope.row.id)"
v-hasPermi="['mes:pro-feedback:update']"> v-hasPermi="['mes:pro-feedback:update']"
>
驳回 驳回
</el-button> </el-button>
<el-button <el-button
link link
type="success" type="success"
@click="handleExecute(scope.row.id)" @click="handleExecute(scope.row.id)"
v-hasPermi="['mes:pro-feedback:update']"> v-hasPermi="['mes:pro-feedback:update']"
>
执行 执行
</el-button> </el-button>
<el-button <el-button
@ -206,12 +221,11 @@
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback' import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback'
import { ProWorkOrderApi } from '@/api/mes/pro/workorder'
import FeedbackForm from './FeedbackForm.vue' import FeedbackForm from './FeedbackForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { MesProFeedbackStatusEnum } from '@/views/mes/utils/constants' import { MesProFeedbackStatusEnum } from '@/views/mes/utils/constants'
// TODO @AI
defineOptions({ name: 'MesProFeedback' }) defineOptions({ name: 'MesProFeedback' })
const message = useMessage() const message = useMessage()
@ -232,6 +246,14 @@ const queryParams = reactive({
const queryFormRef = ref() const queryFormRef = ref()
const exportLoading = ref(false) const exportLoading = ref(false)
/** 工单远程搜索选项 */
const workOrderOptions = ref<any[]>([])
const searchWorkOrder = async (query: string) => {
if (!query) return
const data = await ProWorkOrderApi.getWorkOrderPage({ pageNo: 1, pageSize: 20, code: query })
workOrderOptions.value = data.list
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true