Compare commits

...

2 Commits

Author SHA1 Message Date
shaoleiliu-netizen123
3c02f65a44 Merge branch 'master' of https://git.evo-techina.com/sgc/mes-vue 2026-07-16 11:28:10 +08:00
shaoleiliu-netizen123
b259962512 修改工位 提前明细公共页面 2026-07-16 11:28:08 +08:00
11 changed files with 518 additions and 128 deletions

View File

@ -0,0 +1,84 @@
<template>
<n-form ref="formRef" :model="formDetailData" label-placement="left" label-width="80">
<n-form-item label="批次号/SN码" path="traceCode" label-width="100" v-show="showTraceCode">
<n-input v-model:value="formDetailData.traceCode" disabled />
</n-form-item>
<n-form-item label="判定数量" path="qty" label-width="100" >
<n-input-number v-model:value="formDetailData.qty"
placeholder="请输入判定数量" :min="0"
:disabled="disabled"
/>
</n-form-item>
<n-form-item label="备注" label-width="100">
<n-input
v-model:value="formDetailData.remark"
type="textarea"
placeholder="输入备注原因"
:disabled="disabled"
/>
</n-form-item>
</n-form>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue';
import {qcResultDetailApi,QcResultDetail} from "@/api/qcResultDetail.ts";
const emit = defineEmits(['update:formDetailData'])
const props = defineProps({
id:Number,
formDetailData:Object as () => QcResultDetail,
disabled:Boolean,
showTraceCode:Boolean
})
let formDetailData = ref({...props.formDetailData})
let isInitLoading = true
watch(
()=> props.formDetailData,
(newVal)=>{
formDetailData.value = {...newVal}
},
{ deep: true, immediate: true }
)
watch(
formDetailData,
(newVal)=>{
// if (isInitLoading) {
// isInitLoading = false
// return
// }
emit('update:formDetailData',{...newVal})
},
{ deep: true, flush: 'post' }
)
async function loadData() {
if(!props.id) return
qcResultDetailApi.detail(props.id).then((res:any)=>{
formDetailData.value = { ...formDetailData.value, ...res }
})
}
// watch(() => props.id, (val: Number)=>{
// loadData();
// })
watch(() => props.id, (val: number)=>{
loadData();
})
onMounted(()=>{
loadData()
})
</script>

View File

@ -0,0 +1,138 @@
<template>
<n-tabs type="card" animated>
<n-tab-pane name="合格" tab="合格" v-if="showOkTab">
<SubmitDetailPage
key="ok"
:disabled="false"
:formDetailData="formDetailOKData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailOKData"
/>
</n-tab-pane>
<n-tab-pane name="报废" tab="报废" v-if="showScrapTab">
<SubmitDetailPage
key="scrap"
:disabled="false"
:formDetailData="formDetailScrapData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailScrapData"
/>
</n-tab-pane>
<n-tab-pane name="返工" tab="返工" v-if="showReworkTab">
<SubmitDetailPage
key="rework"
:disabled="false"
:formDetailData="formDetailReworkData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailReworkData"
/>
</n-tab-pane>
<n-tab-pane name="让步接收" tab="让步接收" v-if="showConnessionTab">
<SubmitDetailPage
key="conession"
:disabled="false"
:formDetailData="formDetailConcessionData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailConcessionData"
/>
</n-tab-pane>
</n-tabs>
</template>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import {
NButton, NSpace, useMessage
} from 'naive-ui'
import {useRoute} from "vue-router";
import {QcResultDetail} from "@/api/qcResultDetail.ts";
import { qualityTestingApi} from '@/api/qualityTesting'
import router from '@/router';
import SubmitDetailPage from '@/components/SubmitDetailPage.vue';
const props = defineProps({
showOkTab:Boolean,
showScrapTab:Boolean,
showReworkTab:Boolean,
showConnessionTab:Boolean,
showTraceCode:Boolean,
})
const message = useMessage()
const route = useRoute()
const traceCode = ref(String(route.params.traceCode))
const emit = defineEmits(['updateSubmitDetail'])
const submitDetail = reactive<any>({})
const defaultFormDetailData:QcResultDetail = {
qcId: undefined,
resultType: undefined,
qty: 0,
traceCode: undefined,
defectCode: undefined,
handleAction: undefined,
actionStatus: undefined,
remark: '',
title:undefined,
images:[],
attachments:[]
}
const formDetailOKData = reactive<QcResultDetail>({ ...defaultFormDetailData,traceCode:traceCode.value, resultType: 1,handleAction:'下一道工序',actionStatus:1 })
const formDetailScrapData = reactive<QcResultDetail>({ ...defaultFormDetailData,traceCode:traceCode.value,resultType: 2,handleAction:'报废次品',actionStatus:1 })
const formDetailReworkData = reactive<QcResultDetail>({ ...defaultFormDetailData,traceCode:traceCode.value,resultType: 3,handleAction:'返工',actionStatus:1 })
const formDetailConcessionData = reactive<QcResultDetail>({ ...defaultFormDetailData,traceCode:traceCode.value,resultType: 4,handleAction:'让步接收',actionStatus:1 })
function handleFormDetailOKData(formDetailData:QcResultDetail) {
console.log('===OK表单触发更新===', formDetailData)
Object.assign(formDetailOKData, formDetailData)
submitDetail.okData = formDetailOKData
}
function handleFormDetailScrapData(formDetailData:QcResultDetail) {
console.log('===报废表单触发更新===', formDetailData)
Object.assign(formDetailScrapData, formDetailData)
submitDetail.scrapData = formDetailScrapData
}
function handleFormDetailReworkData(formDetailData:QcResultDetail) {
Object.assign(formDetailReworkData, formDetailData)
}
function handleFormDetailConcessionData(formDetailData:QcResultDetail){
Object.assign(formDetailConcessionData, formDetailData)
}
watch(
submitDetail,
(newVal)=>{
console.log(newVal);
emit('updateSubmitDetail',{...newVal})
},{ deep: true }
)
function handleReset() {
Object.assign(formDetailOKData, { ...defaultFormDetailData, resultType: 1, handleAction: '下一道工序', actionStatus: 1 })
Object.assign(formDetailScrapData, { ...defaultFormDetailData, resultType: 2, handleAction: '报废次品', actionStatus: 1 })
Object.assign(formDetailReworkData, { ...defaultFormDetailData, resultType: 3, handleAction: '返工', actionStatus: 1 })
Object.assign(formDetailConcessionData, { ...defaultFormDetailData, resultType: 4, handleAction: '让步接收', actionStatus: 1 })
message.info("表单已重置")
}
</script>

View File

@ -63,15 +63,6 @@
<n-form ref="formRef" :model="formData" :rules="formRules" label-placement="left" label-width="100px"> <n-form ref="formRef" :model="formData" :rules="formRules" label-placement="left" label-width="100px">
<n-form-item label="设备名称" path="deviceName"> <n-form-item label="设备名称" path="deviceName">
<n-input v-model:value="formData.deviceName" placeholder="请输入设备名称" /> <n-input v-model:value="formData.deviceName" placeholder="请输入设备名称" />
</n-form-item>
<n-form-item label="设备类型" path="deviceTypeId">
<n-select
v-model:value="formData.deviceTypeId"
:options="deviceTypeList"
placeholder="请选择设备类型"
clearable
style="width: 200px"
/>
</n-form-item> </n-form-item>
<n-form-item label="所属工段" path="sectionId"> <n-form-item label="所属工段" path="sectionId">
<n-select <n-select
@ -82,8 +73,14 @@
style="width: 200px" style="width: 200px"
/> />
</n-form-item> </n-form-item>
<n-form-item label="设备规格型号" path="spec"> <n-form-item label="设备类型" path="deviceTypeId">
<n-input v-model:value="formData.spec" placeholder="请输入设备规格型号" /> <n-select
v-model:value="formData.deviceTypeId"
:options="deviceTypeList"
placeholder="请选择设备类型"
clearable
style="width: 200px"
/>
</n-form-item> </n-form-item>
<n-form-item label="生产厂家" path="manufacturer"> <n-form-item label="生产厂家" path="manufacturer">
<n-input v-model:value="formData.manufacturer" placeholder="请输入生产厂家" /> <n-input v-model:value="formData.manufacturer" placeholder="请输入生产厂家" />
@ -148,7 +145,6 @@ import { NButton, NSpace,NTag, NIcon, NUpload, useMessage, useDialog, type DataT
import { SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline, CloudUploadOutline, DownloadOutline } from '@vicons/ionicons5' import { SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline, CloudUploadOutline, DownloadOutline } from '@vicons/ionicons5'
import { deviceApi, type Device } from '@/api/device' import { deviceApi, type Device } from '@/api/device'
import { stationApi, type Station } from '@/api/station'
import { dictDataApi } from '@/api/org' import { dictDataApi } from '@/api/org'
import {sectionApi, type Section} from '@/api/section' import {sectionApi, type Section} from '@/api/section'
@ -193,7 +189,8 @@ const defaultFormData: Device = {
manufactureDate: undefined, manufactureDate: undefined,
workshopId: '', workshopId: '',
remark: '', remark: '',
status:'' status:0,
deviceFlag:'mes_equipment'
} }
const formData = reactive<Device>({ ...defaultFormData }) const formData = reactive<Device>({ ...defaultFormData })
@ -201,6 +198,8 @@ const formData = reactive<Device>({ ...defaultFormData })
const deviceTypeList = ref<{ label: string; value: any ;class:any}[]>([]) const deviceTypeList = ref<{ label: string; value: any ;class:any}[]>([])
const statusList = ref<{ label: string; value: any ;class:any}[]>([]) const statusList = ref<{ label: string; value: any ;class:any}[]>([])
const deviceFlagList = ref<{ label: string; value: any ;class:any}[]>([])
// //
const formRules = { const formRules = {
} }
@ -248,7 +247,8 @@ async function loadData() {
const res = await deviceApi.page({ const res = await deviceApi.page({
page: pagination.page, page: pagination.page,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
deviceCode:searchForm.deviceCode deviceCode:searchForm.deviceCode,
deviceFlag:"mes_equipment"
}) })
tableData.value = res.list tableData.value = res.list
pagination.itemCount = res.total pagination.itemCount = res.total
@ -297,12 +297,7 @@ function handleAdd() {
// //
function handleEdit(row: Device) { function handleEdit(row: Device) {
modalTitle.value = '编辑设备表' modalTitle.value = '编辑设备表'
console.log(row);
Object.assign(formData, row) Object.assign(formData, row)
if (formData.manufactureDate && typeof formData.manufactureDate === 'string') {
formData.manufactureDate = new Date(formData.manufactureDate.replace(' ', 'T')).getTime()
}
modalVisible.value = true modalVisible.value = true
} }
@ -432,6 +427,10 @@ async function loadDictOptions() {
const data = await dictDataApi.listByType("sys_status") const data = await dictDataApi.listByType("sys_status")
statusList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass })) statusList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {} }catch {}
try {
const data = await dictDataApi.listByType("mes_device_flag")
deviceFlagList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
} }

View File

@ -7,7 +7,10 @@
<n-input v-model:value="pauseform.processName" disabled /> <n-input v-model:value="pauseform.processName" disabled />
</n-form-item> </n-form-item>
<n-form-item label="报检数量" path="qcNum"> <n-form-item label="报检数量" path="qcNum">
<n-input v-model:value="pauseform.qcNum" disabled /> <n-input v-model:value="pauseform.qcNum"
:disabled = "qcNumDisabled"
@input="handleQcNumChange"
/>
</n-form-item> </n-form-item>
</n-form> </n-form>
</template> </template>
@ -17,12 +20,14 @@
import { ref, reactive, h, defineProps, onMounted, watch} from 'vue'; import { ref, reactive, h, defineProps, onMounted, watch} from 'vue';
import { info } from '@/api/production' import { info } from '@/api/production'
const props = defineProps<{ const props = defineProps<{
id: number; id: number;
num: number num: number;
qcNumDisabled:boolean
}>(); }>();
const emit = defineEmits(['updateWidth']) const emit = defineEmits(['updateWidth','updateQcNum'])
let pauseform = reactive<any>({ let pauseform = reactive<any>({
id:'', id:'',
@ -38,6 +43,10 @@ async function loadData(){
} }
function handleQcNumChange(){
emit('updateQcNum', pauseform.qcNum)
}
watch(() => props.id, (val: number)=>{ watch(() => props.id, (val: number)=>{
loadData(); loadData();
}) })

View File

@ -95,7 +95,16 @@
</n-modal> </n-modal>
<n-modal v-model:show="modalCheckVisible" preset="card" :title="modalCheckTitle" :style="parentWidth" > <n-modal v-model:show="modalCheckVisible" preset="card" :title="modalCheckTitle" :style="parentWidth" >
<AssingWorkVue v-if="modalCheckData?.businessCode === 'mes_assing_work'" :id="modalCheckData.businessId" :num="modalCheckData.quantity" @updateWidth="handleUpdateWidth"/> <AssingWorkVue v-if="modalCheckData?.businessCode === 'mes_assing_work'"
:id="modalCheckData.businessId"
:num="modalCheckData.quantity"
:qcNumDisabled ="true"
@updateWidth="handleUpdateWidth"/>
<SubmitDetailPage
v-if="modalCheckData?.businessCode === 'mes_quality_testing'"
:id="modalCheckData.businessId"
:disabled="true"
/>
</n-modal> </n-modal>
<!-- 导入弹窗 --> <!-- 导入弹窗 -->
@ -109,6 +118,7 @@ import { SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline,
import { flowingAroundApi, type FlowingAround } from '@/api/flowingAround' import { flowingAroundApi, type FlowingAround } from '@/api/flowingAround'
import { dictDataApi } from '@/api/org' import { dictDataApi } from '@/api/org'
import AssingWorkVue from '@/views/biz/flowingAround/assingWork.vue' import AssingWorkVue from '@/views/biz/flowingAround/assingWork.vue'
import SubmitDetailPage from '@/components/SubmitDetailPage.vue'
const message = useMessage() const message = useMessage()
const dialog = useDialog() const dialog = useDialog()
@ -226,7 +236,7 @@ async function loadData() {
} }
let parentWidth = ref('width: 40%;') let parentWidth = ref('width: 20%;')
function handleUpdateWidth(width:string){ function handleUpdateWidth(width:string){
@ -273,6 +283,8 @@ const modalCheckData = ref<FlowingAround>()
const modalCheckTitle = ref('') const modalCheckTitle = ref('')
// //
function handleView(row: FlowingAround){ function handleView(row: FlowingAround){
console.log(row);
modalCheckTitle.value = '提交详情' modalCheckTitle.value = '提交详情'
modalCheckData.value = row modalCheckData.value = row
modalCheckVisible.value = true modalCheckVisible.value = true

View File

@ -402,7 +402,7 @@ const dispatchLoading = ref(false)
const dispatchformRef = ref() const dispatchformRef = ref()
const dispatchform = reactive<any>({ const dispatchform = reactive<any>({
id: '', name: '', beginTime: '', endTime: '', quantity: '', id: '', name: '', beginTime: '', endTime: '', quantity: '',
list: [{ sectionId:'',deviceId:'',userId: '', quantity: '' }], list: [{ sectionId:'',deviceList:'',userList: '', quantity: '' }],
}) })
const dispatchrules = {} const dispatchrules = {}
@ -606,11 +606,13 @@ function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
dispatchform.beginTime = entity.beginTime dispatchform.beginTime = entity.beginTime
dispatchform.endTime = entity.endTime dispatchform.endTime = entity.endTime
dispatchform.quantity = entity.quantity dispatchform.quantity = entity.quantity
dispatchform.list = [{ sectionId:'',deviceId:'',userId: '', quantity: '' }] dispatchform.orderItemId = entity.orderItemId
dispatchform.sort = entity.sort
dispatchform.list = [{ sectionId:'',deviceList:'',userList: '', quantity: '' }]
} }
function addpgnum() { function addpgnum() {
dispatchform.list.push({ sectionId:'',deviceId:'',userId: '', quantity: '' }) dispatchform.list.push({ sectionId:'',deviceList:'',userList: '', quantity: '' })
} }
function deletenum(index: number) { function deletenum(index: number) {
@ -619,13 +621,17 @@ function deletenum(index: number) {
function dispatchSubmit() { function dispatchSubmit() {
let total = 0 let total = 0
dispatchform.list.forEach((n: any) => { total += Number(n.quantity) || 0 }) dispatchform.list.forEach((n: any) => {
total += Number(n.quantity) || 0
})
dispatchformRef.value?.validate((v: boolean) => { dispatchformRef.value?.validate((v: boolean) => {
if (v) return if (v) return
if (total !== Number(dispatchform.quantity)) { if (total !== Number(dispatchform.quantity)) {
message.error('派工总数量需等于生产总数', { duration: 4000 }) message.error('派工总数量需等于生产总数', { duration: 4000 })
return return
} }
dispatchLoading.value = true dispatchLoading.value = true
orderProcessPlanApi.assignWork(dispatchform).then(() => { orderProcessPlanApi.assignWork(dispatchform).then(() => {
message.success('派工成功') message.success('派工成功')

View File

@ -27,19 +27,28 @@
<n-gi :span="10"> <n-gi :span="10">
<n-form-item <n-form-item
label="指派工位" label="指派工位"
:path="`${listname}[${index}].deviceId`" :path="`${listname}[${index}].deviceList`"
:rule="{ :rule="{
required:true, required:true,
message:`请选择工位`, message:`请选择工位`,
trigger: 'blur' trigger: 'blur',
validator: (rule, value, callback) => {
// value
if (!Array.isArray(value) || value.length === 0) {
callback(new Error('请选择工位'))
} else {
callback()
}
}
}" }"
> >
<n-select <n-select
v-model:value="obj.deviceId" v-model:value="obj.deviceList"
filterable filterable
placeholder="请选择工位" placeholder="请选择工位"
:options="deviceList" :options="deviceList"
:loading="loadingRef" :loading="loadingRef"
multiple
clearable clearable
remote remote
:clear-filter-after-select="false" :clear-filter-after-select="false"
@ -53,21 +62,30 @@
<n-gi :span="10"> <n-gi :span="10">
<n-form-item <n-form-item
label="分配人员" label="分配人员"
:path="`${listname}[${index}].userId`" :path="`${listname}[${index}].userList`"
:rule="{ :rule="{
required: true, required: true,
message: '请选择员工', message: '请选择员工',
trigger: 'blur' trigger: 'blur',
validator: (rule, value, callback) => {
// value
if (!Array.isArray(value) || value.length === 0) {
callback(new Error('请选择员工'))
} else {
callback()
}
}
}" }"
> >
<!--multiple--> <!--multiple-->
<n-select <n-select
v-model:value="obj.userId" v-model:value="obj.userList"
filterable filterable
placeholder="请输入用户名称搜索" placeholder="请输入用户名称搜索"
:options="yglist" :options="yglist"
:loading="loadingRef" :loading="loadingRef"
clearable clearable
multiple
remote remote
:clear-filter-after-select="false" :clear-filter-after-select="false"
@search="slehand" @search="slehand"

View File

@ -466,6 +466,7 @@ const columns: DataTableColumns<QualityTesting> = [
// { title: 'ID', key: 'orderId' }, // { title: 'ID', key: 'orderId' },
// { title: 'ID', key: 'processId' }, // { title: 'ID', key: 'processId' },
// { title: 'ID', key: 'itemId' }, // { title: 'ID', key: 'itemId' },
{ title: '追溯码', key: 'traceCode',align: 'center' },
{ title: '报检总数', key: 'totalQty',align: 'center' }, { title: '报检总数', key: 'totalQty',align: 'center' },
{ title: '已检验数量', key: 'inspectQty',align: 'center' }, { title: '已检验数量', key: 'inspectQty',align: 'center' },
{ title: '质检状态', key: 'status',align: 'center', { title: '质检状态', key: 'status',align: 'center',
@ -508,12 +509,12 @@ const columns: DataTableColumns<QualityTesting> = [
{ label: '查看详情', key: 'view' }, { label: '查看详情', key: 'view' },
{ type: 'divider' }, // 线 { type: 'divider' }, // 线
{ label: '提交判定明细', key: 'submitResultDetail',show:row.status == 1 }, { label: '提交判定明细', key: 'submitResultDetail',show:row.status == 1 },
{ type: 'divider',show:row.status == 1 }, // 线 // { type: 'divider',show:row.status == 1 }, // 线
{ label: '提交部分判定明细', key: 'submitBFResultDetail',show:(row.status == 1 || row.status == 2) }, // { label: '', key: 'submitBFResultDetail',show:(row.status == 1 || row.status == 2) },
{ type: 'divider',show:(row.status == 1 || row.status == 2) }, // 线 { type: 'divider',show:(row.status == 1 || row.status == 2) }, // 线
{ label: '查询判定明细', key: 'queryResultDetail' }, { label: '查询判定明细', key: 'queryResultDetail' },
{ type: 'divider' }, // 线 // { type: 'divider' }, // 线
{ label: '质检撤回', key: 'cancelQuality' }, // { label: '', key: 'cancelQuality' },
], ],
// //
onSelect: (key: string) => { onSelect: (key: string) => {
@ -524,15 +525,15 @@ const columns: DataTableColumns<QualityTesting> = [
case 'submitResultDetail': case 'submitResultDetail':
submitResultDetail(row) submitResultDetail(row)
break break
case 'submitBFResultDetail': // case 'submitBFResultDetail':
submitBFResultDetail(row) // submitBFResultDetail(row)
break // break
case 'queryResultDetail': case 'queryResultDetail':
queryResultDetail(row) queryResultDetail(row)
break break
case 'cancelQuality': // case 'cancelQuality':
handleCancelQuality(row) // handleCancelQuality(row)
break // break
} }
} }
}, { }, {
@ -844,7 +845,7 @@ function submitResultDetail(row:any) {
submitFlag.value = true submitFlag.value = true
let path = `/qc/submitDetail/${row.qcNo}/${row.id}/${submitFlag.value}/${traceCodeShow.value}` let path = `/qc/submitDetail/${row.qcNo}/${row.id}/${submitFlag.value}/${row.traceCode}`
router.push(path) router.push(path)
} }

View File

@ -4,8 +4,8 @@
<!-- 搜索表单 --> <!-- 搜索表单 -->
<div class="search-form"> <div class="search-form">
<n-form inline :model="searchForm" label-placement="left"> <n-form inline :model="searchForm" label-placement="left">
<n-form-item label="工位编码"> <n-form-item label="主键ID">
<n-input v-model:value="searchForm.stationCode" placeholder="请输入工位编码" clearable /> <n-input v-model:value="searchForm.deviceCode" placeholder="请输入工位编码" clearable />
</n-form-item> </n-form-item>
<n-form-item> <n-form-item>
<n-space> <n-space>
@ -61,8 +61,8 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<n-modal v-model:show="modalVisible" preset="card" :title="modalTitle" style="width: 600px"> <n-modal v-model:show="modalVisible" preset="card" :title="modalTitle" style="width: 600px">
<n-form ref="formRef" :model="formData" :rules="formRules" label-placement="left" label-width="100px"> <n-form ref="formRef" :model="formData" :rules="formRules" label-placement="left" label-width="100px">
<n-form-item label="工位名称" path="stationName"> <n-form-item label="工位名称" path="deviceName">
<n-input v-model:value="formData.stationName" placeholder="请输入工位名称" /> <n-input v-model:value="formData.deviceName" placeholder="请输入设备名称" />
</n-form-item> </n-form-item>
<n-form-item label="所属工段" path="sectionId"> <n-form-item label="所属工段" path="sectionId">
<n-select <n-select
@ -92,7 +92,7 @@
</n-modal> </n-modal>
<!-- 导入弹窗 --> <!-- 导入弹窗 -->
<n-modal v-model:show="importModalVisible" preset="card" title="导入工位表" style="width: 500px"> <n-modal v-model:show="importModalVisible" preset="card" title="导入设备表" style="width: 500px">
<n-space vertical> <n-space vertical>
<n-alert type="info"> <n-alert type="info">
<template #header>导入说明</template> <template #header>导入说明</template>
@ -128,20 +128,24 @@
import { ref, reactive, h, onMounted } from 'vue' import { ref, reactive, h, onMounted } from 'vue'
import { NButton, NSpace,NTag, NIcon, NUpload, useMessage, useDialog, type DataTableColumns, type UploadCustomRequestOptions } from 'naive-ui' import { NButton, NSpace,NTag, NIcon, NUpload, useMessage, useDialog, type DataTableColumns, type UploadCustomRequestOptions } from 'naive-ui'
import { SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline, CloudUploadOutline, DownloadOutline } from '@vicons/ionicons5' import { SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline, CloudUploadOutline, DownloadOutline } from '@vicons/ionicons5'
import { stationApi, type Station } from '@/api/station' import { deviceApi, type Device } from '@/api/device'
import { dictDataApi } from '@/api/org' import { dictDataApi } from '@/api/org'
import {sectionApi, type Section} from '@/api/section' import {sectionApi, type Section} from '@/api/section'
const message = useMessage() const message = useMessage()
const dialog = useDialog() const dialog = useDialog()
let sectionList = reactive<{label:string,value:any}[]>([])
// //
const searchForm = reactive({ const searchForm = reactive({
stationCode: null as string | null, deviceCode: null as number | null,
}) })
// //
const tableData = ref<Station[]>([]) const tableData = ref<Device[]>([])
const loading = ref(false) const loading = ref(false)
const selectedIds = ref<number[]>([]) const selectedIds = ref<number[]>([])
const pagination = reactive({ const pagination = reactive({
@ -157,42 +161,48 @@ const modalVisible = ref(false)
const modalTitle = ref('') const modalTitle = ref('')
const importModalVisible = ref(false) const importModalVisible = ref(false)
const formRef = ref() const formRef = ref()
const defaultFormData: Station = { const defaultFormData: Device = {
id:'', id:"",
stationCode: '', deviceCode: '',
stationName: '', deviceName: '',
sectionId: undefined, deviceTypeId: undefined,
status:undefined, deviceType:"",
remark:undefined sectionId: "",
sectionName:"",
spec: '',
manufacturer: '',
manufactureDate: undefined,
workshopId: '',
remark: '',
status:0,
deviceFlag:'mes_station'
} }
const formData = reactive<Station>({ ...defaultFormData }) const formData = reactive<Device>({ ...defaultFormData })
let sectionList = reactive<{label:string,value:any}[]>([])
// //使 // //使
const deviceTypeList = ref<{ label: string; value: any ;class:any}[]>([])
const statusList = ref<{ label: string; value: any ;class:any}[]>([]) const statusList = ref<{ label: string; value: any ;class:any}[]>([])
const deviceFlagList = ref<{ label: string; value: any ;class:any}[]>([])
// //
const formRules = { const formRules = {
} }
// //
const columns: DataTableColumns<Station> = [ const columns: DataTableColumns<Device> = [
{ type: 'selection' }, { type: 'selection' },
{ title: '工位编码', key: 'stationCode' }, { title: '工位编码', key: 'deviceCode' },
{ title: '工位名称', key: 'stationName' }, { title: '工位名称', key: 'deviceName' },
{ title: '所属工段', key: 'sectionName' }, { title: '所属工段', key: 'sectionName' },
{ title: '备注', key: 'remark' }, { title: '状态', key: 'status',
{ title: '启用状态', key: 'status',
render:(row) =>{ render:(row) =>{
const val = row.status const val = row.status
const opt = statusList.value.find(o => o.value === val || String(o.value) === String(val)) const opt = statusList.value.find(o => o.value === val || String(o.value) === String(val))
if (!opt) return val ?? '-' if (!opt) return val ?? '-'
return h(NTag, { type: opt.class, size: 'small' }, { default: () => opt.label }) return h(NTag, { type: opt.class, size: 'small' }, { default: () => opt.label })
} }
}, },
{ title: '创建时间', key: 'createTime' },
{ {
title: '操作', title: '操作',
key: 'actions', key: 'actions',
@ -215,10 +225,11 @@ const columns: DataTableColumns<Station> = [
async function loadData() { async function loadData() {
loading.value = true loading.value = true
try { try {
const res = await stationApi.page({ const res = await deviceApi.page({
page: pagination.page, page: pagination.page,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
stationCode: searchForm.stationCode || undefined, deviceCode:searchForm.deviceCode,
deviceFlag:"mes_station"
}) })
tableData.value = res.list tableData.value = res.list
pagination.itemCount = res.total pagination.itemCount = res.total
@ -235,7 +246,7 @@ function handleSearch() {
// //
function handleReset() { function handleReset() {
searchForm.stationCode = null searchForm.deviceCode = null
handleSearch() handleSearch()
} }
@ -259,14 +270,16 @@ function handleCheck(keys: Array<string | number>) {
// //
function handleAdd() { function handleAdd() {
modalTitle.value = '新增工位表' modalTitle.value = '新增设备表'
Object.assign(formData, defaultFormData) Object.assign(formData, defaultFormData)
modalVisible.value = true modalVisible.value = true
} }
// //
function handleEdit(row: Station) { function handleEdit(row: Device) {
modalTitle.value = '编辑工位表' modalTitle.value = '编辑设备表'
console.log(row);
Object.assign(formData, row) Object.assign(formData, row)
modalVisible.value = true modalVisible.value = true
} }
@ -275,12 +288,12 @@ function handleEdit(row: Station) {
async function handleSubmit() { async function handleSubmit() {
await formRef.value?.validate() await formRef.value?.validate()
try { try {
const submitData = { ...formData } as Station const submitData = { ...formData } as Device
if (submitData.id) { if (submitData.id) {
await stationApi.update(submitData) await deviceApi.update(submitData)
message.success('修改成功') message.success('修改成功')
} else { } else {
await stationApi.create(submitData) await deviceApi.create(submitData)
message.success('新增成功') message.success('新增成功')
} }
modalVisible.value = false modalVisible.value = false
@ -291,7 +304,7 @@ async function handleSubmit() {
} }
// //
function handleDelete(row: Station) { function handleDelete(row: Device) {
dialog.warning({ dialog.warning({
title: '提示', title: '提示',
content: '确定要删除该记录吗?', content: '确定要删除该记录吗?',
@ -299,7 +312,7 @@ function handleDelete(row: Station) {
negativeText: '取消', negativeText: '取消',
onPositiveClick: async () => { onPositiveClick: async () => {
try { try {
await stationApi.delete([row.id!]) await deviceApi.delete([row.id!])
message.success('删除成功') message.success('删除成功')
loadData() loadData()
} catch (error) { } catch (error) {
@ -318,7 +331,7 @@ function handleBatchDelete() {
negativeText: '取消', negativeText: '取消',
onPositiveClick: async () => { onPositiveClick: async () => {
try { try {
await stationApi.delete(selectedIds.value) await deviceApi.delete(selectedIds.value)
message.success('删除成功') message.success('删除成功')
selectedIds.value = [] selectedIds.value = []
loadData() loadData()
@ -334,12 +347,12 @@ async function handleExport() {
try { try {
const params: Record<string, any> = {} const params: Record<string, any> = {}
if (selectedIds.value.length > 0) params.ids = selectedIds.value if (selectedIds.value.length > 0) params.ids = selectedIds.value
if (searchForm.stationCode != null) params.stationCode = searchForm.stationCode if (searchForm.deviceCode != null) params.deviceCode = searchForm.deviceCode
const blob = await stationApi.export(params) const blob = await deviceApi.export(params)
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') const link = document.createElement('a')
link.href = url link.href = url
link.download = '工位表数据.xlsx' link.download = '设备表数据.xlsx'
link.click() link.click()
window.URL.revokeObjectURL(url) window.URL.revokeObjectURL(url)
} catch (error) { } catch (error) {
@ -350,11 +363,11 @@ async function handleExport() {
// //
async function handleDownloadTemplate() { async function handleDownloadTemplate() {
try { try {
const blob = await stationApi.downloadTemplate() const blob = await deviceApi.downloadTemplate()
const url = window.URL.createObjectURL(blob) const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') const link = document.createElement('a')
link.href = url link.href = url
link.download = '工位表导入模板.xlsx' link.download = '设备表导入模板.xlsx'
link.click() link.click()
window.URL.revokeObjectURL(url) window.URL.revokeObjectURL(url)
} catch (error) { } catch (error) {
@ -366,7 +379,7 @@ async function handleDownloadTemplate() {
async function handleImportUpload({ file }: UploadCustomRequestOptions) { async function handleImportUpload({ file }: UploadCustomRequestOptions) {
if (!file.file) return if (!file.file) return
try { try {
const result = await stationApi.importData(file.file) const result = await deviceApi.importData(file.file)
if (result.fail > 0) { if (result.fail > 0) {
dialog.warning({ dialog.warning({
title: '导入结果', title: '导入结果',
@ -385,10 +398,19 @@ async function handleImportUpload({ file }: UploadCustomRequestOptions) {
// //
async function loadDictOptions() { async function loadDictOptions() {
try {
const data = await dictDataApi.listByType("device_type")
deviceTypeList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
try { try {
const data = await dictDataApi.listByType("sys_status") const data = await dictDataApi.listByType("sys_status")
statusList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass })) statusList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {} }catch {}
try {
const data = await dictDataApi.listByType("mes_device_flag")
deviceFlagList.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
} }

View File

@ -496,6 +496,24 @@ const columns = [
key: 'processName', key: 'processName',
minWidth: 200 minWidth: 200
}, },
{
align:'center',
title:"追溯类型",
key:"traceType",
render(row:any) {
const val = row.traceType
if(val == 1) return '-'
if(val == 2) return '追溯码'
if(val == 3) return '批次码'
},
minWidth:80
},
// {
// align:'center',
// title:"/",
// key:"traceCode",
// minWidth:200
// },
{ {
align:'center', align:'center',
title: '派工状态', title: '派工状态',
@ -557,6 +575,26 @@ const columns = [
key: 'reworkNum', key: 'reworkNum',
minWidth: 150 minWidth: 150
}, },
{
align:'center',
title:"是否质检",
key:"isQual",
minWidth:100,
render(row:any) {
const qual = row.isQual === 1
return h(NTag, {type: qual ? 'error' : 'success', size: 'small'}, {default: () => (qual ? '是' : '否')})
}
},
{
align:'center',
title:"是否直接入库",
key:"isStorage",
minWidth:120,
render(row:any) {
const storage = row.isQual === 1
return h(NTag, {type: storage ? 'error' : 'success', size: 'small'}, {default: () => (storage ? '是' : '否')})
}
},
{ {
align:'center', align:'center',
title: '完成数量', title: '完成数量',

View File

@ -120,24 +120,20 @@
style="width: 400px" style="width: 400px"
:mask-closable="false" :mask-closable="false"
> >
<AssingWorkVue
:id="gxobg.id"
:qcNumDisabled ="false"
@updateQcNum="handleUpdateQcNum"
/>
<SumbitDetailCard
:showOkTab="true"
:showScrapTab="true"
:showReworkTab = false
:showTraceCode="false"
@updateSubmitDetail="handleSubmitDetail"
/>
<n-form
ref="pauseformRef"
:model="pauseform"
:rules="pauserules"
label-placement="top"
label-width="80"
>
<n-form-item label="工序编号">
<n-input v-model:value="gxobg.id" disabled />
</n-form-item>
<n-form-item label="工序名称">
<n-input v-model:value="gxobg.name" disabled />
</n-form-item>
<n-form-item label="报检数量" path="qcNum">
<n-input v-model:value="pauseform.qcNum" placeholder="请输入报检数量" />
</n-form-item>
</n-form>
<template #footer> <template #footer>
<n-space justify="end"> <n-space justify="end">
<n-button @click="pausemodal = false">取消</n-button> <n-button @click="pausemodal = false">取消</n-button>
@ -152,6 +148,7 @@
</n-modal> </n-modal>
</div> </div>
</template> </template>
@ -174,7 +171,7 @@ import {
// NGi, // NGi,
NTag, NTag,
useMessage, useMessage,
//useDialog, useDialog,
//type FormInst, //type FormInst,
} from 'naive-ui' } from 'naive-ui'
@ -191,8 +188,11 @@ import {
} from '@/api/production' } from '@/api/production'
import PlmModelDrawer from '@/components/PlmModelDrawer.vue' import PlmModelDrawer from '@/components/PlmModelDrawer.vue'
import type { PlmModelOpenContext } from '@/api/plmModel' import type { PlmModelOpenContext } from '@/api/plmModel'
import AssingWorkVue from '@/views/biz/flowingAround/assingWork.vue'
import { qualityTestingApi, type QualityTesting } from '@/api/qualityTesting'
import SumbitDetailCard from '@/components/SumbitDetailCard.vue'
//const dialog = useDialog() const dialog = useDialog()
const message = useMessage() const message = useMessage()
@ -431,7 +431,7 @@ const columns = [
align:'center', align:'center',
title: '操作', title: '操作',
key: 'actions', key: 'actions',
width: 100, width: 250,
fixed: 'right', fixed: 'right',
render(row:any) { render(row:any) {
const buttons:any = [] const buttons:any = []
@ -442,7 +442,7 @@ const columns = [
type:'primary', type:'primary',
ghost:true, ghost:true,
onClick: () => { handlpause(row) } }, onClick: () => { handlpause(row) } },
{ default: () => ''} { default: () => '完工汇报'}
)) ))
} }
buttons.push(h(NButton, { buttons.push(h(NButton, {
@ -452,6 +452,13 @@ const columns = [
onClick: () => openPlmModel(row), onClick: () => openPlmModel(row),
}, { default: () => '模型' })) }, { default: () => '模型' }))
buttons.push(h(NButton, {
size: 'small',
type: 'info',
ghost: true,
onClick: ()=> cancelQuality(row)
}, { default: () => '质检撤回' }))
return buttons.length > 0 ? h(NSpace, {justify:'center'}, { default: () => buttons }) : '-' return buttons.length > 0 ? h(NSpace, {justify:'center'}, { default: () => buttons }) : '-'
} }
} }
@ -506,7 +513,9 @@ let gxobg = reactive<any>({})
let pausemodal = ref(false) let pausemodal = ref(false)
let pauseform = reactive<any>({ let pauseform = reactive<any>({
id:'', id:'',
qcNum:'' qcNum:'',
okData:undefined,
scrapData:undefined
}) })
const pauseformRef = ref() const pauseformRef = ref()
@ -542,12 +551,38 @@ function handlpause(n:any) {
pauseformRef.value?.restoreValidation() pauseformRef.value?.restoreValidation()
pauseform.id = n.id pauseform.id = n.id
//pauseform.qcNum = `${n.quantity}` //pauseform.qcNum = `${n.quantity}`
pauseform.qcNum = n.quantity-(n.completedQuantity ?? 0) // pauseform.qcNum = n.quantity-(n.completedQuantity ?? 0)
}
function checkPauseSumbit():boolean {
if(pauseform.id == null) {
message.error("参数id为空")
return false
}
if(pauseform.qcNum == null || pauseform.qcNum == '') {
message.error("质检数量不能为空")
return false
}
//
const checkNum = pauseform.okData?.qty + pauseform.scrapData?.qty
if(checkNum != pauseform.qcNum) {
message.error("汇报数量总和不等于提交数量")
return false
}
return true
} }
function pauseSubmit() { function pauseSubmit() {
pauseformRef.value?.validate((v:any) => {
if(!v){ var pass = checkPauseSumbit();
console.log(pass);
if(!pass) return
pauseLoading.value = true pauseLoading.value = true
pauseisedbtn.value = true pauseisedbtn.value = true
inspectio(Object.assign({},pauseform,{qcNum:pauseform.qcNum*1})).then(() => { inspectio(Object.assign({},pauseform,{qcNum:pauseform.qcNum*1})).then(() => {
@ -562,8 +597,19 @@ function pauseSubmit() {
pauseLoading.value = false pauseLoading.value = false
pauseisedbtn.value = false pauseisedbtn.value = false
}) })
} }
})
function handleUpdateQcNum(qcNum:number) {
pauseform.qcNum = qcNum
}
function handleSubmitDetail(submitDetail:any){
pauseform.okData = submitDetail.okData
pauseform.scrapData = submitDetail.scrapData
console.log(pauseform);
} }
// //
@ -588,9 +634,26 @@ async function loadDictOptions() {
// } // }
// }) // })
// } // }
function cancelQuality(row:any) {
dialog.warning({
title: '提示',
content: '确定要撤回质检记录吗?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: async () => {
try {
await qualityTestingApi.cancel(row.id)
message.success('撤回成功')
getlist()
} catch (error) {
console.log("撤回失败"+error)
}
}
})
}
onMounted(() => { onMounted(() => {
getlist() getlist()
loadDictOptions() loadDictOptions()