style:设备台账-关键件/备件列表更换接口

main
黄伟杰 12 hours ago
parent 172d5cacea
commit a9eeef6abd

@ -41,6 +41,7 @@ export interface DeviceOperationOverviewTimelineRowVO {
id: string id: string
name: string name: string
utilizationRate: number utilizationRate: number
totalWarningTime?: number
segments: DeviceOperationOverviewTimelineSegmentVO[] segments: DeviceOperationOverviewTimelineSegmentVO[]
} }

@ -103,8 +103,12 @@ export const DeviceLedgerApi = {
exportDeviceLedger: async (params) => { exportDeviceLedger: async (params) => {
return await request.download({ url: `/mes/device-ledger/export-excel`, params }) return await request.download({ url: `/mes/device-ledger/export-excel`, params })
}, },
exportSpareBased: async (params) => { exportDeviceLedgerSpare: async (params: { deviceLedgerId: string | number }) => {
return await request.download({ url: `/mes/device-ledger/export-spare-based`, params }) return await request.download({ url: `/mes/device-ledger/export-spare`, params })
},
getDeviceLedgerSparePage: async (params: any) => {
return await request.get({ url: `/mes/device-ledger/spare-page`, params })
}, },
exportMold: async (params) => { exportMold: async (params) => {

@ -419,7 +419,7 @@ export default {
currentStatus: 'Status', currentStatus: 'Status',
runningTime: 'Running Time (Today)', runningTime: 'Running Time (Today)',
standbyTime: 'Idle Time (Today)', standbyTime: 'Idle Time (Today)',
alarmTime: 'Alarm Time (Today)', alarmTime: 'Alarm Time (Hours)',
efficiency: 'Activation (Today)' efficiency: 'Activation (Today)'
}, },
empty: 'No device operation data' empty: 'No device operation data'
@ -5681,7 +5681,7 @@ export default {
tableRunningTimeColumn: 'Running Time (Hours)', tableRunningTimeColumn: 'Running Time (Hours)',
tableStandbyTimeColumn: 'Standby Time (Hours)', tableStandbyTimeColumn: 'Standby Time (Hours)',
tableFaultTimeColumn: 'Fault Time (Hours)', tableFaultTimeColumn: 'Fault Time (Hours)',
tableWarningTimeColumn: 'Warning Time (Hours)', tableWarningTimeColumn: 'Alarm Time (Hours)',
tableUtilizationRateColumn: 'Utilization Rate', tableUtilizationRateColumn: 'Utilization Rate',
tableUtilizationRateTooltip: tableUtilizationRateTooltip:
'Power-on Rate = Online Time / Total Time\nOnline Time = Running Time + Standby Time + Fault Time\nUtilization Rate = Running Time / Online Time\nPower-on Rate = (Running Time + Standby Time + Fault Time) / Total Time', 'Power-on Rate = Online Time / Total Time\nOnline Time = Running Time + Standby Time + Fault Time\nUtilization Rate = Running Time / Online Time\nPower-on Rate = (Running Time + Standby Time + Fault Time) / Total Time',

@ -419,7 +419,7 @@ export default {
currentStatus: '当前状态', currentStatus: '当前状态',
runningTime: '运行时间(今日)', runningTime: '运行时间(今日)',
standbyTime: '空闲时间(今日)', standbyTime: '空闲时间(今日)',
alarmTime: '报警时间(今日)', alarmTime: '报警时间(小时)',
efficiency: '稼动率(今日)' efficiency: '稼动率(今日)'
}, },
empty: '暂无设备运行数据' empty: '暂无设备运行数据'
@ -5575,7 +5575,7 @@ export default {
tableRunningTimeColumn: '运行时间(小时)', tableRunningTimeColumn: '运行时间(小时)',
tableStandbyTimeColumn: '待机时间(小时)', tableStandbyTimeColumn: '待机时间(小时)',
tableFaultTimeColumn: '故障时间(小时)', tableFaultTimeColumn: '故障时间(小时)',
tableWarningTimeColumn: '时间(小时)', tableWarningTimeColumn: '警时间(小时)',
tableUtilizationRateColumn: '稼动率', tableUtilizationRateColumn: '稼动率',
tableUtilizationRateTooltip: tableUtilizationRateTooltip:
'开机率 = 在线时间 / 总的时间\n在线时间 = 运行时间 + 空闲时间 + 故障时间\n稼动率 = 运行时间 / 在线时间\n开机率 =(运行时间 + 空闲时间 + 故障时间)/ 总的时间', '开机率 = 在线时间 / 总的时间\n在线时间 = 运行时间 + 空闲时间 + 故障时间\n稼动率 = 运行时间 / 在线时间\n开机率 =(运行时间 + 空闲时间 + 故障时间)/ 总的时间',

@ -86,12 +86,12 @@
prop="totalFaultTime" prop="totalFaultTime"
min-width="140px" min-width="140px"
sortable /> sortable />
<!-- <el-table-column <el-table-column
:label="t('DataCollection.RunReport.tableWarningTimeColumn')" :label="t('DataCollection.RunReport.tableWarningTimeColumn')"
align="center" align="center"
prop="totalWarningTime" prop="totalWarningTime"
min-width="140px" min-width="140px"
sortable /> --> sortable />
<el-table-column <el-table-column
align="center" align="center"
prop="utilizationRate" prop="utilizationRate"

@ -423,17 +423,87 @@
<el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.criticalComponent')" name="criticalComponent"> <el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.criticalComponent')" name="criticalComponent">
<div class="device-ledger-tab-toolbar"> <div class="device-ledger-tab-toolbar">
<el-button <el-form
type="success" ref="criticalComponentQueryFormRef"
plain :model="criticalComponentQueryParams"
:loading="criticalExportLoading" :inline="true"
@click="handleExportCriticalComponent" class="device-ledger-critical-component-query"
v-hasPermi="['mes:device-ledger:export']"
> >
<Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }} <el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.code')" prop="code">
</el-button> <el-input
v-model="criticalComponentQueryParams.code"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderCode')"
clearable
class="!w-240px"
@keyup.enter="handleQueryCriticalComponent"
/>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.name')" prop="name">
<el-input
v-model="criticalComponentQueryParams.name"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderName')"
clearable
class="!w-240px"
@keyup.enter="handleQueryCriticalComponent"
/>
</el-form-item>
<el-form-item
:label="t('EquipmentManagement.EquipmentKeyItems.description')"
prop="description"
>
<el-input
v-model="criticalComponentQueryParams.description"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderDescription')"
clearable
class="!w-240px"
@keyup.enter="handleQueryCriticalComponent"
/>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.remark')" prop="remark">
<el-input
v-model="criticalComponentQueryParams.remark"
:placeholder="t('EquipmentManagement.EquipmentKeyItems.placeholderRemark')"
clearable
class="!w-240px"
@keyup.enter="handleQueryCriticalComponent"
/>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.EquipmentKeyItems.createTime')" prop="createTime">
<el-date-picker
v-model="criticalComponentQueryParams.createTime"
type="daterange"
value-format="YYYY-MM-DD HH:mm:ss"
:start-placeholder="t('common.startTimeText')"
:end-placeholder="t('common.endTimeText')"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" plain @click="handleQueryCriticalComponent">
<Icon icon="ep:search" class="mr-5px" /> {{ t('common.query') }}
</el-button>
<el-button @click="resetCriticalComponentQuery">
<Icon icon="ep:refresh" class="mr-5px" /> {{ t('common.reset') }}
</el-button>
<el-button
type="success"
plain
:loading="criticalExportLoading"
@click="handleExportCriticalComponent"
v-hasPermi="['mes:device-ledger:export']"
>
<Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }}
</el-button>
</el-form-item>
</el-form>
</div> </div>
<el-table v-loading="tableLoading" :data="detailData?.componentList" :stripe="true" :show-overflow-tooltip="true"> <el-table
v-loading="criticalComponentLoading"
:data="criticalComponentList"
:stripe="true"
:show-overflow-tooltip="true"
>
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.componentCode')" align="center" prop="code" min-width="140" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.componentCode')" align="center" prop="code" min-width="140" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.componentName')" align="center" prop="name" min-width="140" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.componentName')" align="center" prop="name" min-width="140" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentKeyItems.count')" align="center" prop="count" min-width="180" /> <el-table-column :label="t('EquipmentManagement.EquipmentKeyItems.count')" align="center" prop="count" min-width="180" />
@ -441,6 +511,12 @@
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.remark')" align="center" prop="remark" min-width="180" /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.remark')" align="center" prop="remark" min-width="180" />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="180" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="180" sortable />
</el-table> </el-table>
<Pagination
:total="criticalComponentTotal"
v-model:page="criticalComponentQueryParams.pageNo"
v-model:limit="criticalComponentQueryParams.pageSize"
@pagination="getCriticalComponentList"
/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.sparePart')" name="component"> <el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.sparePart')" name="component">
@ -455,13 +531,19 @@
<Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }} <Icon icon="ep:download" class="mr-5px" /> {{ t('action.export') }}
</el-button> </el-button>
</div> </div>
<el-table v-loading="tableLoading" :data="detailData?.beijianList" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="spareLoading" :data="spareList" :stripe="true" :show-overflow-tooltip="true">
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.spareCode')" align="center" prop="barCode" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.spareCode')" align="center" prop="barCode" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.spareName')" align="left" prop="name" width="220px" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.spareName')" align="left" prop="name" width="220px" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.category')" align="center" prop="categoryName" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.category')" align="center" prop="subCategoryName" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.unit')" align="center" prop="unitName" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.unit')" align="center" prop="unitName" sortable />
<el-table-column :label="t('EquipmentManagement.EquipmentLedger.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable /> <el-table-column :label="t('EquipmentManagement.EquipmentLedger.createTime')" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
</el-table> </el-table>
<Pagination
:total="spareTotal"
v-model:page="spareQueryParams.pageNo"
v-model:limit="spareQueryParams.pageSize"
@pagination="getSpareList"
/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.mold')" name="mold"> <el-tab-pane :label="t('EquipmentManagement.EquipmentLedger.mold')" name="mold">
@ -497,7 +579,8 @@ import { dateFormatter, formatDate } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger' import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { DeviceTypeApi, DeviceTypeTreeVO } from '@/api/mes/devicetype' import { DeviceTypeApi, DeviceTypeTreeVO } from '@/api/mes/devicetype'
import { CriticalComponentApi } from '@/api/mes/criticalComponent' import { CriticalComponentApi, CriticalComponentVO } from '@/api/mes/criticalComponent'
import { ProductVO } from '@/api/erp/product/product'
import { TicketManagementApi } from '@/api/mes/ticketManagement' import { TicketManagementApi } from '@/api/mes/ticketManagement'
import { DvRepairApi } from '@/api/mes/dvrepair' import { DvRepairApi } from '@/api/mes/dvrepair'
import QrcodeActionCard from '@/components/QrcodeActionCard/index.vue' import QrcodeActionCard from '@/components/QrcodeActionCard/index.vue'
@ -522,6 +605,67 @@ const detailLoading = ref(false)
const tableLoading = ref(false) const tableLoading = ref(false)
const detailData = ref<DeviceLedgerDetailVO | undefined>() const detailData = ref<DeviceLedgerDetailVO | undefined>()
const detailActiveTab = ref('check') const detailActiveTab = ref('check')
const criticalComponentLoading = ref(false)
const criticalComponentList = ref<CriticalComponentVO[]>([])
const criticalComponentTotal = ref(0)
const criticalComponentQueryFormRef = ref()
const criticalComponentQueryParams = reactive({
pageNo: 1,
pageSize: 10,
deviceLedgerId: undefined as string | undefined,
code: undefined as string | undefined,
name: undefined as string | undefined,
description: undefined as string | undefined,
remark: undefined as string | undefined,
createTime: [] as string[]
})
const spareLoading = ref(false)
const spareList = ref<ProductVO[]>([])
const spareTotal = ref(0)
const spareQueryParams = reactive({
pageNo: 1,
pageSize: 10
})
const getCriticalComponentList = async () => {
if (!deviceId.value) return
criticalComponentLoading.value = true
try {
const data = await CriticalComponentApi.getCriticalComponentPage({
...criticalComponentQueryParams,
deviceLedgerId: deviceId.value
})
criticalComponentList.value = data.list ?? []
criticalComponentTotal.value = data.total ?? 0
} finally {
criticalComponentLoading.value = false
}
}
const handleQueryCriticalComponent = async () => {
criticalComponentQueryParams.pageNo = 1
await getCriticalComponentList()
}
const resetCriticalComponentQuery = async () => {
criticalComponentQueryFormRef.value?.resetFields()
await handleQueryCriticalComponent()
}
const getSpareList = async () => {
if (!deviceId.value) return
spareLoading.value = true
try {
const data = await DeviceLedgerApi.getDeviceLedgerSparePage({
...spareQueryParams,
deviceLedgerId: deviceId.value
})
spareList.value = data.list ?? []
spareTotal.value = data.total ?? 0
} finally {
spareLoading.value = false
}
}
const deviceTypeNameMap = ref<Record<string, string>>({}) const deviceTypeNameMap = ref<Record<string, string>>({})
@ -965,7 +1109,7 @@ const handleExportSpareBased = async () => {
try { try {
await message.exportConfirm() await message.exportConfirm()
spareExportLoading.value = true spareExportLoading.value = true
const data = await DeviceLedgerApi.exportSpareBased({ id: deviceId.value }) const data = await DeviceLedgerApi.exportDeviceLedgerSpare({ deviceLedgerId: deviceId.value })
download.excel(data, '备件.xls') download.excel(data, '备件.xls')
} catch { } catch {
} finally { } finally {
@ -999,6 +1143,8 @@ const getDetail = async () => {
onMounted(async () => { onMounted(async () => {
await getTypeTreeForNameMap() await getTypeTreeForNameMap()
await getDetail() await getDetail()
await getCriticalComponentList()
await getSpareList()
}) })
</script> </script>
@ -1203,6 +1349,10 @@ onMounted(async () => {
text-align: right; text-align: right;
} }
.device-ledger-critical-component-query {
text-align: left;
}
.device-ledger-history-items { .device-ledger-history-items {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

@ -50,7 +50,7 @@
<div v-if="alarmDevices.length" class="alarm-list"> <div v-if="alarmDevices.length" class="alarm-list">
<div v-for="item in alarmDevices" :key="item.id" class="alarm-item"> <div v-for="item in alarmDevices" :key="item.id" class="alarm-item">
<strong :title="item.name">{{ item.name }}</strong> <strong :title="item.name">{{ item.name }}</strong>
<span>{{ t('AlarmBoard.alarmPrefix') }} {{ formatHours(item.alarmTime) }}</span> <span>{{ t('AlarmBoard.alarmPrefix') }} {{ formatHours(item.totalWarningTime) }}</span>
<span>{{ item.lastReportTime }}</span> <span>{{ item.lastReportTime }}</span>
</div> </div>
</div> </div>
@ -69,7 +69,7 @@
<span>{{ t('Detail.columns.currentStatus') }}</span> <span>{{ t('Detail.columns.currentStatus') }}</span>
<span>运行时间(小时)</span> <span>运行时间(小时)</span>
<span>待机时间(小时)</span> <span>待机时间(小时)</span>
<span>故障时间(小时)</span> <span>{{ t('Detail.columns.alarmTime') }}</span>
<span>稼动率</span> <span>稼动率</span>
</div> </div>
<div v-if="pagedRows.length" class="table-body"> <div v-if="pagedRows.length" class="table-body">
@ -85,7 +85,7 @@
</span> </span>
<span>{{ formatHours(row.runningTime) }}</span> <span>{{ formatHours(row.runningTime) }}</span>
<span>{{ formatHours(row.standbyTime) }}</span> <span>{{ formatHours(row.standbyTime) }}</span>
<span>{{ formatHours(row.alarmTime) }}</span> <span>{{ formatHours(row.totalWarningTime) }}</span>
<span class="rate">{{ formatPercentText(row.utilizationRate) }}</span> <span class="rate">{{ formatPercentText(row.utilizationRate) }}</span>
</div> </div>
</div> </div>
@ -158,7 +158,7 @@ interface DetailRow {
status: RunStatus status: RunStatus
runningTime: number runningTime: number
standbyTime: number standbyTime: number
alarmTime: number totalWarningTime: number
utilizationRate: string utilizationRate: string
lastReportTime: string lastReportTime: string
} }
@ -273,9 +273,9 @@ const detailRows = computed<DetailRow[]>(() => {
status, status,
runningTime: Number(row.totalRunningTime) || 0, runningTime: Number(row.totalRunningTime) || 0,
standbyTime: Number(row.totalStandbyTime) || 0, standbyTime: Number(row.totalStandbyTime) || 0,
alarmTime: Number(row.totalFaultTime) || 0, totalWarningTime: Number(row.totalWarningTime) || 0,
utilizationRate: row.utilizationRate || '0%', utilizationRate: row.utilizationRate || '0%',
lastReportTime: status === 'fault' || Number(row.totalFaultTime) > 0 ? lastUpdateTime.value || '-' : '-' lastReportTime: status === 'fault' || Number(row.totalWarningTime) > 0 ? lastUpdateTime.value || '-' : '-'
} }
}) })
}) })
@ -296,8 +296,8 @@ const pagedRows = computed(() => {
const detailPageText = computed(() => `${detailPage.value} / ${totalDetailPages.value}`) const detailPageText = computed(() => `${detailPage.value} / ${totalDetailPages.value}`)
const alarmDevices = computed(() => { const alarmDevices = computed(() => {
return detailRows.value return detailRows.value
.filter((item) => item.status === 'fault' || item.alarmTime > 0) .filter((item) => item.status === 'fault' || item.totalWarningTime > 0)
.sort((a, b) => b.alarmTime - a.alarmTime) .sort((a, b) => b.totalWarningTime - a.totalWarningTime)
.slice(0, 2) .slice(0, 2)
}) })
const hourlyRates = computed(() => { const hourlyRates = computed(() => {

@ -84,7 +84,7 @@
</span> </span>
<span>{{ formatMinutes(row.runningMinutes) }}</span> <span>{{ formatMinutes(row.runningMinutes) }}</span>
<span>{{ formatMinutes(row.standbyMinutes) }}</span> <span>{{ formatMinutes(row.standbyMinutes) }}</span>
<span>{{ formatMinutes(row.alarmMinutes) }}</span> <span>{{ formatHours(row.totalWarningTime) }}</span>
<span class="rate">{{ formatPercent(row.utilizationRate) }}</span> <span class="rate">{{ formatPercent(row.utilizationRate) }}</span>
</div> </div>
</div> </div>
@ -140,7 +140,7 @@ interface DetailRow {
status: RunStatus status: RunStatus
runningMinutes: number runningMinutes: number
standbyMinutes: number standbyMinutes: number
alarmMinutes: number totalWarningTime: number
utilizationRate: number utilizationRate: number
lastReportTime: string lastReportTime: string
} }
@ -259,9 +259,9 @@ const detailRows = computed<DetailRow[]>(() => {
status, status,
runningMinutes: minutes.running, runningMinutes: minutes.running,
standbyMinutes: minutes.standby, standbyMinutes: minutes.standby,
alarmMinutes: minutes.fault, totalWarningTime: Number(row.totalWarningTime) || 0,
utilizationRate: Number(row.utilizationRate) || 0, utilizationRate: Number(row.utilizationRate) || 0,
lastReportTime: status === 'fault' || minutes.fault > 0 ? lastUpdateTime.value || '-' : '-' lastReportTime: status === 'fault' || Number(row.totalWarningTime) > 0 ? lastUpdateTime.value || '-' : '-'
} }
}) })
}) })
@ -283,8 +283,8 @@ const pagedRows = computed(() => {
const detailPageText = computed(() => `${detailPage.value} / ${totalDetailPages.value}`) const detailPageText = computed(() => `${detailPage.value} / ${totalDetailPages.value}`)
const alarmDevices = computed(() => { const alarmDevices = computed(() => {
return detailRows.value return detailRows.value
.filter((item) => item.status === 'fault' || item.alarmMinutes > 0) .filter((item) => item.status === 'fault' || item.totalWarningTime > 0)
.sort((a, b) => b.alarmMinutes - a.alarmMinutes) .sort((a, b) => b.totalWarningTime - a.totalWarningTime)
.slice(0, 2) .slice(0, 2)
}) })
const hourlyRates = computed(() => const hourlyRates = computed(() =>
@ -310,6 +310,12 @@ const formatMinutes = (minutes: number) => {
return t('Time.hourMinute', { hour: hours, minute: rest }) return t('Time.hourMinute', { hour: hours, minute: rest })
} }
const formatHours = (value?: number) => {
const hours = Number(value)
const safeHours = Number.isFinite(hours) && hours > 0 ? Math.round(hours * 100) / 100 : 0
return t('Time.hour', { hour: safeHours })
}
const average = (values: number[]) => { const average = (values: number[]) => {
const valid = values.filter((item) => Number.isFinite(item)) const valid = values.filter((item) => Number.isFinite(item))
if (!valid.length) return 0 if (!valid.length) return 0

Loading…
Cancel
Save