✨ feat(mes): 添加报工人和审核人字段,优化审批逻辑
parent
6553ab1875
commit
424f3d04c1
|
|
@ -24,7 +24,7 @@ export interface ProFeedbackVO {
|
||||||
itemId: number // 产品物料编号
|
itemId: number // 产品物料编号
|
||||||
itemCode: string // 物料编码
|
itemCode: string // 物料编码
|
||||||
itemName: string // 物料名称
|
itemName: string // 物料名称
|
||||||
itemSpec: string // 规格型号
|
itemSpecification: string // 规格型号
|
||||||
unitMeasureId: number // 单位编号
|
unitMeasureId: number // 单位编号
|
||||||
unitMeasureName: string // 单位名称
|
unitMeasureName: string // 单位名称
|
||||||
expireDate: Date // 过期日期
|
expireDate: Date // 过期日期
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export interface ProRouteProcessVO {
|
||||||
waitTime?: number // 等待时间(分钟)
|
waitTime?: number // 等待时间(分钟)
|
||||||
colorCode?: string // 甘特图显示颜色
|
colorCode?: string // 甘特图显示颜色
|
||||||
keyFlag?: number // 是否关键工序
|
keyFlag?: number // 是否关键工序
|
||||||
checkFlag?: number // 是否质检工序
|
checkFlag?: boolean // 是否质检工序
|
||||||
remark?: string // 备注
|
remark?: string // 备注
|
||||||
createTime?: Date // 创建时间
|
createTime?: Date // 创建时间
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +37,14 @@ export const ProRouteProcessApi = {
|
||||||
return await request.get({ url: `/mes/pro/route-process/get?id=` + id })
|
return await request.get({ url: `/mes/pro/route-process/get?id=` + id })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 按工艺路线+工序精确查询工序配置
|
||||||
|
getRouteProcessByRouteAndProcess: async (routeId: number, processId: number) => {
|
||||||
|
return await request.get({
|
||||||
|
url: `/mes/pro/route-process/get-by-route-and-process`,
|
||||||
|
params: { routeId, processId }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
// 新增工艺路线工序
|
// 新增工艺路线工序
|
||||||
createRouteProcess: async (data: ProRouteProcessVO) => {
|
createRouteProcess: async (data: ProRouteProcessVO) => {
|
||||||
return await request.post({ url: `/mes/pro/route-process/create`, data })
|
return await request.post({ url: `/mes/pro/route-process/create`, data })
|
||||||
|
|
|
||||||
|
|
@ -1,197 +0,0 @@
|
||||||
<!-- MES 物料产品 弹窗选择器 -->
|
|
||||||
<template>
|
|
||||||
<Dialog title="物料产品选择" v-model="dialogVisible" width="80%">
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<!-- 左侧:分类树 -->
|
|
||||||
<el-col :span="5">
|
|
||||||
<el-input
|
|
||||||
v-model="filterText"
|
|
||||||
placeholder="搜索分类"
|
|
||||||
clearable
|
|
||||||
class="mb-12px"
|
|
||||||
:prefix-icon="iconSearch"
|
|
||||||
/>
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="itemTypeTree"
|
|
||||||
:props="treeProps"
|
|
||||||
:expand-on-click-node="false"
|
|
||||||
:filter-node-method="filterNode"
|
|
||||||
default-expand-all
|
|
||||||
highlight-current
|
|
||||||
@node-click="handleNodeClick"
|
|
||||||
/>
|
|
||||||
</el-col>
|
|
||||||
<!-- 右侧:物料表格 -->
|
|
||||||
<el-col :span="19">
|
|
||||||
<!-- 搜索表单 -->
|
|
||||||
<el-form :inline="true" :model="queryParams" class="mb-10px" label-width="80px">
|
|
||||||
<el-form-item label="物料编码">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.code"
|
|
||||||
placeholder="请输入物料编码"
|
|
||||||
clearable
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="物料名称">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.name"
|
|
||||||
placeholder="请输入物料名称"
|
|
||||||
clearable
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="handleQuery">
|
|
||||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="resetQuery">
|
|
||||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:data="list"
|
|
||||||
:stripe="true"
|
|
||||||
:show-overflow-tooltip="true"
|
|
||||||
border
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
>
|
|
||||||
<el-table-column type="selection" width="50" align="center" />
|
|
||||||
<el-table-column label="物料编码" align="center" prop="code" width="120" />
|
|
||||||
<el-table-column label="物料名称" align="center" prop="name" min-width="120" />
|
|
||||||
<el-table-column label="规格型号" align="center" prop="specification" />
|
|
||||||
<el-table-column label="单位" align="center" prop="unitMeasureName" width="80" />
|
|
||||||
<el-table-column label="物料/产品" align="center" prop="itemOrProduct" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
{{ getItemOrProductLabel(scope.row.itemOrProduct) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="所属分类" align="center" prop="itemTypeName" width="120" />
|
|
||||||
</el-table>
|
|
||||||
<!-- 分页 -->
|
|
||||||
<Pagination
|
|
||||||
:total="total"
|
|
||||||
v-model:page="queryParams.pageNo"
|
|
||||||
v-model:limit="queryParams.pageSize"
|
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<template #footer>
|
|
||||||
<el-button type="primary" @click="confirmSelect">确 定</el-button>
|
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
||||||
</template>
|
|
||||||
</Dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { MdItemApi, MdItemVO } from '@/api/mes/md/item'
|
|
||||||
import { MdItemTypeApi, MdItemTypeVO } from '@/api/mes/md/item/type'
|
|
||||||
import { handleTree } from '@/utils/tree'
|
|
||||||
import { getItemOrProductLabel } from '@/views/mes/utils/constants'
|
|
||||||
import { Search as iconSearch } from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'ItemProductSelect' })
|
|
||||||
|
|
||||||
const message = useMessage() // 消息弹窗
|
|
||||||
const emit = defineEmits<{
|
|
||||||
selected: [rows: MdItemVO[]] // 确认选择事件
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
||||||
const loading = ref(false) // 列表加载中
|
|
||||||
const list = ref<MdItemVO[]>([]) // 物料列表
|
|
||||||
const total = ref(0) // 总条数
|
|
||||||
const selectedRows = ref<MdItemVO[]>([]) // 选中行
|
|
||||||
|
|
||||||
// ==================== 分类树 ====================
|
|
||||||
const treeRef = ref() // 树组件 Ref
|
|
||||||
const filterText = ref('') // 分类搜索文本
|
|
||||||
const itemTypeTree = ref<MdItemTypeVO[]>([]) // 分类树数据
|
|
||||||
const treeProps = { children: 'children', label: 'name' } // 树属性配置
|
|
||||||
|
|
||||||
/** 过滤树节点 */
|
|
||||||
const filterNode = (value: string, data: MdItemTypeVO) => {
|
|
||||||
if (!value) return true
|
|
||||||
return data.name?.includes(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 监听筛选文本变化 */
|
|
||||||
watch(filterText, (val) => {
|
|
||||||
treeRef.value?.filter(val)
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 点击树节点 */
|
|
||||||
const handleNodeClick = (data: MdItemTypeVO) => {
|
|
||||||
queryParams.itemTypeId = data.id
|
|
||||||
handleQuery()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 物料查询 ====================
|
|
||||||
const queryParams = reactive({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
code: undefined as string | undefined,
|
|
||||||
name: undefined as string | undefined,
|
|
||||||
itemTypeId: undefined as number | undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 查询列表 */
|
|
||||||
const getList = async () => {
|
|
||||||
loading.value = true
|
|
||||||
try {
|
|
||||||
const data = await MdItemApi.getItemPage(queryParams)
|
|
||||||
list.value = data.list
|
|
||||||
total.value = data.total
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 搜索 */
|
|
||||||
const handleQuery = () => {
|
|
||||||
queryParams.pageNo = 1
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置 */
|
|
||||||
const resetQuery = () => {
|
|
||||||
queryParams.code = undefined
|
|
||||||
queryParams.name = undefined
|
|
||||||
queryParams.itemTypeId = undefined
|
|
||||||
handleQuery()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 选中变化 */
|
|
||||||
const handleSelectionChange = (rows: MdItemVO[]) => {
|
|
||||||
selectedRows.value = rows
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 确认选择 */
|
|
||||||
const confirmSelect = () => {
|
|
||||||
if (selectedRows.value.length === 0) {
|
|
||||||
message.warning('请至少选择一条数据')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
emit('selected', selectedRows.value)
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 打开弹窗 ====================
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
|
||||||
const open = async () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
selectedRows.value = []
|
|
||||||
// 加载分类树
|
|
||||||
const typeList = await MdItemTypeApi.getItemTypeSimpleList()
|
|
||||||
itemTypeTree.value = handleTree(typeList)
|
|
||||||
// 加载物料列表
|
|
||||||
await getList()
|
|
||||||
}
|
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|
||||||
</script>
|
|
||||||
|
|
@ -66,17 +66,48 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 工序 -->
|
<!-- 数量区域 -->
|
||||||
<el-row :gutter="20">
|
<el-divider content-position="left">报工数量</el-divider>
|
||||||
|
<!-- 非质检工序:报工数量(只读自动计算) + 合格品 + 不良品 -->
|
||||||
|
<el-row :gutter="20" v-if="!checkFlag">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="工序" prop="processId">
|
<el-form-item label="报工数量" prop="feedbackQuantity">
|
||||||
<el-input v-model="processDisplay" disabled placeholder="由任务自动带入" />
|
<el-input-number
|
||||||
|
v-model="formData.feedbackQuantity"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
disabled
|
||||||
|
class="!w-1/1"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item label="合格品数量" prop="qualifiedQuantity">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.qualifiedQuantity"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
:disabled="isDetail"
|
||||||
|
class="!w-1/1"
|
||||||
|
@change="handleQuantityChanged"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-form-item label="不良品数量" prop="unqualifiedQuantity">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.unqualifiedQuantity"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
:disabled="isDetail"
|
||||||
|
class="!w-1/1"
|
||||||
|
@change="handleQuantityChanged"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 数量区域 -->
|
<!-- 质检工序:只填报工数量 -->
|
||||||
<el-divider content-position="left">报工数量</el-divider>
|
<el-row :gutter="20" v-else>
|
||||||
<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
|
||||||
|
|
@ -88,46 +119,9 @@
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- TODO @芋艿:在评审下 -->
|
|
||||||
<el-col :span="8" v-if="!checkFlag">
|
|
||||||
<el-form-item label="合格品数量" prop="qualifiedQuantity">
|
|
||||||
<el-input-number
|
|
||||||
v-model="formData.qualifiedQuantity"
|
|
||||||
:min="0"
|
|
||||||
:precision="2"
|
|
||||||
:disabled="isDetail"
|
|
||||||
class="!w-1/1"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<!-- TODO @芋艿:在评审下 -->
|
|
||||||
<el-col :span="8" v-if="!checkFlag">
|
|
||||||
<el-form-item label="不良品数量" prop="unqualifiedQuantity">
|
|
||||||
<el-input-number
|
|
||||||
v-model="formData.unqualifiedQuantity"
|
|
||||||
:min="0"
|
|
||||||
:precision="2"
|
|
||||||
:disabled="isDetail"
|
|
||||||
class="!w-1/1"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<!-- TODO @芋艿:在评审下 -->
|
|
||||||
<el-col :span="8" v-if="checkFlag">
|
|
||||||
<el-form-item label="待检测数量">
|
|
||||||
<el-input-number
|
|
||||||
v-model="formData.uncheckQuantity"
|
|
||||||
:min="0"
|
|
||||||
:precision="2"
|
|
||||||
:disabled="isDetail"
|
|
||||||
class="!w-1/1"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 废品分类(不良品>0 时展开) -->
|
<!-- 废品分类(非质检工序 且 不良品>0 时展开) -->
|
||||||
<!-- TODO @芋艿:在评审下 -->
|
<el-row :gutter="20" v-if="!checkFlag && 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
|
||||||
|
|
@ -136,6 +130,7 @@
|
||||||
:precision="2"
|
:precision="2"
|
||||||
:disabled="isDetail"
|
:disabled="isDetail"
|
||||||
class="!w-1/1"
|
class="!w-1/1"
|
||||||
|
@change="handleScrapChanged"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -147,6 +142,7 @@
|
||||||
:precision="2"
|
:precision="2"
|
||||||
:disabled="isDetail"
|
:disabled="isDetail"
|
||||||
class="!w-1/1"
|
class="!w-1/1"
|
||||||
|
@change="handleScrapChanged"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -158,6 +154,7 @@
|
||||||
:precision="2"
|
:precision="2"
|
||||||
:disabled="isDetail"
|
:disabled="isDetail"
|
||||||
class="!w-1/1"
|
class="!w-1/1"
|
||||||
|
@change="handleScrapChanged"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -178,7 +175,7 @@
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="formData.feedbackTime"
|
v-model="formData.feedbackTime"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
value-format="x"
|
||||||
placeholder="请选择报工时间"
|
placeholder="请选择报工时间"
|
||||||
:disabled="isDetail"
|
:disabled="isDetail"
|
||||||
class="!w-1/1"
|
class="!w-1/1"
|
||||||
|
|
@ -218,22 +215,32 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||||
import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback'
|
import { ProFeedbackApi, ProFeedbackVO } from '@/api/mes/pro/feedback'
|
||||||
|
import { ProRouteProcessApi } from '@/api/mes/pro/route/process'
|
||||||
import ProWorkOrderSelect from '@/views/mes/pro/workorder/components/ProWorkOrderSelect.vue'
|
import ProWorkOrderSelect from '@/views/mes/pro/workorder/components/ProWorkOrderSelect.vue'
|
||||||
import ProTaskSelect from '@/views/mes/pro/task/components/ProTaskSelect.vue'
|
import ProTaskSelect from '@/views/mes/pro/task/components/ProTaskSelect.vue'
|
||||||
import MdWorkstationSelect from '@/views/mes/md/workstation/components/MdWorkstationSelect.vue'
|
import MdWorkstationSelect from '@/views/mes/md/workstation/components/MdWorkstationSelect.vue'
|
||||||
import UserSelect from '@/views/system/user/components/UserSelect.vue'
|
import UserSelect from '@/views/system/user/components/UserSelect.vue'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
defineOptions({ name: 'FeedbackForm' })
|
defineOptions({ name: 'FeedbackForm' })
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n() // 国际化
|
||||||
const message = useMessage()
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||||
const dialogTitle = ref('')
|
const formLoading = ref(false) // 表单的加载中
|
||||||
const formLoading = ref(false)
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改;detail - 详情
|
||||||
const formType = ref('') // 'create' | 'update' | 'detail'
|
const dialogTitle = computed(() => {
|
||||||
|
if (formType.value === 'detail') {
|
||||||
|
return '查看生产报工记录'
|
||||||
|
}
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
return '添加生产报工记录'
|
||||||
|
}
|
||||||
|
return '修改生产报工记录'
|
||||||
|
})
|
||||||
const formData = ref<Record<string, any>>({
|
const formData = ref<Record<string, any>>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
code: undefined,
|
code: undefined,
|
||||||
|
|
@ -243,6 +250,7 @@ const formData = ref<Record<string, any>>({
|
||||||
processId: undefined,
|
processId: undefined,
|
||||||
workOrderId: undefined,
|
workOrderId: undefined,
|
||||||
taskId: undefined,
|
taskId: undefined,
|
||||||
|
itemId: undefined,
|
||||||
expireDate: undefined,
|
expireDate: undefined,
|
||||||
feedbackQuantity: 0,
|
feedbackQuantity: 0,
|
||||||
qualifiedQuantity: 0,
|
qualifiedQuantity: 0,
|
||||||
|
|
@ -261,46 +269,72 @@ const formRules = reactive({
|
||||||
workOrderId: [{ required: true, message: '生产工单不能为空', trigger: 'change' }],
|
workOrderId: [{ required: true, message: '生产工单不能为空', trigger: 'change' }],
|
||||||
taskId: [{ required: true, message: '生产任务不能为空', trigger: 'change' }],
|
taskId: [{ required: true, message: '生产任务不能为空', trigger: 'change' }],
|
||||||
workstationId: [{ required: true, message: '工作站不能为空', trigger: 'change' }],
|
workstationId: [{ required: true, message: '工作站不能为空', trigger: 'change' }],
|
||||||
feedbackQuantity: [{ required: true, message: '报工数量不能为空', trigger: 'blur' }]
|
feedbackQuantity: [{ required: true, message: '报工数量不能为空', trigger: 'blur' }],
|
||||||
|
feedbackUserId: [{ required: true, message: '报工人不能为空', trigger: 'change' }],
|
||||||
|
feedbackTime: [{ required: true, message: '报工时间不能为空', trigger: 'change' }],
|
||||||
|
approveUserId: [{ required: true, message: '审核人不能为空', trigger: 'change' }]
|
||||||
})
|
})
|
||||||
const formRef = ref()
|
const formRef = ref() // 表单 Ref
|
||||||
|
const isDetail = computed(() => formType.value === 'detail') // 是否为详情模式
|
||||||
/** 是否为详情模式 */
|
const checkFlag = ref(true) // 是否需要检验(默认 true,未选任务时只展示报工数量)
|
||||||
const isDetail = computed(() => formType.value === 'detail')
|
|
||||||
|
|
||||||
/** 是否需要检验(checkFlag) */
|
|
||||||
const checkFlag = ref(false)
|
|
||||||
|
|
||||||
/** 工序显示(只读) */
|
|
||||||
const processDisplay = ref('')
|
|
||||||
|
|
||||||
// ==================== 级联选择回调 ====================
|
// ==================== 级联选择回调 ====================
|
||||||
|
|
||||||
|
/** 加载工序的 checkFlag */
|
||||||
|
const loadCheckFlag = async (routeId?: number, processId?: number) => {
|
||||||
|
if (!routeId || !processId) {
|
||||||
|
checkFlag.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const routeProcess = await ProRouteProcessApi.getRouteProcessByRouteAndProcess(
|
||||||
|
routeId,
|
||||||
|
processId
|
||||||
|
)
|
||||||
|
checkFlag.value = routeProcess?.checkFlag ?? false
|
||||||
|
} catch {
|
||||||
|
checkFlag.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 合格品/不良品变更:自动计算报工数量 = 合格 + 不良 */
|
||||||
|
const handleQuantityChanged = () => {
|
||||||
|
formData.value.feedbackQuantity =
|
||||||
|
(formData.value.qualifiedQuantity || 0) + (formData.value.unqualifiedQuantity || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 废品明细变更:自动计算不良品数量 = 工废 + 料废 + 其他 */
|
||||||
|
const handleScrapChanged = () => {
|
||||||
|
formData.value.unqualifiedQuantity =
|
||||||
|
(formData.value.laborScrapQuantity || 0) +
|
||||||
|
(formData.value.materialScrapQuantity || 0) +
|
||||||
|
(formData.value.otherScrapQuantity || 0)
|
||||||
|
handleQuantityChanged()
|
||||||
|
}
|
||||||
|
|
||||||
/** 工单变更:清空任务相关字段 */
|
/** 工单变更:清空任务相关字段 */
|
||||||
const handleWorkOrderChange = () => {
|
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.workstationId = undefined
|
formData.value.workstationId = undefined
|
||||||
processDisplay.value = ''
|
formData.value.itemId = undefined
|
||||||
checkFlag.value = false
|
checkFlag.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 任务变更:自动填充关联字段 */
|
/** 任务变更:自动填充关联字段 */
|
||||||
const handleTaskChange = (task: any) => {
|
const handleTaskChange = async (task: any) => {
|
||||||
if (!task) {
|
if (!task) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
formData.value.routeId = task.routeId
|
formData.value.routeId = task.routeId
|
||||||
formData.value.processId = task.processId
|
formData.value.processId = task.processId
|
||||||
formData.value.workstationId = task.workstationId
|
formData.value.workstationId = task.workstationId
|
||||||
processDisplay.value = task.processCode ? task.processCode + ' - ' + task.processName : ''
|
formData.value.itemId = task.itemId
|
||||||
// TODO @芋艿:加载 checkFlag(查询 routeProcess)
|
await loadCheckFlag(task.routeId, task.processId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 报工单编号生成 ====================
|
/** 生成报工单编号 */
|
||||||
|
|
||||||
/** 生成报工单编号(前端生成) */
|
|
||||||
// TODO @芋艿:这块的生成逻辑;
|
// TODO @芋艿:这块的生成逻辑;
|
||||||
const generateCode = () => {
|
const generateCode = () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
|
@ -323,33 +357,26 @@ const generateCode = () => {
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: string, id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
// TODO @AI:搞成 computed
|
|
||||||
dialogTitle.value =
|
|
||||||
type === 'detail'
|
|
||||||
? '查看生产报工记录'
|
|
||||||
: type === 'create'
|
|
||||||
? '添加生产报工记录'
|
|
||||||
: '修改生产报工记录'
|
|
||||||
formType.value = type
|
formType.value = type
|
||||||
resetForm()
|
resetForm()
|
||||||
|
// 修改/详情时,设置数据
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = await ProFeedbackApi.getFeedback(id)
|
const data = await ProFeedbackApi.getFeedback(id)
|
||||||
formData.value = data as any
|
formData.value = data as any
|
||||||
// 填充显示字段
|
await loadCheckFlag(data.routeId, data.processId)
|
||||||
processDisplay.value = data.processCode ? data.processCode + ' - ' + data.processName : ''
|
|
||||||
checkFlag.value = (data as any).checkFlag || false
|
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 创建模式:自动生成报工单号
|
// 创建模式:自动生成报工单号 + 默认报工人为当前用户
|
||||||
formData.value.code = generateCode()
|
formData.value.code = generateCode()
|
||||||
|
formData.value.feedbackUserId = useUserStore().getUser.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ open })
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success'])
|
const emit = defineEmits(['success'])
|
||||||
|
|
@ -358,6 +385,21 @@ const submitForm = async () => {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = formData.value as unknown as ProFeedbackVO
|
const data = formData.value as unknown as ProFeedbackVO
|
||||||
|
// 提交前根据 checkFlag 对齐数量
|
||||||
|
if (checkFlag.value) {
|
||||||
|
// 质检工序:报工数量即待检数量,合格/不良/废品归零
|
||||||
|
data.uncheckQuantity = data.feedbackQuantity
|
||||||
|
data.qualifiedQuantity = 0
|
||||||
|
data.unqualifiedQuantity = 0
|
||||||
|
data.laborScrapQuantity = 0
|
||||||
|
data.materialScrapQuantity = 0
|
||||||
|
data.otherScrapQuantity = 0
|
||||||
|
} else {
|
||||||
|
// 非质检工序:报工数量 = 合格 + 不良,待检归零
|
||||||
|
data.feedbackQuantity = (data.qualifiedQuantity || 0) + (data.unqualifiedQuantity || 0)
|
||||||
|
data.uncheckQuantity = 0
|
||||||
|
}
|
||||||
|
// 执行提交
|
||||||
if (formType.value === 'create') {
|
if (formType.value === 'create') {
|
||||||
await ProFeedbackApi.createFeedback(data)
|
await ProFeedbackApi.createFeedback(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
|
|
@ -366,6 +408,7 @@ const submitForm = async () => {
|
||||||
message.success(t('common.updateSuccess'))
|
message.success(t('common.updateSuccess'))
|
||||||
}
|
}
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
emit('success')
|
emit('success')
|
||||||
} finally {
|
} finally {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
|
|
@ -383,6 +426,7 @@ const resetForm = () => {
|
||||||
processId: undefined,
|
processId: undefined,
|
||||||
workOrderId: undefined,
|
workOrderId: undefined,
|
||||||
taskId: undefined,
|
taskId: undefined,
|
||||||
|
itemId: undefined,
|
||||||
expireDate: undefined,
|
expireDate: undefined,
|
||||||
feedbackQuantity: 0,
|
feedbackQuantity: 0,
|
||||||
qualifiedQuantity: 0,
|
qualifiedQuantity: 0,
|
||||||
|
|
@ -396,8 +440,7 @@ const resetForm = () => {
|
||||||
approveUserId: undefined,
|
approveUserId: undefined,
|
||||||
remark: undefined
|
remark: undefined
|
||||||
}
|
}
|
||||||
processDisplay.value = ''
|
checkFlag.value = true
|
||||||
checkFlag.value = false
|
|
||||||
formRef.value?.resetFields()
|
formRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,21 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="生产工单" prop="workOrderId">
|
<el-form-item label="生产工单" prop="workOrderId">
|
||||||
<ProWorkOrderSelect v-model="queryParams.workOrderId" placeholder="请选择工单" class="!w-240px" />
|
<ProWorkOrderSelect
|
||||||
|
v-model="queryParams.workOrderId"
|
||||||
|
placeholder="请选择工单"
|
||||||
|
class="!w-240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品物料" prop="itemId">
|
<el-form-item label="产品物料" prop="itemId">
|
||||||
<MdItemSelect v-model="queryParams.itemId" placeholder="请选择产品物料" class="!w-240px" />
|
<MdItemSelect v-model="queryParams.itemId" placeholder="请选择产品物料" class="!w-240px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="报工人" prop="feedbackUserId">
|
<el-form-item label="报工人" prop="feedbackUserId">
|
||||||
<UserSelect v-model="queryParams.feedbackUserId" placeholder="请选择报工人" class="!w-240px" />
|
<UserSelect
|
||||||
|
v-model="queryParams.feedbackUserId"
|
||||||
|
placeholder="请选择报工人"
|
||||||
|
class="!w-240px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="记录人" prop="creator">
|
<el-form-item label="记录人" prop="creator">
|
||||||
<UserSelect v-model="queryParams.creator" placeholder="请选择记录人" class="!w-240px" />
|
<UserSelect v-model="queryParams.creator" placeholder="请选择记录人" class="!w-240px" />
|
||||||
|
|
@ -99,8 +107,14 @@
|
||||||
:show-overflow-tooltip="true"
|
:show-overflow-tooltip="true"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
>
|
>
|
||||||
<!-- TODO @AI:这里点击后,跳转详情;然后,去掉下面的【详情】按钮 -->
|
<!-- DONE @AI:这里点击后,跳转详情;然后,去掉下面的【详情】按钮 -->
|
||||||
<el-table-column label="报工单号" align="center" prop="code" width="160" />
|
<el-table-column label="报工单号" align="center" prop="code" width="160">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="openForm('detail', scope.row.id)">{{
|
||||||
|
scope.row.code
|
||||||
|
}}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="报工类型" align="center" prop="type" width="100">
|
<el-table-column label="报工类型" align="center" prop="type" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :type="DICT_TYPE.MES_PRO_FEEDBACK_TYPE" :value="scope.row.type" />
|
<dict-tag :type="DICT_TYPE.MES_PRO_FEEDBACK_TYPE" :value="scope.row.type" />
|
||||||
|
|
@ -111,7 +125,7 @@
|
||||||
<el-table-column label="生产工单编码" align="center" prop="workOrderCode" width="160" />
|
<el-table-column label="生产工单编码" align="center" prop="workOrderCode" width="160" />
|
||||||
<el-table-column label="产品物料编码" align="center" prop="itemCode" width="120" />
|
<el-table-column label="产品物料编码" align="center" prop="itemCode" width="120" />
|
||||||
<el-table-column label="产品物料名称" align="center" prop="itemName" width="120" />
|
<el-table-column label="产品物料名称" align="center" prop="itemName" width="120" />
|
||||||
<el-table-column label="规格型号" align="center" prop="itemSpec" width="120" />
|
<el-table-column label="规格型号" align="center" prop="itemSpecification" width="120" />
|
||||||
<el-table-column label="单位" align="center" prop="unitMeasureName" width="80" />
|
<el-table-column label="单位" align="center" prop="unitMeasureName" width="80" />
|
||||||
<el-table-column label="报工数量" align="center" prop="feedbackQuantity" width="100" />
|
<el-table-column label="报工数量" align="center" prop="feedbackQuantity" width="100" />
|
||||||
<el-table-column label="报工人" align="center" prop="feedbackUserNickname" width="100" />
|
<el-table-column label="报工人" align="center" prop="feedbackUserNickname" width="100" />
|
||||||
|
|
@ -158,33 +172,18 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 审批中状态:驳回、执行、取消 -->
|
<!-- 审批中状态:驳回、执行、取消 -->
|
||||||
<!-- TODO @AI:把【审批】【驳回】融合,点击后,弹出一个界面,然后里面在通过,不通过; -->
|
<!-- DONE @AI:把【审批】【驳回】融合,点击后弹出一个界面,里面通过/不通过 -->
|
||||||
|
<!-- TODO @AI:弹出,继续是 Form 组件,参考 /Users/yunai/Java/yudao-all-in-one/yudao-ui-admin-vue3/src/views/mes/wm/returnvendor/ReturnVendorForm.vue -->
|
||||||
<template v-if="scope.row.status === MesProFeedbackStatusEnum.APPROVING">
|
<template v-if="scope.row.status === MesProFeedbackStatusEnum.APPROVING">
|
||||||
<el-button
|
<el-button
|
||||||
link
|
link
|
||||||
type="warning"
|
type="primary"
|
||||||
@click="handleReject(scope.row.id)"
|
@click="openApproveDialog(scope.row.id)"
|
||||||
v-hasPermi="['mes:pro-feedback:update']"
|
|
||||||
>
|
|
||||||
驳回
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
link
|
|
||||||
type="success"
|
|
||||||
@click="handleApprove(scope.row.id)"
|
|
||||||
v-hasPermi="['mes:pro-feedback:approve']"
|
v-hasPermi="['mes:pro-feedback:approve']"
|
||||||
>
|
>
|
||||||
审批
|
审批
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 所有状态:详情 -->
|
|
||||||
<el-button
|
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
@click="openForm('detail', scope.row.id)"
|
|
||||||
v-hasPermi="['mes:pro-feedback:query']"
|
|
||||||
>详情</el-button
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -199,6 +198,17 @@
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 -->
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
<FeedbackForm ref="formRef" @success="getList" />
|
<FeedbackForm ref="formRef" @success="getList" />
|
||||||
|
|
||||||
|
<!-- 审批弹窗 -->
|
||||||
|
<Dialog title="审批报工" v-model="approveDialogVisible" width="400px">
|
||||||
|
<div style="text-align: center; padding: 20px 0">
|
||||||
|
<p style="margin-bottom: 20px; font-size: 14px">请确认审批结果</p>
|
||||||
|
<el-button type="success" size="large" @click="handleApprove">通过</el-button>
|
||||||
|
<el-button type="danger" size="large" @click="handleReject" style="margin-left: 24px"
|
||||||
|
>不通过</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
@ -279,24 +289,36 @@ const handleSubmit = async (id: number) => {
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReject = async (id: number) => {
|
// ==================== 审批弹窗 ====================
|
||||||
|
|
||||||
|
const approveDialogVisible = ref(false)
|
||||||
|
const approveTargetId = ref<number>()
|
||||||
|
|
||||||
|
const openApproveDialog = (id: number) => {
|
||||||
|
approveTargetId.value = id
|
||||||
|
approveDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleApprove = async () => {
|
||||||
try {
|
try {
|
||||||
await message.confirm('确认要驳回该报工单吗?')
|
const id = approveTargetId.value!
|
||||||
await ProFeedbackApi.rejectFeedback(id)
|
approveDialogVisible.value = false
|
||||||
message.success('报工单已驳回')
|
const finished = await ProFeedbackApi.approveFeedback(id)
|
||||||
|
if (finished) {
|
||||||
|
message.success('报工单已审批完成')
|
||||||
|
} else {
|
||||||
|
message.success('报工成功,请等待质量检验完成!')
|
||||||
|
}
|
||||||
await getList()
|
await getList()
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleApprove = async (id: number) => {
|
const handleReject = async () => {
|
||||||
try {
|
try {
|
||||||
await message.confirm('确认要审批该报工单吗?')
|
const id = approveTargetId.value!
|
||||||
const status = await ProFeedbackApi.approveFeedback(id)
|
approveDialogVisible.value = false
|
||||||
if (status === MesProFeedbackStatusEnum.UNCHECK) {
|
await ProFeedbackApi.rejectFeedback(id)
|
||||||
message.success('报工成功,请等待质量检验完成!')
|
message.success('报工单已驳回')
|
||||||
} else {
|
|
||||||
message.success('报工单已审批完成')
|
|
||||||
}
|
|
||||||
await getList()
|
await getList()
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue