Compare commits

..

4 Commits

Author SHA1 Message Date
andy
d12738722c 修改 2026-08-14 14:22:26 +08:00
andy
e56f0900c6 Merge branch 'master' of https://git.evo-techina.com/sgc/mes-vue 2026-08-14 14:21:32 +08:00
andy
ef2463ec68 修改 2026-08-14 14:21:14 +08:00
andy
b5e07e6e64 修改 2026-08-10 15:59:53 +08:00
10 changed files with 356 additions and 36 deletions

View File

@ -0,0 +1,86 @@
<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="70" >
<n-input-number
style="width: 100%;"
v-model:value="formDetailData.qty"
placeholder="请输入判定数量" :min="0"
:disabled="disabled"
/>
</n-form-item>
<n-form-item label="备注" label-width="70">
<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,222 @@
<template>
<div style="margin: 20px;padding: 20px;border: 4px double #ccc;border-radius: 10px;">
<div style="margin-bottom: 20px;padding-bottom: 10px;font-size: 18px;color: #145165;border-bottom:1px solid #ccc;"><span style="padding-right: 20px;color: #5c6163;">批次号/SN码</span>{{ formDetailOKData.traceCode }}</div>
<div style="display: flex;justify-content: space-between;flex-wrap: wrap;">
<div style="width: 48%;margin-bottom: 20px;padding:15px 15px 0;border: 2px dashed #ccc;border-radius: 8px;">
<div style="margin-bottom: 20px;padding-bottom: 10px;font-size: 16px;color: #838282;border-bottom:1px solid #ccc;">合格</div>
<SubmitDetailPage1
key="ok"
:disabled="false"
:formDetailData="formDetailOKData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailOKData"
/>
</div>
<div style="width: 48%;margin-bottom: 20px;padding:15px 15px 0;border: 2px dashed #ccc;border-radius: 8px;">
<div style="margin-bottom: 20px;padding-bottom: 10px;font-size: 16px;color: #838282;border-bottom:1px solid #ccc;">报废</div>
<SubmitDetailPage1
key="scrap"
:disabled="false"
:formDetailData="formDetailScrapData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailScrapData"
/>
</div>
<div style="width: 48%;padding: 15px 15px 0;border: 2px dashed #ccc;border-radius: 8px;">
<div style="margin-bottom: 20px;padding-bottom: 10px;font-size: 16px;color: #838282;border-bottom:1px solid #ccc;">返工</div>
<SubmitDetailPage1
key="rework"
:disabled="false"
:formDetailData="formDetailReworkData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailReworkData"
/>
</div>
<div style="width: 48%;padding: 15px 15px 0;border: 2px dashed #ccc;border-radius: 8px;">
<div style="margin-bottom: 20px;padding-bottom: 10px;font-size: 16px;color: #838282;border-bottom:1px solid #ccc;">让步接收</div>
<SubmitDetailPage1
key="conession"
:disabled="false"
:formDetailData="formDetailConcessionData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailConcessionData"
/>
</div>
</div>
</div>
<!-- <n-tabs type="card" animated>
<n-tab-pane name="合格" tab="合格" v-if="showOkTab">
<SubmitDetailPage1
key="ok"
:disabled="false"
:formDetailData="formDetailOKData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailOKData"
/>
</n-tab-pane>
<n-tab-pane name="报废" tab="报废" v-if="showScrapTab">
<SubmitDetailPage1
key="scrap"
:disabled="false"
:formDetailData="formDetailScrapData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailScrapData"
/>
</n-tab-pane>
<n-tab-pane name="返工" tab="返工" v-if="showReworkTab">
<SubmitDetailPage1
key="rework"
:disabled="false"
:formDetailData="formDetailReworkData"
:showTraceCode="showTraceCode"
@update:formDetailData= "handleFormDetailReworkData"
/>
</n-tab-pane>
<n-tab-pane name="让步接收" tab="让步接收" v-if="showConnessionTab">
<SubmitDetailPage1
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, onMounted } from 'vue'
import {
NButton, NSpace, useMessage
} from 'naive-ui'
import {useRoute} from "vue-router";
import {qcResultDetailApi, type QcResultDetail} from "@/api/qcResultDetail.ts";
import { qualityTestingApi} from '@/api/qualityTesting'
import router from '@/router';
import SubmitDetailPage1 from '@/components/SubmitDetailPage1.vue';
const props = defineProps({
showOkTab:Boolean,
showScrapTab:Boolean,
showReworkTab:Boolean,
showConnessionTab:Boolean,
showTraceCode:Boolean,
qcId:Number
})
const message = useMessage()
const route = useRoute()
const traceCode = ref(String(route.params.traceCode))
const emit = defineEmits(['updateSubmitDetail','qcSumitDetail'])
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)
submitDetail.reworkData = formDetailReworkData
}
function handleFormDetailConcessionData(formDetailData:QcResultDetail){
Object.assign(formDetailConcessionData, formDetailData)
submitDetail.concessionData = formDetailConcessionData
}
watch(
submitDetail,
(newVal)=>{
emit('updateSubmitDetail',{...newVal})
},{ deep: true }
)
watch(
submitDetail,
(newVal)=>{
emit('qcSumitDetail',{...newVal})
}
)
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("表单已重置")
}
async function loadData() {
if(props.qcId == -1) return
const resultList = await qcResultDetailApi.selectlistByqcId(props.qcId);
Object.assign(formDetailOKData,{...resultList.formDetailOKData})
Object.assign(formDetailScrapData,{...resultList.formDetailScrapData})
Object.assign(formDetailReworkData, { ...resultList.formDetailReworkData})
Object.assign(formDetailConcessionData, { ...resultList.formDetailConsecctionData })
submitDetail.okData = resultList.formDetailOKData ?? { ...defaultFormDetailData, resultType: 1, handleAction: '下一道工序', actionStatus: 1 }
submitDetail.scrapData = resultList.formDetailScrapData ?? { ...defaultFormDetailData, resultType: 2, handleAction: '报废次品', actionStatus: 1 }
submitDetail.reworkData = resultList.formDetailReworkData ?? { ...defaultFormDetailData, resultType: 3, handleAction: '返工', actionStatus: 1 }
submitDetail.concessionData = resultList.formDetailConsecctionData ?? { ...defaultFormDetailData, resultType: 4, handleAction: '让步接收', actionStatus: 1 }
}
onMounted(()=>{
loadData()
})
</script>

