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

liutao_branch
黄伟杰 4 months ago
parent 9b49732922
commit 3257182441

@ -39,7 +39,8 @@
> >
维保 维保
</el-button> --> </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']"> v-hasPermi="['erp:mold-brand:update']">
编辑 编辑
</el-button> </el-button>
@ -50,79 +51,199 @@
</el-table-column> </el-table-column>
</el-table> </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" /> @pagination="getList" />
</ContentWrap> </ContentWrap>
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<MoldForm ref="formRef" @success="getList" /> <MoldForm ref="formRef" @success="getList" />
<el-dialog v-model="detailVisible" title="模具详情" width="80%" :destroy-on-close="true"> <el-dialog v-model="detailVisible" title="模具详情" width="80%" :destroy-on-close="true" draggable>
<div v-loading="detailLoading"> <div v-loading="detailLoading" class="mold-detail-body">
<el-descriptions :column="3" class="mold-detail-desc"> <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="模具名称">{{ detailData?.name ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具状态"> <el-descriptions-item label="模具状态">
<dict-tag :type="DICT_TYPE.ERP_MOLD_STATUS" :value="detailData?.status" /> <dict-tag :type="DICT_TYPE.ERP_MOLD_STATUS" :value="detailData?.status" />
</el-descriptions-item> </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?.brandName ?? '' }}</el-descriptions-item>
<el-descriptions-item label="模具规格">{{ detailData?.moldType ?? '' }}</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?.useTime ?? '' }}</el-descriptions-item>
<el-descriptions-item label="使用设备">{{ detailData?.machineName ?? detailData?.machineId ?? '' <el-descriptions-item label="使用设备">{{ detailData?.machineName ?? detailData?.machineId ?? ''
}}</el-descriptions-item> }}</el-descriptions-item>
<el-descriptions-item label="入库日期">{{ formatDetailDate(detailData?.inTime) }}</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="是否启用"> <el-descriptions-item label="是否启用">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="detailData?.isEnable" /> <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="detailData?.isEnable" />
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="备注">{{ detailData?.remark ?? '' }}</el-descriptions-item> <el-descriptions-item label="备注">{{ detailData?.remark ?? '' }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
<el-tabs v-model="detailActiveTab" class="mt-12px"> <div class="mold-detail-tabs">
<el-tabs v-model="detailActiveTab" class="mt-12px">
<el-tab-pane label="点检履历" name="check"> <el-tab-pane label="点检履历" name="check">
<el-empty v-if="!inspectionHistoryView.length" /> <el-empty v-if="!inspectionStepGroups.length" />
<el-table v-else :data="inspectionHistoryView" :stripe="true" :show-overflow-tooltip="true" <el-steps
class="mold-history-table"> v-else
<el-table-column label="项目" prop="name" min-width="160" /> direction="vertical"
<el-table-column label="方式" prop="method" min-width="120"> :active="inspectionStepGroups.length"
<template #default="scope"> class="device-ledger-history-steps"
<dict-tag type="Inspection_method" :value="scope.row.method" /> >
<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> </template>
</el-table-column> <template #description>
<el-table-column label="判定标准" prop="criteria" min-width="180" /> <div class="device-ledger-history-items">
<el-table-column label="结果" align="center"> <div
<template #default="scope"> v-for="item in group.items"
<el-tag :type="getResultTagType(scope.row.result)">{{ getResultLabel(scope.row.result) }}</el-tag> :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-image>
</div>
</div>
</div>
</div>
</template> </template>
</el-table-column> </el-step>
<el-table-column label="时间" prop="time" width="180" /> </el-steps>
<el-table-column label="备注" prop="remark" min-width="200" />
</el-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="保养履历" name="maintain"> <el-tab-pane label="保养履历" name="maintain">
<el-empty v-if="!maintainHistoryView.length" /> <el-empty v-if="!maintainStepGroups.length" />
<el-table v-else :data="maintainHistoryView" :stripe="true" :show-overflow-tooltip="true" <el-steps
class="mold-history-table"> v-else
<el-table-column label="项目" prop="name" min-width="160" /> direction="vertical"
<el-table-column label="方式" prop="method" min-width="120"> class="device-ledger-history-steps"
<template #default="scope"> :active="maintainStepGroups.length"
<dict-tag type="Inspection_method" :value="scope.row.method" /> >
<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> </template>
</el-table-column> <template #description>
<el-table-column label="判定标准" prop="criteria" min-width="180" /> <div class="device-ledger-history-items">
<el-table-column label="时间" prop="time" width="180" /> <div
<el-table-column label="结果" align="center" width="80"> v-for="item in group.items"
<template #default="scope"> :key="item.key"
<el-tag :type="getResultTagType(scope.row.result)">{{ getResultLabel(scope.row.result) }}</el-tag> 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-image>
</div>
</div>
</div>
</div>
</template> </template>
</el-table-column> </el-step>
<el-table-column label="备注" prop="remark" min-width="200" /> </el-steps>
</el-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="维修履历" name="repair"> <el-tab-pane label="维修履历" name="repair">
<el-empty v-if="!repairHistoryView.length" /> <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"> class="mold-history-table">
<el-table-column label="维修单ID" prop="repairId" width="120" /> <el-table-column label="维修单ID" prop="repairId" width="120" />
<el-table-column label="项目编码" prop="subjectCode" width="120" /> <el-table-column label="项目编码" prop="subjectCode" width="120" />
@ -140,6 +261,7 @@
</el-table> </el-table>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@ -270,41 +392,96 @@ const getResultTagType = (value: any) => {
return 'info' 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 name: string
result: any result: any
method?: any method?: any
criteria?: any criteria?: any
time?: string images?: string[]
remark?: any remark?: any
inspectionTime?: any
createTime?: any
} }
const inspectionHistoryView = computed<SimpleHistoryRow[]>(() => { type HistoryStepGroup = { key: string; time: string; operator: string; items: HistoryStepItem[] }
const data: any = detailData.value
const list = data?.inspectionList ?? [] const parseImages = (value: any): string[] => {
const rows = Array.isArray(list) ? list : [] if (!value) return []
return rows.map((row: any) => ({ if (Array.isArray(value)) return value.map(String).filter(Boolean)
name: String(row?.inspectionItemName ?? row?.name ?? ''), const cleaned = String(value).replace(/[`'\"]/g, '').trim()
result: row?.inspectionResult ?? row?.result, return cleaned
method: row?.inspectionMethod ?? row?.method, .split(',')
criteria: row?.judgmentCriteria ?? row?.criteria, .map((v) => v.trim())
time: formatHistoryTime(row?.inspectionTime ?? row?.time ?? row?.createTime), .filter(Boolean)
remark: row?.remark }
}))
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 maintainStepGroups = computed<HistoryStepGroup[]>(() => {
const data: any = detailData.value return buildStepGroups(maintainHistory.value, {
const list = data?.maintainList ?? [] timeField: 'inspectionTime',
const rows = Array.isArray(list) ? list : [] nameFieldCandidates: ['maintainItemName', 'inspectionItemName', 'name'],
return rows.map((row: any) => ({ resultFieldCandidates: ['maintainResult', 'inspectionResult']
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
}))
}) })
type RepairHistoryRow = { type RepairHistoryRow = {
@ -359,4 +536,109 @@ const openDetail = async (id: number) => {
.mold-history-table { .mold-history-table {
margin-top: 8px; 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> </style>

Loading…
Cancel
Save