feat:模具管理-模具详情-点检履历/保养履历改成step组件

main
黄伟杰 3 weeks ago
parent 9b49732922
commit 3257182441

@ -39,7 +39,8 @@
>
维保
</el-button> -->
<el-button link type="primary" @click="openForm('update', scope.row.id)"
<el-button
link type="primary" @click="openForm('update', scope.row.id)"
v-hasPermi="['erp:mold-brand:update']">
编辑
</el-button>
@ -50,79 +51,199 @@
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<MoldForm ref="formRef" @success="getList" />
<el-dialog v-model="detailVisible" title="模具详情" width="80%" :destroy-on-close="true">
<div v-loading="detailLoading">
<el-dialog v-model="detailVisible" title="模具详情" width="80%" :destroy-on-close="true" draggable>
<div v-loading="detailLoading" class="mold-detail-body">
<el-descriptions :column="3" class="mold-detail-desc">
<el-descriptions-item label="模具编">{{ detailData?.code ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具编">{{ detailData?.code ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具名称">{{ detailData?.name ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具状态">
<dict-tag :type="DICT_TYPE.ERP_MOLD_STATUS" :value="detailData?.status" />
</el-descriptions-item>
<el-descriptions-item label="模具品牌">{{ detailData?.brandName ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具型号">{{ detailData?.brandName ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具规格">{{ detailData?.moldType ?? '' }}</el-descriptions-item>
<el-descriptions-item label="工序">
<dict-tag :type="DICT_TYPE.MES_ORG_TYPE" :value="detailData?.orgType" />
</el-descriptions-item>
<el-descriptions-item label="模穴数">{{ detailData?.moldSize ?? '' }}</el-descriptions-item>
<el-descriptions-item label="使用次数/次">{{ detailData?.useTime ?? '' }}</el-descriptions-item>
<el-descriptions-item label="使用设备">{{ detailData?.machineName ?? detailData?.machineId ?? ''
}}</el-descriptions-item>
<el-descriptions-item label="入库日期">{{ formatDetailDate(detailData?.inTime) }}</el-descriptions-item>
<el-descriptions-item label="上次保养日期">{{ formatDetailDate(detailData?.lastMaintainTime) }}</el-descriptions-item>
<el-descriptions-item label="上次维修日期">{{ formatDetailDate(detailData?.lastRepairTime) }}</el-descriptions-item>
<el-descriptions-item label="是否启用">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="detailData?.isEnable" />
</el-descriptions-item>
<el-descriptions-item label="备注">{{ detailData?.remark ?? '' }}</el-descriptions-item>
</el-descriptions>
<div class="mold-detail-tabs">
<el-tabs v-model="detailActiveTab" class="mt-12px">
<el-tab-pane label="点检履历" name="check">
<el-empty v-if="!inspectionHistoryView.length" />
<el-table v-else :data="inspectionHistoryView" :stripe="true" :show-overflow-tooltip="true"
class="mold-history-table">
<el-table-column label="项目" prop="name" min-width="160" />
<el-table-column label="方式" prop="method" min-width="120">
<template #default="scope">
<dict-tag type="Inspection_method" :value="scope.row.method" />
<el-empty v-if="!inspectionStepGroups.length" />
<el-steps
v-else
direction="vertical"
:active="inspectionStepGroups.length"
class="device-ledger-history-steps"
>
<el-step v-for="group in inspectionStepGroups" :key="group.key">
<template #title>
<div class="device-ledger-history-title">
<span class="device-ledger-history-time">[{{ group.time }}]</span>
<span class="device-ledger-history-operator">操作人: {{ group.operator }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="判定标准" prop="criteria" min-width="180" />
<el-table-column label="结果" align="center">
<template #default="scope">
<el-tag :type="getResultTagType(scope.row.result)">{{ getResultLabel(scope.row.result) }}</el-tag>
<template #description>
<div class="device-ledger-history-items">
<div
v-for="item in group.items"
:key="item.key"
class="device-ledger-history-item"
>
<div class="device-ledger-history-item-head">
<el-tag :type="getResultTagType(item.result)">{{ getResultLabel(item.result) }}</el-tag>
<span class="device-ledger-history-item-text">{{ item.name }}</span>
</div>
<div class="device-ledger-history-item-body">
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">点检方式</span>
<span class="device-ledger-history-item-value">
<dict-tag type="Inspection_method" :value="item.method" />
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">判定标准</span>
<span class="device-ledger-history-item-value">{{ item.criteria ?? '-' }}</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">点检时间</span>
<span class="device-ledger-history-item-value">
{{ formatHistoryTime(item.inspectionTime) }}
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">创建时间</span>
<span class="device-ledger-history-item-value">
{{ formatHistoryTime(item.createTime) }}
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">备注</span>
<span class="device-ledger-history-item-value">{{ item.remark ?? '-' }}</span>
</div>
<div
v-if="item.images?.length"
class="device-ledger-history-item-images"
>
<el-image
v-for="img in item.images"
:key="img"
:src="img"
:preview-src-list="item.images"
preview-teleported
fit="cover"
class="device-ledger-history-item-image"
>
<template #error>
<div class="device-ledger-history-image-error">图片加载失败</div>
</template>
</el-table-column>
<el-table-column label="时间" prop="time" width="180" />
<el-table-column label="备注" prop="remark" min-width="200" />
</el-table>
</el-image>
</div>
</div>
</div>
</div>
</template>
</el-step>
</el-steps>
</el-tab-pane>
<el-tab-pane label="保养履历" name="maintain">
<el-empty v-if="!maintainHistoryView.length" />
<el-table v-else :data="maintainHistoryView" :stripe="true" :show-overflow-tooltip="true"
class="mold-history-table">
<el-table-column label="项目" prop="name" min-width="160" />
<el-table-column label="方式" prop="method" min-width="120">
<template #default="scope">
<dict-tag type="Inspection_method" :value="scope.row.method" />
<el-empty v-if="!maintainStepGroups.length" />
<el-steps
v-else
direction="vertical"
class="device-ledger-history-steps"
:active="maintainStepGroups.length"
>
<el-step v-for="group in maintainStepGroups" :key="group.key">
<template #title>
<div class="device-ledger-history-title">
<span class="device-ledger-history-time">[{{ group.time }}]</span>
<span class="device-ledger-history-operator">操作人: {{ group.operator }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="判定标准" prop="criteria" min-width="180" />
<el-table-column label="时间" prop="time" width="180" />
<el-table-column label="结果" align="center" width="80">
<template #default="scope">
<el-tag :type="getResultTagType(scope.row.result)">{{ getResultLabel(scope.row.result) }}</el-tag>
<template #description>
<div class="device-ledger-history-items">
<div
v-for="item in group.items"
:key="item.key"
class="device-ledger-history-item"
>
<div class="device-ledger-history-item-head">
<el-tag :type="getResultTagType(item.result)">{{ getResultLabel(item.result) }}</el-tag>
<span class="device-ledger-history-item-text">{{ item.name }}</span>
</div>
<div class="device-ledger-history-item-body">
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">保养方式</span>
<span class="device-ledger-history-item-value">
<dict-tag type="Inspection_method" :value="item.method" />
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">判定标准</span>
<span class="device-ledger-history-item-value">{{ item.criteria ?? '-' }}</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">保养时间</span>
<span class="device-ledger-history-item-value">
{{ formatHistoryTime(item.inspectionTime) }}
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">创建时间</span>
<span class="device-ledger-history-item-value">
{{ formatHistoryTime(item.createTime) }}
</span>
</div>
<div class="device-ledger-history-item-row">
<span class="device-ledger-history-item-label">备注</span>
<span class="device-ledger-history-item-value">{{ item.remark ?? '-' }}</span>
</div>
<div
v-if="item.images?.length"
class="device-ledger-history-item-images"
>
<el-image
v-for="img in item.images"
:key="img"
:src="img"
:preview-src-list="item.images"
preview-teleported
fit="cover"
class="device-ledger-history-item-image"
>
<template #error>
<div class="device-ledger-history-image-error">图片加载失败</div>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark" min-width="200" />
</el-table>
</el-image>
</div>
</div>
</div>
</div>
</template>
</el-step>
</el-steps>
</el-tab-pane>
<el-tab-pane label="维修履历" name="repair">
<el-empty v-if="!repairHistoryView.length" />
<el-table v-else :data="repairHistoryView" :stripe="true" :show-overflow-tooltip="true"
<el-table
v-else :data="repairHistoryView" :stripe="true" :show-overflow-tooltip="true"
class="mold-history-table">
<el-table-column label="维修单ID" prop="repairId" width="120" />
<el-table-column label="项目编码" prop="subjectCode" width="120" />
@ -141,6 +262,7 @@
</el-tab-pane>
</el-tabs>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="detailVisible = false"> </el-button>
@ -270,41 +392,96 @@ const getResultTagType = (value: any) => {
return 'info'
}
type SimpleHistoryRow = {
const inspectionHistory = computed(() => {
const data: any = detailData.value
return data?.inspectionList ?? []
})
const maintainHistory = computed(() => {
const data: any = detailData.value
const list = data?.maintainList ?? []
return Array.isArray(list) ? list : []
})
type HistoryStepItem = {
key: string
name: string
result: any
method?: any
criteria?: any
time?: string
images?: string[]
remark?: any
inspectionTime?: any
createTime?: any
}
const inspectionHistoryView = computed<SimpleHistoryRow[]>(() => {
const data: any = detailData.value
const list = data?.inspectionList ?? []
const rows = Array.isArray(list) ? list : []
return rows.map((row: any) => ({
name: String(row?.inspectionItemName ?? row?.name ?? ''),
result: row?.inspectionResult ?? row?.result,
method: row?.inspectionMethod ?? row?.method,
criteria: row?.judgmentCriteria ?? row?.criteria,
time: formatHistoryTime(row?.inspectionTime ?? row?.time ?? row?.createTime),
remark: row?.remark
}))
type HistoryStepGroup = { key: string; time: string; operator: string; items: HistoryStepItem[] }
const parseImages = (value: any): string[] => {
if (!value) return []
if (Array.isArray(value)) return value.map(String).filter(Boolean)
const cleaned = String(value).replace(/[`'\"]/g, '').trim()
return cleaned
.split(',')
.map((v) => v.trim())
.filter(Boolean)
}
const buildStepGroups = (
rows: any[],
options: { timeField: string; nameFieldCandidates: string[]; resultFieldCandidates: string[] }
) => {
const groups = new Map<string, HistoryStepGroup>()
for (const row of rows ?? []) {
const time = formatHistoryTime(row?.[options.timeField] ?? row?.createTime)
const operator = String(row?.creatorName ?? row?.creator ?? '-')
const groupKey = `${row?.managementId ?? ''}__${time}__${operator}`
const name =
options.nameFieldCandidates
.map((k) => row?.[k])
.find((v) => v !== undefined && v !== null && String(v).trim() !== '') ?? '-'
const result =
options.resultFieldCandidates.map((k) => row?.[k]).find((v) => v !== undefined && v !== null) ?? undefined
const item: HistoryStepItem = {
key: String(row?.id ?? `${groupKey}__${String(name)}`),
name: String(name),
result,
method: row?.inspectionMethod,
criteria: row?.judgmentCriteria,
images: parseImages(row?.images),
remark: row?.remark,
inspectionTime: row?.inspectionTime,
createTime: row?.createTime
}
if (!groups.has(groupKey)) {
groups.set(groupKey, { key: groupKey, time, operator, items: [item] })
} else {
groups.get(groupKey)!.items.push(item)
}
}
return Array.from(groups.values()).sort((a, b) => String(b.time).localeCompare(String(a.time)))
}
const inspectionStepGroups = computed<HistoryStepGroup[]>(() => {
return buildStepGroups(inspectionHistory.value, {
timeField: 'inspectionTime',
nameFieldCandidates: ['inspectionItemName', 'name'],
resultFieldCandidates: ['inspectionResult']
})
})
const maintainHistoryView = computed<SimpleHistoryRow[]>(() => {
const data: any = detailData.value
const list = data?.maintainList ?? []
const rows = Array.isArray(list) ? list : []
return rows.map((row: any) => ({
name: String(row?.maintainItemName ?? row?.inspectionItemName ?? row?.name ?? ''),
result: row?.maintainResult ?? row?.inspectionResult ?? row?.result,
method: row?.inspectionMethod ?? row?.method,
criteria: row?.judgmentCriteria ?? row?.criteria,
time: formatHistoryTime(row?.inspectionTime ?? row?.time ?? row?.createTime),
remark: row?.remark
}))
const maintainStepGroups = computed<HistoryStepGroup[]>(() => {
return buildStepGroups(maintainHistory.value, {
timeField: 'inspectionTime',
nameFieldCandidates: ['maintainItemName', 'inspectionItemName', 'name'],
resultFieldCandidates: ['maintainResult', 'inspectionResult']
})
})
type RepairHistoryRow = {
@ -359,4 +536,109 @@ const openDetail = async (id: number) => {
.mold-history-table {
margin-top: 8px;
}
.mold-detail-body {
max-height: 70vh;
}
.mold-detail-tabs {
max-height: 50vh;
overflow-y: auto;
padding-right: 4px;
}
.device-ledger-history-steps {
padding: 8px 8px 0;
}
.device-ledger-history-title {
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
}
.device-ledger-history-time {
font-weight: 600;
}
.device-ledger-history-operator {
color: var(--el-text-color-secondary);
}
.device-ledger-history-items {
display: flex;
flex-direction: column;
gap: 6px;
margin-top: 8px;
}
.device-ledger-history-item {
display: flex;
flex-direction: column;
gap: 8px;
padding: 10px;
border: 1px solid var(--el-border-color-lighter);
border-radius: 8px;
background: var(--el-fill-color-blank);
}
.device-ledger-history-item-head {
display: flex;
align-items: center;
gap: 10px;
}
.device-ledger-history-item-body {
display: flex;
flex-direction: column;
gap: 6px;
width: 100%;
}
.device-ledger-history-item-row {
display: flex;
gap: 10px;
}
.device-ledger-history-item-label {
width: 70px;
flex: 0 0 70px;
color: var(--el-text-color-secondary);
}
.device-ledger-history-item-value {
flex: 1;
color: var(--el-text-color-regular);
word-break: break-word;
}
.device-ledger-history-item-images {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 4px;
}
.device-ledger-history-item-image {
width: 76px;
height: 76px;
border-radius: 6px;
overflow: hidden;
}
.device-ledger-history-image-error {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: var(--el-text-color-secondary);
background: var(--el-fill-color);
}
.device-ledger-history-item-text {
color: var(--el-text-color-regular);
}
</style>

Loading…
Cancel
Save