View File

@ -216,12 +216,12 @@ const routes: RouteRecordRaw[] = [
meta: { title: '设备状态监控', icon: 'PulseOutline' } meta: { title: '设备状态监控', icon: 'PulseOutline' }
}, },
// 入库管理 // 入库管理
{ // {
path: 'biz/stockIn', // path: 'biz/stockIn',
name: 'BizStockIn', // name: 'BizStockIn',
component: () => import('@/views/biz/stockIn/index.vue'), // component: () => import('@/views/biz/stockIn/index.vue'),
meta: { title: '入库管理', icon: 'ArchiveOutline' } // meta: { title: '入库管理', icon: 'ArchiveOutline' }
}, // },
// 甘特图排产 // 甘特图排产
{ {
path: 'biz/orderProject/gantt', path: 'biz/orderProject/gantt',

View File

@ -563,7 +563,7 @@ body.dark-theme {
// 页面容器 // 页面容器
.page-container { .page-container {
padding: 20px; padding: 20px;
min-height: calc(100vh - 60px); //min-height: calc(100vh - 60px);
} }
// 搜索表单 // 搜索表单

View File

@ -957,7 +957,7 @@ function handleExport() {
const deviceDocumentConnectionVisible = ref<Boolean>(false) const deviceDocumentConnectionVisible = ref<Boolean>(false)
const title = ref<String>("") const title = ref<String>("")
const deviceDocumentConnection = ref<DeviceDocumentConnection>({}) const deviceDocumentConnection = reactive<any>({})
const connectionLoading = ref<boolean>(false) const connectionLoading = ref<boolean>(false)
const connectionPagination = reactive({ const connectionPagination = reactive({
page: 1, page: 1,
@ -968,7 +968,7 @@ const connectionPagination = reactive({
}) })
const deviceList = ref<Device[]>([]) const deviceList = ref<Device[]>([])
const selectedDeviceIds = ref<Device[]>([]) const selectedDeviceIds = ref<any>([])
function handlerConnectionDevice(row:any) { function handlerConnectionDevice(row:any) {
deviceDocumentConnectionVisible.value = true deviceDocumentConnectionVisible.value = true
@ -1022,7 +1022,7 @@ const loadCreateApi = async ()=>{
} }
async function getDeviceList(id) { async function getDeviceList(id:any) {
try { try {
const res = await deviceApi.getDeviceByNcId({ const res = await deviceApi.getDeviceByNcId({
ncId:id, ncId:id,
@ -1033,7 +1033,7 @@ async function getDeviceList(id) {
connectionPagination.itemCount = res.total connectionPagination.itemCount = res.total
// //
selectedDeviceIds.value = deviceList.value.filter(item=>item.isBind).map(item=>item.id) selectedDeviceIds.value = deviceList.value.filter((item:any) =>item.isBind).map(item=>item.id)
connectionLoading.value = false connectionLoading.value = false
}catch (error) { }catch (error) {
message.error("获取关联异常") message.error("获取关联异常")
@ -1059,7 +1059,7 @@ const deviceColumns:DataTableColumns<Device> = [
{ type: 'selection' }, { type: 'selection' },
{title: '设备名称', key: 'deviceName',width:80}, {title: '设备名称', key: 'deviceName',width:80},
{ title: "关联状态",key:"isBind",width:80, { title: "关联状态",key:"isBind",width:80,
render(row) { render(row:any) {
const val = row.isBind; const val = row.isBind;
if (val) { if (val) {
return h(NTag, { type: "success" }, { default: () => "已关联" }); return h(NTag, { type: "success" }, { default: () => "已关联" });

View File

@ -116,6 +116,7 @@
v-model:value="formData.sectionId" v-model:value="formData.sectionId"
cascade cascade
checkable checkable
default-expand-all
:options="sectionList" :options="sectionList"
/> />
</n-form-item> </n-form-item>

View File

@ -240,14 +240,14 @@ const modalTitle = ref('')
const importModalVisible = ref(false) const importModalVisible = ref(false)
const formRef = ref() const formRef = ref()
const defaultFormData = { const defaultFormData = {
subscriptionKey: '', subscriptionKey: undefined,
title: '', title: '',
subscriptionDeviceIds: '', subscriptionDeviceIds: '',
subscriptionDiscoverField: '', subscriptionDiscoverField: undefined,
notifierMethod:1, notifierMethod:1,
sendingMethod: [], sendingMethod: [],
discoverValue: '', discoverValue: '',
detectionMethod: '', detectionMethod: undefined,
notifier: '', notifier: '',
notifierContent: '', notifierContent: '',
abnormalReporting: undefined, abnormalReporting: undefined,
@ -306,10 +306,18 @@ userApi.getPathList().then(rps => {
}) })
// const itemOptions = computed(() => {
// if (!selectedCategory.value) {
// return [] //
// }
// return allItems[selectedCategory.value] || []
// })
function keyupdate(v:any,n:any) { function keyupdate(v:any,n:any) {
formData.subscriptionDiscoverField = '' formData.subscriptionDiscoverField = null
yiczdopt.value = n.childList yiczdopt.value = n.childList
console.log(v) console.log(v)
console.log(n) console.log(n)
} }
@ -348,7 +356,7 @@ const columns: DataTableColumns<ErrorNotification> = [
minWidth:150, minWidth:150,
render(row) { render(row) {
const vals = Array.isArray(row.subscriptionDeviceIds) ? row.subscriptionDeviceIds : (row.subscriptionDeviceIds ? String(row.subscriptionDeviceIds).split(',') : []) const vals = Array.isArray(row.subscriptionDeviceIds) ? row.subscriptionDeviceIds : (row.subscriptionDeviceIds ? String(row.subscriptionDeviceIds).split(',') : [])
return vals.map(v => deviclist.value.find(o => String(o.value) === String(v))?.label ?? v).filter(Boolean).join(', ') || '-' return vals.map(v => deviclist.value.find((o:any) => String(o.value) === String(v))?.label ?? v).filter(Boolean).join(', ') || '-'
}, },
}, },
@ -386,7 +394,7 @@ const columns: DataTableColumns<ErrorNotification> = [
minWidth:150, minWidth:150,
render(row) { render(row) {
const vals = Array.isArray(row.notifier) ? row.notifier : (row.notifier ? String(row.notifier).split(',') : []) const vals = Array.isArray(row.notifier) ? row.notifier : (row.notifier ? String(row.notifier).split(',') : [])
return vals.map(v => userlist.value.find(o => String(o.value) === String(v))?.label ?? v).filter(Boolean).join(', ') || '-' return vals.map(v => userlist.value.find((o:any) => String(o.value) === String(v))?.label ?? v).filter(Boolean).join(', ') || '-'
}, },
}, },
{ {

View File

@ -393,9 +393,10 @@
</n-gi> </n-gi>
</n-grid> </n-grid>
</n-card> </n-card>
<!--:rules="dispatchrules"-->
<n-form ref="dispatchformRef" :model="dispatchform" <n-form ref="dispatchformRef" :model="dispatchform"
label-placement="left" label-placement="left"
:rules="dispatchrules"
style="margin-top: 10px;" style="margin-top: 10px;"
label-width="80"> label-width="80">
<n-grid :cols="2"> <n-grid :cols="2">
@ -1244,7 +1245,7 @@ function disphand(process: ProcessPlanItemVO, order?: OrderProcessPlanVO) {
dispatchform.sort = entity.sort dispatchform.sort = entity.sort
dispatchform.sectionId = entity.sectionId ?? process.sectionId ?? null dispatchform.sectionId = entity.sectionId ?? process.sectionId ?? null
dispatchform.workshopId = entity.workshopId ?? process.workshopId ?? order?.workshopId ?? null dispatchform.workshopId = entity.workshopId ?? process.workshopId ?? order?.workshopId ?? null
dispatchform.list = [{ sectionId: '', deviceId: '', quantity: remainQty || '',ncId:'' }] dispatchform.list = [{ sectionId: '', deviceId: '', quantity: remainQty+'' || '',ncId:'' }]
} }
function addpgnum() { function addpgnum() {

View File

@ -32,7 +32,7 @@
</div> </div>
<!-- 工具栏 --> <!-- 工具栏 -->
<div class="table-toolbar"> <!-- <div class="table-toolbar">
<n-space> <n-space>
<n-button type="primary" @click="handleAdd"> <n-button type="primary" @click="handleAdd">
<template #icon><n-icon><AddOutline /></n-icon></template> <template #icon><n-icon><AddOutline /></n-icon></template>
@ -51,7 +51,7 @@
删除 删除
</n-button> </n-button>
</n-space> </n-space>
</div> </div> -->
<!-- 表格 --> <!-- 表格 -->
<n-data-table <n-data-table
@ -225,8 +225,9 @@
</n-modal> </n-modal>
<!-- 提交判定明细抽屉 --> <!-- 提交判定明细抽屉 -->
<n-drawer v-model:show="showSubmitOuter" :width="800"> <n-drawer v-model:show="showSubmitOuter" :width="900">
<SumbitDetailCard <SumbitDetailCard1
:mask-closable="false"
:showOkTab="true" :showOkTab="true"
:showScrapTab="true" :showScrapTab="true"
:showReworkTab = true :showReworkTab = true
@ -237,7 +238,8 @@
/> />
<n-space justify="center" style="width: 100%; margin-top: 16px;"> <n-space justify="center" style="width: 100%; margin-top: 16px;">
<n-button size="small" @click="handleReset">重置</n-button> <!-- <n-button size="small" @click="handleReset">重置</n-button> -->
<n-button size="small" @click="showSubmitOuter = false">取消</n-button>
<n-button type="primary" size="small" @click="handleSubmitResultDetail">提交</n-button> <n-button type="primary" size="small" @click="handleSubmitResultDetail">提交</n-button>
</n-space> </n-space>
</n-drawer> </n-drawer>
@ -262,7 +264,7 @@ import {assingReworkApi} from '@/api/assingRework'
import { dictDataApi } from '@/api/org' import { dictDataApi } from '@/api/org'
import {qcResultDetailApi, type QcResultDetail} from "@/api/qcResultDetail.ts"; import {qcResultDetailApi, type QcResultDetail} from "@/api/qcResultDetail.ts";
import SumbitDetailCard from '@/components/SumbitDetailCard.vue' import SumbitDetailCard1 from '@/components/SumbitDetailCard1.vue'
import router from "@/router"; import router from "@/router";
@ -476,7 +478,7 @@ const formRules = {
// //
const columns: DataTableColumns<QualityTesting> = [ const columns: DataTableColumns<QualityTesting> = [
{ type: 'selection' }, // { type: 'selection' },
{ title: '质检编号', key: 'qcNo',align: 'center' }, { title: '质检编号', key: 'qcNo',align: 'center' },
{ {
title: '物料名称', title: '物料名称',
@ -538,9 +540,9 @@ const columns: DataTableColumns<QualityTesting> = [
h(NButton, { size: 'small', quaternary: true, onClick: () => handleEdit(row) }, { h(NButton, { size: 'small', quaternary: true, onClick: () => handleEdit(row) }, {
default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' 编辑'] default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' 编辑']
}), }),
h(NButton, { size: 'small', quaternary: true, type: 'error', onClick: () => handleDelete(row) }, { // h(NButton, { size: 'small', quaternary: true, type: 'error', onClick: () => handleDelete(row) }, {
default: () => [h(NIcon, null, { default: () => h(TrashOutline) }), ' 删除'] // default: () => [h(NIcon, null, { default: () => h(TrashOutline) }), ' ']
}), // }),
h(NDropdown, { h(NDropdown, {
trigger: 'click', // trigger: 'click', //
options: [ options: [
@ -930,7 +932,7 @@ function queryResultDetail(row:any) {
onMounted(() => { onMounted(() => {
loadData() loadData()
loadDictOptions() loadDictOptions()
loadAssignWorkOrder() //loadAssignWorkOrder()
}) })
</script> </script>

View File

@ -16,7 +16,7 @@ export default defineConfig({
emptyOutDir: true emptyOutDir: true
}, },
server: { server: {
host:'192.168.12.4', //true, //host:'192.168.12.4', //true,
port: 3000, port: 3000,
proxy: { proxy: {
'/api': { '/api': {
@ -24,8 +24,8 @@ export default defineConfig({
// target:'http://192.168.12.4:8888/', // target:'http://192.168.12.4:8888/',
//target:'http://192.168.12.230:8888', //target:'http://192.168.12.230:8888',
//target:'http://192.168.5.230:8888', //target:'http://192.168.5.230:8888',
//target:'http://192.168.5.232:8888/', target:'http://192.168.5.232:8888/',
target:'http://localhost:8888', //target:'http://localhost:8888',
changeOrigin: true changeOrigin: true
}, },
'/druid': { '/druid': {