派工管理添加查询汇报详情功能

This commit is contained in:
shaoleiliu-netizen123 2026-06-03 13:07:40 +08:00
parent 3a7ffef12f
commit 8f2faf04b0
3 changed files with 272 additions and 61 deletions

View File

@ -71,5 +71,11 @@ export const submitLogApi = {
//汇报统计
statistics(params?: {time?:string; type?:string}){
return request({url:'/mes/report/statistics',method:'get',params})
},
//按派工单id查询汇报
getByDispatch(dispatchId:number){
return request({url:`/mes/report/bydispatch/${dispatchId}`,method:"get"})
}
}

View File

@ -243,6 +243,21 @@ const formRules = {
//
const columns: DataTableColumns<SubmitLog> = [
{ type: 'selection' },
{ title: '物料名称', key: 'materialName',align: 'center',
render(rowData, rowIndex) {
return rowData.materialName? rowData.materialName: '-'
},
},
{ title: '物料编码', key: 'materialCode',align: 'center',
render(rowData, rowIndex) {
return rowData.materialCode? rowData.materialCode: '-'
},
},
{ title: '物料数量', key: 'materialQty',align: 'center',
render(rowData, rowIndex) {
return rowData.materialQty? rowData.materialQty: '-'
},
},
{ title: '工序名称', key: 'processName',align: 'center' },
{ title: '工序编号', key: 'processCode',align: 'center' },
{ title: '派工编号', key: 'assingCode',align: 'center' },

View File

@ -259,6 +259,76 @@
</template>
</n-modal>
<!--查询汇报详情-->
<n-modal v-model:show="reportDetailVisible" preset="card" :title="reportDetailTitle" style="width: 800px">
<n-card hoverable style="margin-bottom: 12px" >
<template #header>
<div style="display:flex;justify-content:space-between;align-items:center;width:100%">
<span>主表信息</span>
<n-button text @click="infoIsCollapse = !infoIsCollapse">
<n-icon :component="infoIsCollapse ? ArrowDownOutline : ArrowUpOutline" />
</n-button>
</div>
</template>
<n-descriptions :column="3" bordered v-show="!infoIsCollapse">
<n-descriptions-item
v-for="item in mappedInfoList"
:key="item.key"
:label="item.label"
>
{{ formatDisplayValue(item.key, item.value) }}
</n-descriptions-item>
</n-descriptions>
</n-card>
<n-card title="汇报信息" hoverable style="margin-bottom: 12px" >
<div v-if="qualityTestings.length === 0" style="height:520px;display:flex;align-items:center;justify-content:center;color:#999">
暂无质检单据数据
</div>
<n-tabs
type="line"
animated
placement="left"
style="height: 520px"
v-else>
<n-tab-pane
v-for="item in qualityTestings"
:name="item.qcNo"
:tab="item.qcNo">
<n-card title="质检基础信息" style="margin-bottom:12px">
<n-descriptions :column="3">
<n-descriptions-item label="资源类型">{{formatDisplayValue("resourceType",item.resourceType) }}</n-descriptions-item>
<n-descriptions-item label="质检状态">{{formatDisplayValue("status",item.qcStatus) }}</n-descriptions-item>
<n-descriptions-item label="总数量">{{ item.totalQty }}</n-descriptions-item>
</n-descriptions>
</n-card>
<!--汇报表格-->
<n-card title="汇报列表">
<n-data-table
:columns="submitColumns"
:data="item.submitLogs"
:scroll-x="700"
max-height="320"
:pagination="{ pageSize:3 }"
>
<!--空数据提示插槽-->
<template #empty>
<div style="padding:40px;text-align:center;color:#999">
当前没有数据
</div>
</template>
</n-data-table>
</n-card>
</n-tab-pane>
</n-tabs>
</n-card>
</n-modal>
</div>
</template>
@ -273,6 +343,7 @@ import {
import {
NButton,
NDropdown,
NIcon,
NSpace,
NPagination,
@ -283,14 +354,12 @@ import {
//useDialog,
type FormInst,
} from 'naive-ui'
import {
SearchOutline,
RefreshOutline
import {
SearchOutline, RefreshOutline, AddOutline, TrashOutline, CreateOutline, CloudUploadOutline, DownloadOutline,
EllipsisHorizontalOutline, ArrowDownOutline, ArrowUpOutline
} from '@vicons/ionicons5'
import { useUserStore } from '@/stores/user'
import { dictDataApi } from '@/api/org'
import {
disworlist,
editdiswor,
@ -299,6 +368,9 @@ import {
//workload
} from '@/api/production'
import { submitLogApi } from '@/api/submitLog'
import { an } from 'vue-router/dist/router-CWoNjPRp.mjs'
//const dialog = useDialog()
const message = useMessage()
@ -308,6 +380,40 @@ const userStore = useUserStore()
//
const hasPermission = (permission: string) => userStore.hasPermission(permission)
//
const qcResultTypeOptions = ref<{ label: string; value: any }[]>([])
//
const qcSourceTypeOptions = ref<{ label: string; value: any }[]>([])
//
const qcStatusOptions = ref<{ label: string; value: any }[]>([])
//
const qcAssingStatusOptions = ref<{ label: string; value: any }[]>([])
//
const infoIsCollapse = ref(false)
const reportDetailVisible = ref(false)
const reportDetailTitle = ref<string>('')
const mappedInfoList = ref<Array<{ label: string; key: string; value: any }>>([])
const qualityTestings = ref<any[]>([])
const submitColumns = ref([
{ title: "提交人", key: "sumbitUser" },
{ title: "提交时间", key: "submitCreateTime" },
{ title: "提交数量", key: "quantity" },
{ title: "单据状态", key: "submitStatus",
render: (row) => {
const val = row.submitStatus
const opt = qcResultTypeOptions.value.find(o => o.value === val || String(o.value) === String(val))
if (!opt) return val ?? '-'
return h(NTag, { type: opt.class, size: 'small' }, { default: () => opt.label })
}
}
])
// ==================== ====================
const searchForm = reactive({
@ -491,52 +597,79 @@ const columns = [
width: 200,
fixed: 'right',
render(row:any) {
const buttons:any = [
// h(NButton, {
// size: 'small',
// type:'warning',
// ghost:true,
// onClick: () => handleEdit(row) },
// //{ default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' ' ]}
// { default: () => ''}
// )
]
return h('div',{ style: { display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap' } },[
h(NButton, { size: 'small', quaternary: true, onClick: () => handleEdit(row) }, {
default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' 编辑']
}),
h(NDropdown, {
trigger:'click',
options:[
{label:"改派",key:'transfer'},
{type: 'divider' }, // 线
{label:'暂停',key:'pauseResume'},
{type: 'divider' }, // 线
{label:'查看汇报',key:'view'},
],
onSelect:(key:string)=>{
switch(key) {
case "transfer":
handlreass(row)
break
case "pauseResume":
handlpause(row)
break
case "view":
handleViewReport(row.id)
break
}
}
},{
// /
default: () => h(NButton, { size: 'small', quaternary: true }, {
default: () => [h(NIcon, null, { default: () => h(EllipsisHorizontalOutline) })]
})
})
])
// const buttons:any = [
// ]
if(hasPermission('biz:assingWork:edit')){
buttons.push(h(NButton, {
size: 'small',
type:'primary',
ghost:true,
onClick: () => { handleEdit(row) } },
//{ default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' ' ]}
{ default: () => '编辑'}
))
}
if(hasPermission('biz:assingWork:transfer')){
buttons.push(h(NButton, {
size: 'small',
type:'success',
ghost:true,
onClick: () => { handlreass(row) } },
{ default: () => '改派'}
))
}
if(hasPermission('biz:assingWork:pauseResume')){
buttons.push(h(NButton, {
size: 'small',
type:'warning',
ghost:true,
onClick:()=>{ handlpause(row) }
},
{ default: () => '暂停'}
))
}
// if(hasPermission('biz:assingWork:edit')){
// buttons.push(h(NButton, {
// size: 'small',
// type:'primary',
// ghost:true,
// onClick: () => { handleEdit(row) } },
// //{ default: () => [h(NIcon, null, { default: () => h(CreateOutline) }), ' ' ]}
// { default: () => ''}
// ))
// }
// if(hasPermission('biz:assingWork:transfer')){
// buttons.push(h(NButton, {
// size: 'small',
// type:'success',
// ghost:true,
// onClick: () => { handlreass(row) } },
// { default: () => ''}
// ))
// }
// if(hasPermission('biz:assingWork:pauseResume')){
// buttons.push(h(NButton, {
// size: 'small',
// type:'warning',
// ghost:true,
// onClick:()=>{ handlpause(row) }
// },
// { default: () => ''}
// ))
// }
// buttons.push(
// )
return buttons.length > 0 ? h(NSpace, {justify:'center'}, { default: () => buttons }) : '-'
// return buttons.length > 0 ? h(NSpace, {justify:'center'}, { default: () => buttons }) : '-'
}
}
]
@ -747,23 +880,80 @@ function pauseSubmit() {
})
}
// function zantqy(row:any) {
// dialog.warning({
// title: '',
// content: `"${row.processName}"`,
// positiveText: '',
// negativeText: '',
// onPositiveClick: () => {
// pauseresume({}).then(() => {
// message.success('!')
// getlist()
// })
// }
// })
// }
async function handleViewReport(id:number) {
reportDetailTitle.value='汇报详情'
reportDetailVisible.value = true
const res = await submitLogApi.getByDispatch(id);
mappedInfoList.value = [
{key:"materialCode",label:"物料编码",value:res.materialCode},
{key:"materialName",label:"物料名称",value:res.materialName},
{key:"materialQty",label:"物料数量",value:res.materialQty},
{key:"processCode",label:"工序编号",value:res.processCode},
{key:"processName",label:"工序名称",value:res.processName},
{key:"processQty",label:"生产总数",value:res.processQty},
{key:"assingCode",label:"派工编号",value:res.assingCode},
{key:"workerName",label:"派工人",value:res.workerName},
{key:"assingQty",label:"派工数量",value:res.assingQty}
]
qualityTestings.value = res.qualityTestings
}
function formatDisplayValue(key: string, value: any): string {
if (value === null || value === undefined) return '-'
//
switch (key) {
case 'resourceType': {
const sourceOpt = qcSourceTypeOptions.value.find(o => o.value === value || String(o.value) === String(value))
return sourceOpt ? sourceOpt.label : String(value)
}
case 'status': {
const statusOpt = qcStatusOptions.value.find(o => o.value === value || String(o.value) === String(value))
return statusOpt ? statusOpt.label : String(value)
}
case 'qcNo':
return value ? new Date(value).toLocaleString('zh-CN') : '-'
case 'inspectTime':
case 'createTime':
case 'updateTime':
return value ? new Date(value).toLocaleString('zh-CN') : '-'
default:
return String(value)
}
}
//
async function loadDictOptions() {
try {
const data = await dictDataApi.listByType('qc_result_type')
qcResultTypeOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
try {
const data = await dictDataApi.listByType('source_type')
qcSourceTypeOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
try {
const data = await dictDataApi.listByType('qc_status')
qcStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
try {
const data = await dictDataApi.listByType('assing_status')
qcAssingStatusOptions.value = data.map(d => ({ label: d.dictLabel, value: (Number(d.dictValue) || d.dictValue),class:d.listClass }))
}catch {}
}
onMounted(() => {
getlist()
loadDictOptions()
//workload()
})