|
@@ -1,137 +1,166 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <Dialog v-model="dialogVisible"
|
|
|
|
|
- :title="t('monitor.details')"
|
|
|
|
|
- :width="dialogWidth"
|
|
|
|
|
- class="fixed-height-dialog"
|
|
|
|
|
- @close="handleClose" >
|
|
|
|
|
- <ContentWrap>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 添加设备信息展示区域 -->
|
|
|
|
|
- <div v-if="deviceInfo" class="device-info-card">
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <span class="info-label">{{ t('iotDevice.code') }}:</span>
|
|
|
|
|
- <span class="info-value">{{ deviceInfo.deviceCode }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <span class="info-label">{{ t('iotDevice.name') }}:</span>
|
|
|
|
|
- <span class="info-value">{{ deviceInfo.deviceName }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-item" v-if="deviceInfo.model">
|
|
|
|
|
- <span class="info-label">{{ t('deviceForm.model') }}:</span>
|
|
|
|
|
- <span class="info-value">{{ deviceInfo.model }}</span>
|
|
|
|
|
|
|
+ <Dialog
|
|
|
|
|
+ v-model="dialogVisible"
|
|
|
|
|
+ :title="t('monitor.details')"
|
|
|
|
|
+ :width="dialogWidth"
|
|
|
|
|
+ class="device-alarm-detail-dialog"
|
|
|
|
|
+ @close="handleClose">
|
|
|
|
|
+ <template #title>
|
|
|
|
|
+ <div class="dialog-title">
|
|
|
|
|
+ <div class="dialog-title__icon"><Icon icon="ep:calendar" /></div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="dialog-title__text">{{ t('monitor.details') }}</div>
|
|
|
|
|
+ <div class="dialog-title__subtitle">查看设备保养项目及各维度保养里程</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
-
|
|
|
|
|
- <div class="table-container">
|
|
|
|
|
- <!-- 添加表格容器并设置滚动 -->
|
|
|
|
|
- <el-table
|
|
|
|
|
- v-loading="loading"
|
|
|
|
|
- :data="paginatedList"
|
|
|
|
|
- :stripe="true"
|
|
|
|
|
- :show-overflow-tooltip="true"
|
|
|
|
|
- style="width: auto"
|
|
|
|
|
- height="100%"
|
|
|
|
|
- class="scrollable-table"
|
|
|
|
|
- ref="tableRef"
|
|
|
|
|
- >
|
|
|
|
|
- <el-table-column :label="t('iotDevice.code')" align="center" prop="deviceCode"
|
|
|
|
|
- :width="columnWidths.deviceCode" v-if="false"/>
|
|
|
|
|
- <el-table-column :label="t('iotDevice.name')" align="center" prop="deviceName"
|
|
|
|
|
- :width="columnWidths.deviceName" v-if="false"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.MaintItems')" align="center" prop="name"
|
|
|
|
|
- :width="columnWidths.name"/>
|
|
|
|
|
-
|
|
|
|
|
- <el-table-column :label="t('operationFillForm.sumTime')" align="center" prop="totalRunTime"
|
|
|
|
|
- :width="columnWidths.totalRunTime">
|
|
|
|
|
- <template #default="{ row }">
|
|
|
|
|
- {{ row.totalRunTime ?? row.tempTotalRunTime }}
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column :label="t('operationFillForm.sumKil')" align="center" prop="totalMileage"
|
|
|
|
|
- :width="columnWidths.totalMileage">
|
|
|
|
|
- <template #default="{ row }">
|
|
|
|
|
- {{ row.totalMileage ?? row.tempTotalMileage }}
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 时间分组列 -->
|
|
|
|
|
- <el-table-column v-if="showTimeColumns" label="保养时长"
|
|
|
|
|
- align="center"
|
|
|
|
|
- :width="columnWidths.timeGroup">
|
|
|
|
|
- <el-table-column :label="t('mainPlan.lastMaintenanceOperationTime')" align="center" prop="lastRunningTime"
|
|
|
|
|
- :width="columnWidths.lastRunningTime"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.RunTimeCycle')" align="center" prop="nextRunningTime"
|
|
|
|
|
- :width="columnWidths.nextRunningTime"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.nextMaintTime')" align="center" prop="timePeriod"
|
|
|
|
|
- :width="columnWidths.timePeriod">
|
|
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="dialog-content">
|
|
|
|
|
+ <section v-if="deviceInfo" class="device-info-section">
|
|
|
|
|
+ <div class="section-heading"><span></span>设备信息</div>
|
|
|
|
|
+ <div class="device-info-grid">
|
|
|
|
|
+ <div class="info-item">
|
|
|
|
|
+ <span class="info-label">{{ t('iotDevice.code') }}</span>
|
|
|
|
|
+ <span class="info-value">{{ deviceInfo.deviceCode }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="info-item">
|
|
|
|
|
+ <span class="info-label">{{ t('iotDevice.name') }}</span>
|
|
|
|
|
+ <span class="info-value">{{ deviceInfo.deviceName }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="info-item" v-if="deviceInfo.model">
|
|
|
|
|
+ <span class="info-label">{{ t('deviceForm.model') }}</span>
|
|
|
|
|
+ <span class="info-value">{{ deviceInfo.model }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="maintenance-section">
|
|
|
|
|
+ <div class="section-heading"><span></span>保养项目</div>
|
|
|
|
|
+ <div class="table-container">
|
|
|
|
|
+ <ZmTable
|
|
|
|
|
+ :loading="loading"
|
|
|
|
|
+ :data="paginatedList"
|
|
|
|
|
+ :show-border="true"
|
|
|
|
|
+ settings-cache-key="pms-device-maintenance-alarm-detail">
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('iotDevice.code')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="deviceCode"
|
|
|
|
|
+ v-if="false" />
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('iotDevice.name')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="deviceName"
|
|
|
|
|
+ v-if="false" />
|
|
|
|
|
+ <ZmTableColumn :label="t('mainPlan.MaintItems')" align="center" prop="name" />
|
|
|
|
|
+
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('operationFillForm.sumTime')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="totalRunTime">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <span :class="{ 'negative-value': isNegative(row.timePeriod) }">
|
|
|
|
|
- {{ row.timePeriod }}
|
|
|
|
|
- </span>
|
|
|
|
|
|
|
+ {{ row.totalRunTime ?? row.tempTotalRunTime }}
|
|
|
</template>
|
|
</template>
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 里程分组列 -->
|
|
|
|
|
- <el-table-column v-if="showMileageColumns" label="保养里程"
|
|
|
|
|
- align="center"
|
|
|
|
|
- :width="columnWidths.mileageGroup">
|
|
|
|
|
- <el-table-column :label="t('mainPlan.lastMaintenanceMileage')" align="center" prop="lastRunningKilometers"
|
|
|
|
|
- :width="columnWidths.lastRunningKilometers"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.operatingMileageCycle')" align="center" prop="nextRunningKilometers"
|
|
|
|
|
- :width="columnWidths.nextRunningKilometers"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.nextMaintKil')" align="center" prop="kilometerCycle"
|
|
|
|
|
- :width="columnWidths.kilometerCycle">
|
|
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('operationFillForm.sumKil')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="totalMileage">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <span :class="{ 'negative-value': isNegative(row.kilometerCycle) }">
|
|
|
|
|
- {{ row.kilometerCycle }}
|
|
|
|
|
- </span>
|
|
|
|
|
|
|
+ {{ row.totalMileage ?? row.tempTotalMileage }}
|
|
|
</template>
|
|
</template>
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 日期分组列 -->
|
|
|
|
|
- <el-table-column v-if="showNaturalDateColumns" label="保养日期"
|
|
|
|
|
- align="center"
|
|
|
|
|
- :width="columnWidths.dateGroup">
|
|
|
|
|
- <el-table-column :label="t('mainPlan.lastMaintenanceNaturalDate')" align="center" prop="lastNaturalDate"
|
|
|
|
|
- :width="columnWidths.lastNaturalDate">
|
|
|
|
|
- <template #default="scope">
|
|
|
|
|
- <el-date-picker
|
|
|
|
|
- v-model="scope.row.lastNaturalDate"
|
|
|
|
|
- type="date"
|
|
|
|
|
- placeholder="选择日期"
|
|
|
|
|
- format="YYYY-MM-DD"
|
|
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
|
|
- style="width: 100%"
|
|
|
|
|
- :disabled="true"
|
|
|
|
|
- />
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.NaturalDailyCycle')" align="center" prop="nextNaturalDate"
|
|
|
|
|
- :width="columnWidths.nextNaturalDate"/>
|
|
|
|
|
- <el-table-column :label="t('mainPlan.nextMaintDate')" align="center" prop="naturalDatePeriod"
|
|
|
|
|
- :width="columnWidths.naturalDatePeriod"/>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table>
|
|
|
|
|
- </div>
|
|
|
|
|
- <Pagination
|
|
|
|
|
- :total="total"
|
|
|
|
|
- v-model:page="queryParams.pageNo"
|
|
|
|
|
- v-model:limit="queryParams.pageSize"
|
|
|
|
|
- @pagination="handlePagination"
|
|
|
|
|
- />
|
|
|
|
|
- </ContentWrap>
|
|
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 时间分组列 -->
|
|
|
|
|
+ <ZmTableColumn v-if="showTimeColumns" label="保养时长" align="center">
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.lastMaintenanceOperationTime')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="lastRunningTime" />
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.RunTimeCycle')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="nextRunningTime" />
|
|
|
|
|
+ <ZmTableColumn :label="t('mainPlan.nextMaintTime')" align="center" prop="timePeriod">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span :class="{ 'negative-value': isNegative(row.timePeriod) }">
|
|
|
|
|
+ {{ row.timePeriod }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 里程分组列 -->
|
|
|
|
|
+ <ZmTableColumn v-if="showMileageColumns" label="保养里程" align="center">
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.lastMaintenanceMileage')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="lastRunningKilometers" />
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.operatingMileageCycle')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="nextRunningKilometers" />
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.nextMaintKil')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="kilometerCycle">
|
|
|
|
|
+ <template #default="{ row }">
|
|
|
|
|
+ <span :class="{ 'negative-value': isNegative(row.kilometerCycle) }">
|
|
|
|
|
+ {{ row.kilometerCycle }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 日期分组列 -->
|
|
|
|
|
+ <ZmTableColumn v-if="showNaturalDateColumns" label="保养日期" align="center">
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.lastMaintenanceNaturalDate')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="lastNaturalDate"
|
|
|
|
|
+ min-width="160">
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <el-date-picker
|
|
|
|
|
+ v-model="scope.row.lastNaturalDate"
|
|
|
|
|
+ type="date"
|
|
|
|
|
+ placeholder="选择日期"
|
|
|
|
|
+ format="YYYY-MM-DD"
|
|
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ :disabled="true" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.NaturalDailyCycle')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="nextNaturalDate" />
|
|
|
|
|
+ <ZmTableColumn
|
|
|
|
|
+ :label="t('mainPlan.nextMaintDate')"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="naturalDatePeriod" />
|
|
|
|
|
+ </ZmTableColumn>
|
|
|
|
|
+ </ZmTable>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <Pagination
|
|
|
|
|
+ class="mr-4"
|
|
|
|
|
+ :total="total"
|
|
|
|
|
+ v-model:page="queryParams.pageNo"
|
|
|
|
|
+ v-model:limit="queryParams.pageSize"
|
|
|
|
|
+ @pagination="handlePagination" />
|
|
|
|
|
+ </section>
|
|
|
|
|
+ </div>
|
|
|
</Dialog>
|
|
</Dialog>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { DictDataVO } from '@/api/system/dict/dict.data'
|
|
import { DictDataVO } from '@/api/system/dict/dict.data'
|
|
|
import dayjs from 'dayjs'
|
|
import dayjs from 'dayjs'
|
|
|
-import { IotMainWorkOrderBomApi, IotMainWorkOrderBomVO } from '@/api/pms/iotmainworkorderbom'
|
|
|
|
|
|
|
+import { IotMainWorkOrderBomApi } from '@/api/pms/iotmainworkorderbom'
|
|
|
import { IotMaintenanceBomApi, IotMaintenanceBomVO } from '@/api/pms/iotmaintenancebom'
|
|
import { IotMaintenanceBomApi, IotMaintenanceBomVO } from '@/api/pms/iotmaintenancebom'
|
|
|
-import {propTypes} from "@/utils/propTypes";
|
|
|
|
|
|
|
+import { propTypes } from '@/utils/propTypes'
|
|
|
|
|
+import { useTableComponents } from '@/components/ZmTable/useTableComponents'
|
|
|
const { t } = useI18n() // 国际化
|
|
const { t } = useI18n() // 国际化
|
|
|
|
|
+const { ZmTable, ZmTableColumn } = useTableComponents<IotMaintenanceBomVO>()
|
|
|
const emit = defineEmits(['close']) // 定义 success 事件,用于操作成功后的回调
|
|
const emit = defineEmits(['close']) // 定义 success 事件,用于操作成功后的回调
|
|
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
const dialogVisible = ref(false) // 弹窗的是否展示
|
|
|
const loading = ref(true) // 列表的加载中
|
|
const loading = ref(true) // 列表的加载中
|
|
@@ -145,10 +174,7 @@ const shouldResetPagination = ref(false)
|
|
|
// 添加外部传入的设备信息
|
|
// 添加外部传入的设备信息
|
|
|
const externalDeviceInfo = ref(null)
|
|
const externalDeviceInfo = ref(null)
|
|
|
|
|
|
|
|
-const dialogWidth = '1500px';
|
|
|
|
|
-
|
|
|
|
|
-const tableRef = ref(null) // 表格实例引用
|
|
|
|
|
-const columnWidths = ref({}) // 存储列宽的对象
|
|
|
|
|
|
|
+const dialogWidth = 'min(1200px, 92vw)'
|
|
|
|
|
|
|
|
const queryParams = reactive({
|
|
const queryParams = reactive({
|
|
|
pageNo: 1,
|
|
pageNo: 1,
|
|
@@ -159,69 +185,11 @@ const queryParams = reactive({
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
const props = defineProps({
|
|
|
- flag: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
|
|
|
|
|
|
|
+ flag: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const selectedRow = ref(null)
|
|
const selectedRow = ref(null)
|
|
|
|
|
|
|
|
-const getTextWidth = (str: string) => {
|
|
|
|
|
- if (!str) return 0;
|
|
|
|
|
- if (widthCache.has(str)) return widthCache.get(str)!;
|
|
|
|
|
-
|
|
|
|
|
- const span = document.createElement('span');
|
|
|
|
|
- span.style.visibility = 'hidden';
|
|
|
|
|
- span.style.position = 'absolute';
|
|
|
|
|
- span.style.whiteSpace = 'nowrap';
|
|
|
|
|
- span.style.font = '14px Microsoft YaHei';
|
|
|
|
|
- span.textContent = str;
|
|
|
|
|
-
|
|
|
|
|
- document.body.appendChild(span);
|
|
|
|
|
- const width = span.offsetWidth;
|
|
|
|
|
- document.body.removeChild(span);
|
|
|
|
|
-
|
|
|
|
|
- widthCache.set(str, width);
|
|
|
|
|
- return width;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 添加列宽计算函数
|
|
|
|
|
-const widthCache = new Map<string, number>();
|
|
|
|
|
-
|
|
|
|
|
-const flexColumnWidth = (label: string, prop: keyof IotMaintenanceBomVO) => {
|
|
|
|
|
- // 确保有数据时才计算
|
|
|
|
|
- if (!paginatedList.value.length) return "auto";
|
|
|
|
|
- // 基础内边距30px
|
|
|
|
|
- const basePadding = 20;
|
|
|
|
|
- const labelWidth = getActualWidth(label) + basePadding; // 文本宽度 + 内边距
|
|
|
|
|
- // 计算内容最大宽度
|
|
|
|
|
- let maxContentWidth = 0;
|
|
|
|
|
- // 获取该列所有内容的宽度
|
|
|
|
|
- for (const row of paginatedList.value) {
|
|
|
|
|
- let value = "";
|
|
|
|
|
-
|
|
|
|
|
- // 特殊列处理
|
|
|
|
|
- if (prop === "totalRunTime") {
|
|
|
|
|
- value = (row.totalRunTime ?? row.tempTotalRunTime)?.toString() || "";
|
|
|
|
|
- } else if (prop === "totalMileage") {
|
|
|
|
|
- value = (row.totalMileage ?? row.tempTotalMileage)?.toString() || "";
|
|
|
|
|
- } else {
|
|
|
|
|
- value = row[prop]?.toString() || "";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 数值格式化
|
|
|
|
|
- if (value && !isNaN(Number(value))) {
|
|
|
|
|
- value = Number(value).toLocaleString();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const contentWidth = getActualWidth(value) + basePadding;
|
|
|
|
|
- if (contentWidth > maxContentWidth) {
|
|
|
|
|
- maxContentWidth = contentWidth;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 返回较大值加上安全边距
|
|
|
|
|
- return Math.max(labelWidth, maxContentWidth, 120) + "px";
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
// 处理单选逻辑
|
|
// 处理单选逻辑
|
|
|
const selectRow = (row) => {
|
|
const selectRow = (row) => {
|
|
|
selectedRow.value = selectedRow.value?.id === row.id ? null : row
|
|
selectedRow.value = selectedRow.value?.id === row.id ? null : row
|
|
@@ -231,82 +199,21 @@ const selectRow = (row) => {
|
|
|
|
|
|
|
|
// 分页事件处理
|
|
// 分页事件处理
|
|
|
const handlePagination = () => {
|
|
const handlePagination = () => {
|
|
|
- console.log("分页变化,当前页:", queryParams.pageNo);
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 改进的宽度计算函数
|
|
|
|
|
-const getActualWidth = (text: string) => {
|
|
|
|
|
- if (!text) return 0;
|
|
|
|
|
-
|
|
|
|
|
- // 更精准的字符宽度计算
|
|
|
|
|
- const chineseChars = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
|
|
|
|
|
- const otherChars = text.length - chineseChars;
|
|
|
|
|
-
|
|
|
|
|
- // 中文16px,英文9px
|
|
|
|
|
- return chineseChars * 16 + otherChars * 9;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 设置列宽
|
|
|
|
|
-const setColumnWidths = () => {
|
|
|
|
|
- const widths: Record<string, string> = {};
|
|
|
|
|
-
|
|
|
|
|
- // 固定列
|
|
|
|
|
- // widths.deviceCode = flexColumnWidth(t('iotDevice.code'), 'deviceCode');
|
|
|
|
|
- // widths.deviceName = flexColumnWidth(t('iotDevice.name'), 'deviceName');
|
|
|
|
|
- widths.totalRunTime = flexColumnWidth(t('operationFillForm.sumTime'), 'totalRunTime');
|
|
|
|
|
- widths.totalMileage = flexColumnWidth(t('operationFillForm.sumKil'), 'totalMileage');
|
|
|
|
|
- widths.name = flexColumnWidth(t('mainPlan.MaintItems'), 'name');
|
|
|
|
|
-
|
|
|
|
|
- // 动态列
|
|
|
|
|
- if (showTimeColumns.value) {
|
|
|
|
|
- widths.lastRunningTime = flexColumnWidth(t('mainPlan.lastMaintenanceOperationTime'), 'lastRunningTime');
|
|
|
|
|
- widths.nextRunningTime = flexColumnWidth(t('mainPlan.RunTimeCycle'), 'nextRunningTime');
|
|
|
|
|
- widths.timePeriod = flexColumnWidth(t('mainPlan.nextMaintTime'), 'timePeriod');
|
|
|
|
|
- // 分组列宽度 = 子列宽度之和 + 边框补偿
|
|
|
|
|
- widths.timeGroup = `${[
|
|
|
|
|
- parseFloat(widths.lastRunningTime),
|
|
|
|
|
- parseFloat(widths.nextRunningTime),
|
|
|
|
|
- parseFloat(widths.timePeriod)
|
|
|
|
|
- ].reduce((sum, w) => sum + w, 0) + 2}px`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (showMileageColumns.value) {
|
|
|
|
|
- widths.lastRunningKilometers = flexColumnWidth(t('mainPlan.lastMaintenanceMileage'), 'lastRunningKilometers');
|
|
|
|
|
- widths.nextRunningKilometers = flexColumnWidth(t('mainPlan.operatingMileageCycle'), 'nextRunningKilometers');
|
|
|
|
|
- widths.kilometerCycle = flexColumnWidth(t('mainPlan.nextMaintKil'), 'kilometerCycle');
|
|
|
|
|
- widths.mileageGroup = `${[
|
|
|
|
|
- parseFloat(widths.lastRunningKilometers),
|
|
|
|
|
- parseFloat(widths.nextRunningKilometers),
|
|
|
|
|
- parseFloat(widths.kilometerCycle)
|
|
|
|
|
- ].reduce((sum, w) => sum + w, 0) + 2}px`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (showNaturalDateColumns.value) {
|
|
|
|
|
- widths.lastNaturalDate = flexColumnWidth(t('mainPlan.lastMaintenanceOperationTime'), 'lastNaturalDate'); // 固定日期选择器的宽度
|
|
|
|
|
- widths.nextNaturalDate = flexColumnWidth(t('mainPlan.NaturalDailyCycle'), 'nextNaturalDate');
|
|
|
|
|
- widths.naturalDatePeriod = flexColumnWidth(t('mainPlan.nextMaintDate'), 'naturalDatePeriod');
|
|
|
|
|
- widths.dateGroup = `${[
|
|
|
|
|
- parseFloat(widths.lastNaturalDate),
|
|
|
|
|
- parseFloat(widths.nextNaturalDate),
|
|
|
|
|
- parseFloat(widths.naturalDatePeriod)
|
|
|
|
|
- ].reduce((sum, w) => sum + w, 0) + 2}px`;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- columnWidths.value = widths;
|
|
|
|
|
-};
|
|
|
|
|
|
|
+ console.log('分页变化,当前页:', queryParams.pageNo)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
// 分页计算属性
|
|
// 分页计算属性
|
|
|
const paginatedList = computed(() => {
|
|
const paginatedList = computed(() => {
|
|
|
- const start = (queryParams.pageNo - 1) * queryParams.pageSize;
|
|
|
|
|
- const end = start + queryParams.pageSize;
|
|
|
|
|
- return list.value.slice(start, end);
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ const start = (queryParams.pageNo - 1) * queryParams.pageSize
|
|
|
|
|
+ const end = start + queryParams.pageSize
|
|
|
|
|
+ return list.value.slice(start, end)
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
const open = async (id?: number, flag?: string, deviceInfo?: any) => {
|
|
const open = async (id?: number, flag?: string, deviceInfo?: any) => {
|
|
|
// 重置分页参数
|
|
// 重置分页参数
|
|
|
queryParams.pageNo = 1
|
|
queryParams.pageNo = 1
|
|
|
queryParams.pageSize = 10
|
|
queryParams.pageSize = 10
|
|
|
- list.value = [] // 清空列表避免显示旧数据
|
|
|
|
|
|
|
+ list.value = [] // 清空列表避免显示旧数据
|
|
|
total.value = 0
|
|
total.value = 0
|
|
|
|
|
|
|
|
await nextTick() // 确保DOM更新完成
|
|
await nextTick() // 确保DOM更新完成
|
|
@@ -314,7 +221,7 @@ const open = async (id?: number, flag?: string, deviceInfo?: any) => {
|
|
|
externalDeviceInfo.value = deviceInfo
|
|
externalDeviceInfo.value = deviceInfo
|
|
|
queryParams.deviceId = deviceInfo.deviceId // 如果需要的话
|
|
queryParams.deviceId = deviceInfo.deviceId // 如果需要的话
|
|
|
}
|
|
}
|
|
|
- if('workOrder' === flag) {
|
|
|
|
|
|
|
+ if ('workOrder' === flag) {
|
|
|
// 加载保养工单 BOM
|
|
// 加载保养工单 BOM
|
|
|
queryParams.workOrderId = id
|
|
queryParams.workOrderId = id
|
|
|
queryParams.planId = undefined
|
|
queryParams.planId = undefined
|
|
@@ -334,7 +241,7 @@ const getWorkOrderList = async () => {
|
|
|
try {
|
|
try {
|
|
|
const data = await IotMainWorkOrderBomApi.getWorkOrderBOMs(queryParams)
|
|
const data = await IotMainWorkOrderBomApi.getWorkOrderBOMs(queryParams)
|
|
|
// 格式化日期字段
|
|
// 格式化日期字段
|
|
|
- data.forEach(item => {
|
|
|
|
|
|
|
+ data.forEach((item) => {
|
|
|
if (item.lastNaturalDate) {
|
|
if (item.lastNaturalDate) {
|
|
|
// 将时间戳转换为 YYYY-MM-DD 格式
|
|
// 将时间戳转换为 YYYY-MM-DD 格式
|
|
|
item.lastNaturalDate = dayjs(item.lastNaturalDate).format('YYYY-MM-DD')
|
|
item.lastNaturalDate = dayjs(item.lastNaturalDate).format('YYYY-MM-DD')
|
|
@@ -343,9 +250,9 @@ const getWorkOrderList = async () => {
|
|
|
item.lastNaturalDate = ''
|
|
item.lastNaturalDate = ''
|
|
|
}
|
|
}
|
|
|
// 计算下次保养运行时长 H
|
|
// 计算下次保养运行时长 H
|
|
|
- item.timePeriod = calculateTimePeriod(item);
|
|
|
|
|
|
|
+ item.timePeriod = calculateTimePeriod(item)
|
|
|
// 计算下次保养公里数 KM
|
|
// 计算下次保养公里数 KM
|
|
|
- item.kilometerCycle = calculateKiloPeriod(item);
|
|
|
|
|
|
|
+ item.kilometerCycle = calculateKiloPeriod(item)
|
|
|
// 计算下次保养日期
|
|
// 计算下次保养日期
|
|
|
item.naturalDatePeriod = calculateNextNaturalDate(item)
|
|
item.naturalDatePeriod = calculateNextNaturalDate(item)
|
|
|
})
|
|
})
|
|
@@ -357,12 +264,11 @@ const getWorkOrderList = async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const getPlanList = async () => {
|
|
const getPlanList = async () => {
|
|
|
- widthCache.clear();
|
|
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
try {
|
|
try {
|
|
|
const data = await IotMaintenanceBomApi.getMainPlanBOMs(queryParams)
|
|
const data = await IotMaintenanceBomApi.getMainPlanBOMs(queryParams)
|
|
|
// 格式化日期字段
|
|
// 格式化日期字段
|
|
|
- data.forEach(item => {
|
|
|
|
|
|
|
+ data.forEach((item) => {
|
|
|
if (item.lastNaturalDate) {
|
|
if (item.lastNaturalDate) {
|
|
|
// 将时间戳转换为 YYYY-MM-DD 格式
|
|
// 将时间戳转换为 YYYY-MM-DD 格式
|
|
|
item.lastNaturalDate = dayjs(item.lastNaturalDate).format('YYYY-MM-DD')
|
|
item.lastNaturalDate = dayjs(item.lastNaturalDate).format('YYYY-MM-DD')
|
|
@@ -371,9 +277,9 @@ const getPlanList = async () => {
|
|
|
item.lastNaturalDate = ''
|
|
item.lastNaturalDate = ''
|
|
|
}
|
|
}
|
|
|
// 计算下次保养运行时长 H
|
|
// 计算下次保养运行时长 H
|
|
|
- item.timePeriod = calculateTimePeriod(item);
|
|
|
|
|
|
|
+ item.timePeriod = calculateTimePeriod(item)
|
|
|
// 计算下次保养公里数 KM
|
|
// 计算下次保养公里数 KM
|
|
|
- item.kilometerCycle = calculateKiloPeriod(item);
|
|
|
|
|
|
|
+ item.kilometerCycle = calculateKiloPeriod(item)
|
|
|
// 计算下次保养日期
|
|
// 计算下次保养日期
|
|
|
item.naturalDatePeriod = calculateNextNaturalDate(item)
|
|
item.naturalDatePeriod = calculateNextNaturalDate(item)
|
|
|
})
|
|
})
|
|
@@ -381,7 +287,6 @@ const getPlanList = async () => {
|
|
|
total.value = data.length
|
|
total.value = data.length
|
|
|
} finally {
|
|
} finally {
|
|
|
loading.value = false
|
|
loading.value = false
|
|
|
- nextTick(setColumnWidths); // 数据加载后计算列宽
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -389,18 +294,18 @@ const getPlanList = async () => {
|
|
|
const deviceInfo = computed(() => {
|
|
const deviceInfo = computed(() => {
|
|
|
// 优先使用外部传入的设备信息
|
|
// 优先使用外部传入的设备信息
|
|
|
if (externalDeviceInfo.value) {
|
|
if (externalDeviceInfo.value) {
|
|
|
- return externalDeviceInfo.value;
|
|
|
|
|
|
|
+ return externalDeviceInfo.value
|
|
|
}
|
|
}
|
|
|
if (list.value.length > 0) {
|
|
if (list.value.length > 0) {
|
|
|
- const firstRecord = list.value[0];
|
|
|
|
|
|
|
+ const firstRecord = list.value[0]
|
|
|
return {
|
|
return {
|
|
|
deviceCode: firstRecord.deviceCode,
|
|
deviceCode: firstRecord.deviceCode,
|
|
|
deviceName: firstRecord.deviceName,
|
|
deviceName: firstRecord.deviceName,
|
|
|
model: firstRecord.model // 确保列表数据中也有 model
|
|
model: firstRecord.model // 确保列表数据中也有 model
|
|
|
- };
|
|
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- return null;
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ return null
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
const handleClose = () => {
|
|
const handleClose = () => {
|
|
|
// 重置状态避免多个弹窗出现
|
|
// 重置状态避免多个弹窗出现
|
|
@@ -419,32 +324,30 @@ const handleClose = () => {
|
|
|
// 计算 距离下次保养运行时长 H
|
|
// 计算 距离下次保养运行时长 H
|
|
|
const calculateTimePeriod = (item: IotMaintenanceBomVO) => {
|
|
const calculateTimePeriod = (item: IotMaintenanceBomVO) => {
|
|
|
if (item.runningTimeRule === 0) {
|
|
if (item.runningTimeRule === 0) {
|
|
|
- const totalRunVal = item.totalRunTime ?? item.tempTotalRunTime;
|
|
|
|
|
- const next = Number(item.nextRunningTime) || 0;
|
|
|
|
|
- const totalRun = totalRunVal != null ? Number(totalRunVal) : 0;
|
|
|
|
|
- const lastRun = Number(item.lastRunningTime) || 0;
|
|
|
|
|
- const result = next - (totalRun - lastRun);
|
|
|
|
|
- return Number(result.toFixed(2));
|
|
|
|
|
|
|
+ const totalRunVal = item.totalRunTime ?? item.tempTotalRunTime
|
|
|
|
|
+ const next = Number(item.nextRunningTime) || 0
|
|
|
|
|
+ const totalRun = totalRunVal != null ? Number(totalRunVal) : 0
|
|
|
|
|
+ const lastRun = Number(item.lastRunningTime) || 0
|
|
|
|
|
+ const result = next - (totalRun - lastRun)
|
|
|
|
|
+ return Number(result.toFixed(2))
|
|
|
}
|
|
}
|
|
|
- return typeof item.timePeriod === 'number'
|
|
|
|
|
- ? Number(item.timePeriod.toFixed(2))
|
|
|
|
|
- : item.timePeriod;
|
|
|
|
|
-};
|
|
|
|
|
|
|
+ return typeof item.timePeriod === 'number' ? Number(item.timePeriod.toFixed(2)) : item.timePeriod
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
// 计算 距离下次保养公里数 KM
|
|
// 计算 距离下次保养公里数 KM
|
|
|
const calculateKiloPeriod = (item: IotMaintenanceBomVO) => {
|
|
const calculateKiloPeriod = (item: IotMaintenanceBomVO) => {
|
|
|
if (item.mileageRule === 0) {
|
|
if (item.mileageRule === 0) {
|
|
|
- const totalRunVal = item.totalMileage ?? item.tempTotalMileage;
|
|
|
|
|
- const next = Number(item.nextRunningKilometers) || 0;
|
|
|
|
|
- const totalRun = totalRunVal != null ? Number(totalRunVal) : 0;
|
|
|
|
|
- const lastRun = Number(item.lastRunningKilometers) || 0;
|
|
|
|
|
- const result = next - (totalRun - lastRun);
|
|
|
|
|
- return Number(result.toFixed(2));
|
|
|
|
|
|
|
+ const totalRunVal = item.totalMileage ?? item.tempTotalMileage
|
|
|
|
|
+ const next = Number(item.nextRunningKilometers) || 0
|
|
|
|
|
+ const totalRun = totalRunVal != null ? Number(totalRunVal) : 0
|
|
|
|
|
+ const lastRun = Number(item.lastRunningKilometers) || 0
|
|
|
|
|
+ const result = next - (totalRun - lastRun)
|
|
|
|
|
+ return Number(result.toFixed(2))
|
|
|
}
|
|
}
|
|
|
return typeof item.kilometerCycle === 'number'
|
|
return typeof item.kilometerCycle === 'number'
|
|
|
? Number(item.kilometerCycle.toFixed(2))
|
|
? Number(item.kilometerCycle.toFixed(2))
|
|
|
- : item.kilometerCycle;
|
|
|
|
|
-};
|
|
|
|
|
|
|
+ : item.kilometerCycle
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
// 计算下次保养日期
|
|
// 计算下次保养日期
|
|
|
const calculateNextNaturalDate = (item: IotMaintenanceBomVO): string => {
|
|
const calculateNextNaturalDate = (item: IotMaintenanceBomVO): string => {
|
|
@@ -456,18 +359,18 @@ const calculateNextNaturalDate = (item: IotMaintenanceBomVO): string => {
|
|
|
|
|
|
|
|
// 计算属性:控制时间相关列的显示
|
|
// 计算属性:控制时间相关列的显示
|
|
|
const showTimeColumns = computed(() => {
|
|
const showTimeColumns = computed(() => {
|
|
|
- return paginatedList.value.some(item => item.runningTimeRule === 0);
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ return paginatedList.value.some((item) => item.runningTimeRule === 0)
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 计算属性:控制里程相关列的显示
|
|
// 计算属性:控制里程相关列的显示
|
|
|
const showMileageColumns = computed(() => {
|
|
const showMileageColumns = computed(() => {
|
|
|
- return paginatedList.value.some(item => item.mileageRule === 0);
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ return paginatedList.value.some((item) => item.mileageRule === 0)
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 计算属性:自然日期相关列的显示
|
|
// 计算属性:自然日期相关列的显示
|
|
|
const showNaturalDateColumns = computed(() => {
|
|
const showNaturalDateColumns = computed(() => {
|
|
|
- return paginatedList.value.some(item => item.naturalDateRule === 0);
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ return paginatedList.value.some((item) => item.naturalDateRule === 0)
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
/** 搜索按钮操作 */
|
|
/** 搜索按钮操作 */
|
|
|
const handleQuery = () => {
|
|
const handleQuery = () => {
|
|
@@ -486,192 +389,171 @@ const resetQuery = () => {
|
|
|
|
|
|
|
|
// 判断是否为负数的辅助函数
|
|
// 判断是否为负数的辅助函数
|
|
|
const isNegative = (value: any): boolean => {
|
|
const isNegative = (value: any): boolean => {
|
|
|
- if (value === null || value === undefined || value === '') return false;
|
|
|
|
|
- const num = Number(value);
|
|
|
|
|
- return !isNaN(num) && num < 0;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 监听分页数据变化,重新设置列宽
|
|
|
|
|
-watch(paginatedList, () => {
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- setColumnWidths();
|
|
|
|
|
- });
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-// 监听动态列的变化
|
|
|
|
|
-watch([showTimeColumns, showMileageColumns, showNaturalDateColumns], () => {
|
|
|
|
|
- nextTick(setColumnWidths);
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (value === null || value === undefined || value === '') return false
|
|
|
|
|
+ const num = Number(value)
|
|
|
|
|
+ return !isNaN(num) && num < 0
|
|
|
|
|
+}
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
|
|
+@media (width <= 768px) {
|
|
|
|
|
+ .dialog-title__subtitle {
|
|
|
|
|
+ display: none;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .device-info-grid {
|
|
|
|
|
+ grid-template-columns: minmax(0, 1fr);
|
|
|
|
|
+ padding: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .maintenance-section .table-container {
|
|
|
|
|
+ padding-right: 12px;
|
|
|
|
|
+ padding-left: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-/* 设备信息卡片样式 */
|
|
|
|
|
.device-info-card {
|
|
.device-info-card {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- gap: 24px; /* 项间距 */
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
padding: 16px;
|
|
padding: 16px;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
background-color: #f8f9fa;
|
|
background-color: #f8f9fa;
|
|
|
border-radius: 8px;
|
|
border-radius: 8px;
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
|
|
|
|
|
|
+ box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 24px; /* 项间距 */
|
|
|
|
|
|
|
|
.info-item {
|
|
.info-item {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
|
|
|
|
|
.info-label {
|
|
.info-label {
|
|
|
|
|
+ margin-right: 8px;
|
|
|
font-weight: 600;
|
|
font-weight: 600;
|
|
|
color: #606266;
|
|
color: #606266;
|
|
|
- margin-right: 8px;
|
|
|
|
|
white-space: nowrap;
|
|
white-space: nowrap;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.info-value {
|
|
.info-value {
|
|
|
|
|
+ min-width: 200px;
|
|
|
|
|
+ padding: 4px 12px;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
color: #303133;
|
|
color: #303133;
|
|
|
- padding: 4px 12px;
|
|
|
|
|
- background: #ffffff;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
|
|
+ background: #fff;
|
|
|
border: 1px solid #ebeef5;
|
|
border: 1px solid #ebeef5;
|
|
|
- min-width: 200px;
|
|
|
|
|
|
|
+ border-radius: 4px;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 分组表头样式 */
|
|
|
|
|
-:deep(.el-table .el-table__header .el-table-column--group) {
|
|
|
|
|
- background-color: #f5f7fa;
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-
|
|
|
|
|
- > .cell {
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
- color: #303133;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- background-color: #f0f7ff;
|
|
|
|
|
- border: 1px solid #409eff !important;
|
|
|
|
|
- box-shadow: 0 2px 4px rgba(64, 158, 255, 0.2);
|
|
|
|
|
-
|
|
|
|
|
- > .cell {
|
|
|
|
|
- font-weight: 700;
|
|
|
|
|
- color: #1d63dc;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/* 负数值样式 */
|
|
|
|
|
+.negative-value {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #f56c6c;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 加深所有单元格边框 */
|
|
|
|
|
-:deep(.el-table__header th) {
|
|
|
|
|
- border: 1px solid #c0c4cc !important;
|
|
|
|
|
|
|
+.dialog-title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ min-width: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 分组内部单元格特殊样式 */
|
|
|
|
|
-:deep(.el-table-column--group .el-table__cell) {
|
|
|
|
|
- border-top: 1px dashed #a0cfff !important;
|
|
|
|
|
|
|
+.dialog-title__icon {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ width: 38px;
|
|
|
|
|
+ height: 38px;
|
|
|
|
|
+ margin-right: 12px;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ color: var(--el-color-primary);
|
|
|
|
|
+ background: var(--el-color-primary-light-9);
|
|
|
|
|
+ border: 1px solid var(--el-color-primary-light-7);
|
|
|
|
|
+ border-radius: 8px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 分组间垂直线 */
|
|
|
|
|
-:deep(.el-table-column--group) {
|
|
|
|
|
- position: relative;
|
|
|
|
|
-
|
|
|
|
|
- &::after {
|
|
|
|
|
- content: "";
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- right: -1px;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- bottom: 0;
|
|
|
|
|
- width: 2px;
|
|
|
|
|
- background: linear-gradient(to bottom, #409eff, #79bbff);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.dialog-title__text {
|
|
|
|
|
+ font-size: 17px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ line-height: 24px;
|
|
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 新版CSS解决方案 */
|
|
|
|
|
-.fixed-height-dialog {
|
|
|
|
|
- :deep(.el-dialog) {
|
|
|
|
|
- width: 1500px !important; /* 固定宽度 */
|
|
|
|
|
- height: 85vh !important; /* 使用视口高度 */
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- margin-top: 5vh !important; /* 垂直居中 */
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /* 添加媒体查询,确保在小屏幕上也能完整显示 */
|
|
|
|
|
- @media (max-width: 1500px) {
|
|
|
|
|
- :deep(.el-dialog) {
|
|
|
|
|
- width: 95% !important;
|
|
|
|
|
- max-width: 1500px; /* 仍然限制最大宽度 */
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.dialog-title__subtitle {
|
|
|
|
|
+ margin-top: 1px;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- :deep(.el-dialog__header) {
|
|
|
|
|
- padding: 20px;
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.dialog-content {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- :deep(.el-dialog__body) {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- padding: 10px 20px;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- overflow: hidden; /* 防止内容溢出 */
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.device-info-section,
|
|
|
|
|
+.maintenance-section {
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ border: 1px solid var(--el-border-color-lighter);
|
|
|
|
|
+ border-radius: 8px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 表格容器 */
|
|
|
|
|
-.table-container {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- overflow: auto;
|
|
|
|
|
- position: relative;
|
|
|
|
|
-
|
|
|
|
|
- .scrollable-table {
|
|
|
|
|
- width: 100%; /* 自适应宽度 */
|
|
|
|
|
-
|
|
|
|
|
- :deep(.el-table__header) {
|
|
|
|
|
- th {
|
|
|
|
|
- white-space: nowrap !important; /* 强制表头不换行 */
|
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- padding: 8px 0; /* 增加内边距 */
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.section-heading {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ height: 44px;
|
|
|
|
|
+ padding: 0 16px;
|
|
|
|
|
+ font-size: 15px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
|
|
+ background: var(--el-fill-color-extra-light);
|
|
|
|
|
+ border-bottom: 1px solid var(--el-border-color-lighter);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- :deep(.el-table__body) {
|
|
|
|
|
- td {
|
|
|
|
|
- white-space: nowrap !important; /* 强制内容不换行 */
|
|
|
|
|
- text-overflow: ellipsis;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- padding: 8px 0; /* 增加内边距 */
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.section-heading span {
|
|
|
|
|
+ width: 4px;
|
|
|
|
|
+ height: 17px;
|
|
|
|
|
+ margin-right: 9px;
|
|
|
|
|
+ background: var(--el-color-primary);
|
|
|
|
|
+ border-radius: 2px;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- :deep(.el-table__body-wrapper) {
|
|
|
|
|
- overflow-x: hidden !important; /* 隐藏X轴滚动条 */
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.device-info-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ padding: 14px 16px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 分页样式 */
|
|
|
|
|
-.pagination-footer {
|
|
|
|
|
- margin-top: 15px;
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
|
|
+.device-info-grid .info-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ padding: 10px 12px;
|
|
|
|
|
+ background: var(--el-fill-color-extra-light);
|
|
|
|
|
+ border: 1px solid var(--el-border-color-lighter);
|
|
|
|
|
+ border-radius: 6px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 响应式处理 - 确保在小屏幕上布局合理 */
|
|
|
|
|
-@media (max-width: 1500px) {
|
|
|
|
|
- .fixed-height-dialog :deep(.el-dialog) {
|
|
|
|
|
- width: 95% !important;
|
|
|
|
|
- max-width: 98vw;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.device-info-grid .info-label {
|
|
|
|
|
+ flex: 0 0 auto;
|
|
|
|
|
+ margin-right: 10px;
|
|
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- .table-container {
|
|
|
|
|
- overflow-x: auto;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+.device-info-grid .info-value {
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 负数值样式 */
|
|
|
|
|
-.negative-value {
|
|
|
|
|
- color: #f56c6c;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
|
|
+.maintenance-section .table-container {
|
|
|
|
|
+ padding: 14px 16px 0;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 设备信息卡片样式 */
|
|
|
</style>
|
|
</style>
|