Browse Source

refactor(mainplandevicelist): 调整设备名称固定列宽,超出tooltip

Zimo 2 ngày trước cách đây
mục cha
commit
0c3ce6b281
1 tập tin đã thay đổi với 250 bổ sung184 xóa
  1. 250 184
      src/views/pms/maintenance/MainPlanDeviceList.vue

+ 250 - 184
src/views/pms/maintenance/MainPlanDeviceList.vue

@@ -1,8 +1,12 @@
 <template>
-  <Dialog v-model="dialogVisible" :title="t('deviceList.selectDevice')"
-          :style="{ width: dialogWidth }"
-          :body-style="{ height: '100%' }"
-          class="device-select-dialog"  @close="handleClose" :close-on-click-modal="false">
+  <Dialog
+    v-model="dialogVisible"
+    :title="t('deviceList.selectDevice')"
+    :style="{ width: dialogWidth }"
+    :body-style="{ height: '100%' }"
+    class="device-select-dialog"
+    @close="handleClose"
+    :close-on-click-modal="false">
     <ContentWrap class="dialog-top">
       <el-form
         class="-mb-15px"
@@ -10,31 +14,33 @@
         ref="queryFormRef"
         :inline="true"
         label-width="68px"
-        @submit.prevent
-      >
-        <el-form-item  :label="t('deviceList.deviceName')" prop="deviceName">
+        @submit.prevent>
+        <el-form-item :label="t('deviceList.deviceName')" prop="deviceName">
           <el-input
             @keyup.enter="handleQuery"
             v-model="queryParams.deviceName"
             :placeholder="t('deviceList.nameHolder')"
             clearable
-            class="!w-200px"
-          />
+            class="!w-200px" />
         </el-form-item>
-        <el-form-item  :label="t('deviceList.deviceCode')" prop="deviceCode">
+        <el-form-item :label="t('deviceList.deviceCode')" prop="deviceCode">
           <el-input
             @keyup.enter="handleQuery"
             v-model="queryParams.deviceCode"
             :placeholder="t('deviceList.codeHolder')"
             clearable
-            class="!w-200px"
-          />
+            class="!w-200px" />
         </el-form-item>
         <el-form-item>
-          <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" />
-            {{ t('deviceList.search') }}</el-button>
-          <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> {{ t('deviceList.reset') }}</el-button>
-          <el-button @click="handleConfirm" class="custom-green-button"><Icon icon="ep:check" class="mr-5px" /> {{ t('workOrderMaterial.confirm') }}</el-button>
+          <el-button @click="handleQuery"
+            ><Icon icon="ep:search" class="mr-5px" /> {{ t('deviceList.search') }}</el-button
+          >
+          <el-button @click="resetQuery"
+            ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('deviceList.reset') }}</el-button
+          >
+          <el-button @click="handleConfirm" class="custom-green-button"
+            ><Icon icon="ep:check" class="mr-5px" /> {{ t('workOrderMaterial.confirm') }}</el-button
+          >
         </el-form-item>
       </el-form>
     </ContentWrap>
@@ -49,51 +55,79 @@
           @row-click="handleRowClick"
           :max-height="effectiveTableHeight"
           style="width: 100%; min-width: 100%"
-          class="fixed-layout-table"
-        >
+          class="fixed-layout-table">
           <el-table-column width="60" :label="t('workOrderMaterial.select')">
             <template #default="{ row }">
               <el-checkbox
-                :model-value="selectedRows.some(item => item.id === row.id)"
+                :model-value="selectedRows.some((item) => item.id === row.id)"
                 @click.stop="toggleRow(row)"
-                class="no-label-radio"
-              />
+                class="no-label-radio" />
             </template>
           </el-table-column>
-          <el-table-column :label="t('chooseMaintain.deviceCode')" align="center" prop="deviceCode" :min-width="flexColumnMinWidths.deviceCode"/>
-          <el-table-column :label="t('deviceList.deviceName')" align="center" prop="deviceName" :min-width="flexColumnMinWidths.deviceName">
+          <el-table-column
+            :label="t('chooseMaintain.deviceCode')"
+            align="center"
+            prop="deviceCode"
+            :min-width="flexColumnMinWidths.deviceCode" />
+          <el-table-column
+            :label="t('deviceList.deviceName')"
+            align="center"
+            prop="deviceName"
+            width="320"
+            show-overflow-tooltip
+            class-name="device-name-column">
             <template #default="{ row }">
-              <div class="flex-cell">
+              <div class="device-name-cell">
                 {{ row.deviceName }}
               </div>
             </template>
           </el-table-column>
-          <el-table-column :label="t('faultForm.deptId')" align="center" prop="deptId" v-if="false"/>
-          <el-table-column :label="t('iotDevice.dept')" align="center" prop="deptName" :min-width="flexColumnMinWidths.deptName"/>
-          <el-table-column :label="t('iotDevice.status')" align="center" prop="deviceStatus" :min-width="flexColumnMinWidths.deviceStatus">
+          <el-table-column
+            :label="t('faultForm.deptId')"
+            align="center"
+            prop="deptId"
+            v-if="false" />
+          <el-table-column
+            :label="t('iotDevice.dept')"
+            align="center"
+            prop="deptName"
+            :min-width="flexColumnMinWidths.deptName" />
+          <el-table-column
+            :label="t('iotDevice.status')"
+            align="center"
+            prop="deviceStatus"
+            :min-width="flexColumnMinWidths.deviceStatus">
             <template #default="scope">
               <dict-tag :type="DICT_TYPE.PMS_DEVICE_STATUS" :value="scope.row.deviceStatus" />
             </template>
           </el-table-column>
-          <el-table-column :label="t('deviceInfo.deviceBOM')" align="center" prop="hasSetMaintenanceBom" :min-width="flexColumnMinWidths.createTime">
+          <el-table-column
+            :label="t('deviceInfo.deviceBOM')"
+            align="center"
+            prop="hasSetMaintenanceBom"
+            :min-width="flexColumnMinWidths.createTime">
             <template #header>
               <div class="column-header">
                 {{ t('deviceInfo.deviceBOM') }}
                 <!-- 添加感叹号图标,并使用 el-tooltip 显示提示 -->
-                <el-tooltip
-                  effect="dark"
-                  content="请选择有保养项的设备"
-                  placement="top"
-                >
-                  <el-icon :size="12" color="#e6a23c" style="cursor: pointer; margin-left: 3px">
+                <el-tooltip effect="dark" content="请选择有保养项的设备" placement="top">
+                  <el-icon :size="12" color="#e6a23c" style="margin-left: 3px; cursor: pointer">
                     <WarningFilled />
                   </el-icon>
                 </el-tooltip>
               </div>
             </template>
             <template #default="{ row }">
-              <div :class="{'no-maintenance': !row.hasSetMaintenanceBom, 'has-maintenance': row.hasSetMaintenanceBom}">
-                {{ row.hasSetMaintenanceBom ? t('mainPlan.haveMaintItems') : t('mainPlan.noMaintItems') }}
+              <div
+                :class="{
+                  'no-maintenance': !row.hasSetMaintenanceBom,
+                  'has-maintenance': row.hasSetMaintenanceBom
+                }">
+                {{
+                  row.hasSetMaintenanceBom
+                    ? t('mainPlan.haveMaintItems')
+                    : t('mainPlan.noMaintItems')
+                }}
               </div>
             </template>
           </el-table-column>
@@ -118,8 +152,7 @@
         :total="total"
         v-model:page="queryParams.pageNo"
         v-model:limit="queryParams.pageSize"
-        @pagination="getList"
-      />
+        @pagination="getList" />
     </ContentWrap>
   </Dialog>
 </template>
@@ -127,8 +160,7 @@
 <script setup lang="ts">
 import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
 import { DICT_TYPE } from '@/utils/dict'
-import { dateFormatter } from '@/utils/formatTime'
-import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import { useCache } from '@/hooks/web/useCache'
 import { WarningFilled } from '@element-plus/icons-vue'
 
 const dialogVisible = ref(false) // 弹窗的是否展示
@@ -136,8 +168,8 @@ const loading = ref(true) // 列表的加载中
 const queryFormRef = ref() // 搜索的表单
 const list = ref<IotDeviceVO[]>([]) // 列表的数据
 const total = ref(0) // 列表的总页数
-const tableRef = ref();
-const selectedRows = ref<IotDeviceVO[]>([]); // 多选数据(存储所有选中行的数组)
+const tableRef = ref()
+const selectedRows = ref<IotDeviceVO[]>([]) // 多选数据(存储所有选中行的数组)
 const { t } = useI18n() // 国际化
 // 调整 emit 类型
 const emit = defineEmits<{
@@ -159,11 +191,11 @@ const queryParams = reactive({
 })
 
 // 响应式变量
-const dialogWidth = ref('1100px');
-const tableMinHeight = ref(400); // 初始最小高度
-const effectiveTableHeight = ref<number | null>(null); // 单一高度变量
-const dialogTopRef = ref<HTMLElement | null>(null);
-const showPagination = ref(false); // 控制分页显示
+const dialogWidth = ref('1100px')
+const tableMinHeight = ref(400) // 初始最小高度
+const effectiveTableHeight = ref<number | null>(null) // 单一高度变量
+const dialogTopRef = ref<HTMLElement | null>(null)
+const showPagination = ref(false) // 控制分页显示
 const tableContainerWidth = ref(0) // 表格容器宽度
 
 // 弹性列最小宽度记录
@@ -186,31 +218,35 @@ const open = async () => {
   queryFormRef.value?.resetFields()
 
   // 初始隐藏分页组件
-  showPagination.value = false;
+  showPagination.value = false
 
   await getList()
 
   // 动态计算宽度
-  await nextTick();
-  const viewportWidth = window.innerWidth;
+  await nextTick()
+  const viewportWidth = window.innerWidth
   if (viewportWidth < 1200) {
     // 小屏幕自适应
-    dialogWidth.value = Math.min(1100, viewportWidth - 40) + 'px';
+    dialogWidth.value = Math.min(1100, viewportWidth - 40) + 'px'
   } else {
     // 大屏幕保持固定
-    dialogWidth.value = '1100px';
+    dialogWidth.value = '1100px'
   }
   // 确保计算高度的DOM已渲染
-  await nextTick();
-  calculateTableHeight();
+  await nextTick()
+  calculateTableHeight()
 }
 
 defineExpose({ open })
 const { wsCache } = useCache()
 
 // 文本测量工具函数
-const measureText = (text: string, fontSize: string = '14px',
-                     fontWeight: string = 'normal', extraStyles: Record<string, string> = {}): number => {
+const measureText = (
+  text: string,
+  fontSize: string = '14px',
+  fontWeight: string = 'normal',
+  extraStyles: Record<string, string> = {}
+): number => {
   const span = document.createElement('span')
   span.style.visibility = 'hidden'
   span.style.position = 'absolute'
@@ -221,37 +257,37 @@ const measureText = (text: string, fontSize: string = '14px',
   span.textContent = text
 
   // 应用额外样式
-  Object.keys(extraStyles).forEach(key => {
-    span.style[key as any] = extraStyles[key];
-  });
+  Object.keys(extraStyles).forEach((key) => {
+    span.style[key as any] = extraStyles[key]
+  })
 
   document.body.appendChild(span)
   const width = span.offsetWidth
   document.body.removeChild(span)
 
   return width
-};
+}
 
 // 自定义日期时间格式化函数
 const formatDateTime = (dateString: string | Date) => {
-  if (!dateString) return '';
+  if (!dateString) return ''
 
-  const date = new Date(dateString);
+  const date = new Date(dateString)
 
   // 确保日期有效
   if (isNaN(date.getTime())) {
-    return String(dateString).replace(/[\r\n]/g, '');;
+    return String(dateString).replace(/[\r\n]/g, '')
   }
 
-  const year = date.getFullYear();
-  const month = String(date.getMonth() + 1).padStart(2, '0');
-  const day = String(date.getDate()).padStart(2, '0');
-  const hours = String(date.getHours()).padStart(2, '0');
-  const minutes = String(date.getMinutes()).padStart(2, '0');
-  const seconds = String(date.getSeconds()).padStart(2, '0');
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  const hours = String(date.getHours()).padStart(2, '0')
+  const minutes = String(date.getMinutes()).padStart(2, '0')
+  const seconds = String(date.getSeconds()).padStart(2, '0')
 
-  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`.replace(/[\r\n]/g, '');
-};
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`.replace(/[\r\n]/g, '')
+}
 
 // 列宽计算函数
 const calculateColumnWidths = async () => {
@@ -277,60 +313,63 @@ const calculateColumnWidths = async () => {
     // 测量表头宽度 - 使用表头实际样式
     const headerWidth = col.label
       ? measureText(col.label, '14px', 'bold', {
-      padding: '0 12px', // 表头实际内边距
-      boxSizing: 'border-box'
-    }) + 0 // 安全边距
-      : 0;
+          padding: '0 12px', // 表头实际内边距
+          boxSizing: 'border-box'
+        }) + 0 // 安全边距
+      : 0
 
     // 测量单元格内容宽度
     let maxCellWidth = 0
-    rows.forEach(row => {
+    rows.forEach((row) => {
       let cellValue = ''
       let cellWidth = 0
       if (col.property === 'createTime') {
         // 特殊处理:使用格式化后的日期文本
         cellValue = formatDateTime(row[col.property])
         // 使用完整时间样本确保宽度足够
-        const sampleText = '2024-12-31 23:59:59';
+        const sampleText = '2024-12-31 23:59:59'
         const sampleWidth = measureText(sampleText, '14px', 'normal', {
           padding: '0 12px',
           boxSizing: 'border-box'
-        });
+        })
         // 时间列额外增加安全边距
-        cellWidth = Math.max(
-          measureText(cellValue, '14px', 'normal', {
-            padding: '0 12px',
-            boxSizing: 'border-box'
-          }),
-          sampleWidth
-        ) + 0; // 安全边距
+        cellWidth =
+          Math.max(
+            measureText(cellValue, '14px', 'normal', {
+              padding: '0 12px',
+              boxSizing: 'border-box'
+            }),
+            sampleWidth
+          ) + 0 // 安全边距
         // if (cellWidth > maxCellWidth) maxCellWidth = cellWidth
       } else if (col.property === 'deviceStatus') {
         // 特殊处理:字典标签文本
-        const statusText = row.deviceStatusLabel || row[col.property] || '';
+        const statusText = row.deviceStatusLabel || row[col.property] || ''
         // 模拟el-tag样式进行测量
-        cellWidth = measureText(statusText, '12px', 'normal', {
-          padding: '2px 7px',
-          border: '1px solid #dcdfe6',
-          borderRadius: '4px',
-          display: 'inline-block',
-          lineHeight: '1.5',
-          boxSizing: 'border-box'
-        }) + 0; // 20px安全边距
+        cellWidth =
+          measureText(statusText, '12px', 'normal', {
+            padding: '2px 7px',
+            border: '1px solid #dcdfe6',
+            borderRadius: '4px',
+            display: 'inline-block',
+            lineHeight: '1.5',
+            boxSizing: 'border-box'
+          }) + 0 // 20px安全边距
       } else {
         cellValue = row[col.property] || ''
-        cellWidth = measureText(cellValue, '14px', 'normal', {
-          padding: '0 12px',
-          boxSizing: 'border-box'
-        }) + 0; // 安全边距
+        cellWidth =
+          measureText(cellValue, '14px', 'normal', {
+            padding: '0 12px',
+            boxSizing: 'border-box'
+          }) + 0 // 安全边距
       }
       if (cellWidth > maxCellWidth) maxCellWidth = cellWidth
     })
 
     // 取标题和内容的最大值,并设置最小宽度
-    let minWidth = 100; // 默认最小宽度
+    let minWidth = 100 // 默认最小宽度
     if (col.property === 'createTime') {
-      minWidth = 100; // 时间列最小宽度设为180px
+      minWidth = 100 // 时间列最小宽度设为180px
     }
     // 取标题和内容的最大值
     return Math.max(headerWidth, maxCellWidth, minWidth)
@@ -345,7 +384,7 @@ const calculateColumnWidths = async () => {
 
   // 触发表格重新布局
   table.doLayout()
-};
+}
 
 const getList = async () => {
   loading.value = true
@@ -357,16 +396,16 @@ const getList = async () => {
     total.value = data.total
 
     // 只有在需要时才显示分页
-    showPagination.value = total.value > queryParams.pageSize;
+    showPagination.value = total.value > queryParams.pageSize
     // 数据加载完成后重新计算高度
-    await nextTick();
-    calculateTableHeight();
+    await nextTick()
+    calculateTableHeight()
     calculateColumnWidths()
   } finally {
     loading.value = false
     // 数据加载完成后计算列宽
-    await nextTick();
-    calculateColumnWidths();
+    await nextTick()
+    calculateColumnWidths()
   }
 }
 
@@ -375,38 +414,38 @@ const calculateTableHeight = () => {
   nextTick(() => {
     try {
       // 获取对话框实际可用空间
-      const dialogBody = document.querySelector('.el-dialog__body');
-      if (!dialogBody || !dialogTopRef.value) return;
+      const dialogBody = document.querySelector('.el-dialog__body')
+      if (!dialogBody || !dialogTopRef.value) return
 
-      const dialogBodyRect = dialogBody.getBoundingClientRect();
+      const dialogBodyRect = dialogBody.getBoundingClientRect()
 
       // 计算可用高度 = 对话框body高度 - 顶部表单高度 - 内边距
-      const dialogPadding = 20; // 上下内边距
-      const topHeight = dialogTopRef.value.offsetHeight;
-      const availableHeight = dialogBodyRect.height - topHeight - dialogPadding;
+      const dialogPadding = 20 // 上下内边距
+      const topHeight = dialogTopRef.value.offsetHeight
+      const availableHeight = dialogBodyRect.height - topHeight - dialogPadding
 
       // 保证最小高度
-      let calculatedHeight = Math.max(availableHeight, tableMinHeight.value);
+      let calculatedHeight = Math.max(availableHeight, tableMinHeight.value)
 
       // 根据记录数量计算所需高度(考虑表头和行高)
-      const headerHeight = 40; // 表头高度估算
-      const rowHeight = 48; // 行高估算(增加8px用于行间分割线)
-      const totalRowsHeight = headerHeight + (list.value.length * rowHeight);
+      const headerHeight = 40 // 表头高度估算
+      const rowHeight = 48 // 行高估算(增加8px用于行间分割线)
+      const totalRowsHeight = headerHeight + list.value.length * rowHeight
 
       // 如果所需高度小于可用高度,则按实际高度显示
       if (totalRowsHeight < availableHeight) {
-        calculatedHeight = totalRowsHeight;
+        calculatedHeight = totalRowsHeight
       }
 
       // 确保高度合理
-      effectiveTableHeight.value = Math.max(calculatedHeight, 300);
+      effectiveTableHeight.value = Math.max(calculatedHeight, 300)
     } catch (e) {
-      console.error("高度计算错误:", e);
+      console.error('高度计算错误:', e)
       // 设置回退高度
-      effectiveTableHeight.value = 500;
+      effectiveTableHeight.value = 500
     }
-  });
-};
+  })
+}
 
 const initialQueryParams = {
   pageNo: 1,
@@ -423,20 +462,20 @@ const initialQueryParams = {
 
 // 多选 切换行选中状态
 const toggleRow = (row) => {
-  const index = selectedRows.value.findIndex(item => item.id === row.id);
+  const index = selectedRows.value.findIndex((item) => item.id === row.id)
   if (index > -1) {
-    selectedRows.value.splice(index, 1); // 取消选中
+    selectedRows.value.splice(index, 1) // 取消选中
   } else {
-    selectedRows.value.push(row); // 选中
+    selectedRows.value.push(row) // 选中
   }
-};
+}
 
 // 关闭时清空选择
 const handleClose = () => {
-  tableRef.value?.clearSelection();
+  tableRef.value?.clearSelection()
   selectedRows.value = []
   emit('close')
-};
+}
 
 // 确认选择
 const handleConfirm = () => {
@@ -446,9 +485,7 @@ const handleConfirm = () => {
   }
 
   // 检查是否有设备没有保养项
-  const hasInvalidDevice = selectedRows.value.some(
-    row => row.hasSetMaintenanceBom === false
-  )
+  const hasInvalidDevice = selectedRows.value.some((row) => row.hasSetMaintenanceBom === false)
 
   if (hasInvalidDevice) {
     // 显示警告信息
@@ -460,21 +497,24 @@ const handleConfirm = () => {
     return // 不关闭弹窗
   }
 
-  emit('choose', selectedRows.value.map(row => ({
-    ...row,
-    // 确保返回必要字段
-    id: row.id,
-    deviceCode: row.deviceCode,
-    deviceName: row.deviceName,
-    deviceStatus: row.deviceStatus,
-    deptName: row.deptName,
-    assetProperty: row.assetProperty,
-    name: row.name,
-    code: row.code
-  })))
-  dialogVisible.value = false;
+  emit(
+    'choose',
+    selectedRows.value.map((row) => ({
+      ...row,
+      // 确保返回必要字段
+      id: row.id,
+      deviceCode: row.deviceCode,
+      deviceName: row.deviceName,
+      deviceStatus: row.deviceStatus,
+      deptName: row.deptName,
+      assetProperty: row.assetProperty,
+      name: row.name,
+      code: row.code
+    }))
+  )
+  dialogVisible.value = false
   handleClose()
-};
+}
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
@@ -495,26 +535,24 @@ const resetQuery = () => {
 
 // 监听列表变化动态调整高度
 watch(list, () => {
-  calculateTableHeight();
+  calculateTableHeight()
   if (dialogVisible.value) {
-    calculateColumnWidths();
+    calculateColumnWidths()
   }
-});
+})
 
 // 监听窗口大小变化
 onMounted(() => {
-  window.addEventListener('resize', calculateTableHeight);
-  window.addEventListener('resize', calculateColumnWidths);
-});
+  window.addEventListener('resize', calculateTableHeight)
+  window.addEventListener('resize', calculateColumnWidths)
+})
 
 onUnmounted(() => {
-  window.removeEventListener('resize', calculateTableHeight);
-  window.removeEventListener('resize', calculateColumnWidths);
-});
-
+  window.removeEventListener('resize', calculateTableHeight)
+  window.removeEventListener('resize', calculateColumnWidths)
+})
 </script>
 <style lang="scss" scoped>
-
 .device-select-dialog {
   display: flex;
   flex-direction: column;
@@ -522,8 +560,8 @@ onUnmounted(() => {
 
   // 增强弹窗高度利用
   ::v-deep(.el-dialog) {
-    max-height: 85vh;
     display: flex;
+    max-height: 85vh;
     flex-direction: column;
 
     .el-dialog__header {
@@ -571,26 +609,28 @@ onUnmounted(() => {
 ::v-deep(.el-table) {
   .el-table__header th {
     padding: 0 !important;
+
     .cell {
-      padding: 0 0px !important;
-      box-sizing: border-box !important;
-      font-weight: bold !important;
       display: flex;
+      height: 100%;
+      padding: 0 !important;
+      font-weight: bold !important;
+      box-sizing: border-box !important;
       justify-content: center;
       align-items: center;
-      height: 100%;
     }
   }
 
   .el-table__body td {
     padding: 0 !important;
+
     .cell {
-      padding: 0 0px !important;
-      box-sizing: border-box !important;
       display: flex;
+      height: 100%;
+      padding: 0 !important;
+      box-sizing: border-box !important;
       justify-content: center;
       align-items: center;
-      height: 100%;
     }
   }
 
@@ -599,9 +639,9 @@ onUnmounted(() => {
   .el-table__cell:nth-child(5), /* 状态列 */
   .el-table__cell:nth-child(6)  /* 时间列 */ {
     .date-cell {
-      white-space: nowrap !important;
       overflow: visible !important;
       text-overflow: clip !important;
+      white-space: nowrap !important;
       justify-content: center;
     }
   }
@@ -610,9 +650,9 @@ onUnmounted(() => {
 /* 固定表格布局 */
 .fixed-layout-table {
   ::v-deep(table) {
-    table-layout: fixed !important; /* 固定列宽 */
     width: auto !important;
     min-width: 100%;
+    table-layout: fixed !important; /* 固定列宽 */
   }
 
   ::v-deep(.el-table__header),
@@ -621,19 +661,24 @@ onUnmounted(() => {
   }
 
   ::v-deep(.el-table__cell) {
-    overflow: visible !important;   /* 禁用裁剪 */
+    overflow: visible !important; /* 禁用裁剪 */
     text-overflow: unset !important; /* 移除省略号 */
-    white-space: nowrap !important;  /* 禁止换行 */
+    white-space: nowrap !important; /* 禁止换行 */
 
-    &:nth-child(4) { /* 部门 */
+    &:nth-child(4) {
+      /* 部门 */
       min-width: v-bind('flexColumnMinWidths.deptName + "px"');
       text-align: center;
     }
-    &:nth-child(5) { /* 状态 */
+
+    &:nth-child(5) {
+      /* 状态 */
       min-width: v-bind('flexColumnMinWidths.deviceStatus + "px"');
       text-align: center;
     }
-    &:nth-child(6) { /* 创建时间 */
+
+    &:nth-child(6) {
+      /* 创建时间 */
       min-width: v-bind('(flexColumnMinWidths.createTime) + "px"');
       overflow: visible !important;
       text-align: center;
@@ -651,14 +696,15 @@ onUnmounted(() => {
 }
 
 .table-container {
-  flex: 1;
   display: flex;
-  flex-direction: column;
-  min-height: 0;
   max-height: 100%;
+  min-height: 0;
+  flex: 1;
+  flex-direction: column;
 
   .table-wrapper {
     overflow: auto !important;
+
     .el-table {
       // 表格自带的滚动机制
       ::v-deep(.el-table__body-wrapper) {
@@ -669,40 +715,61 @@ onUnmounted(() => {
 }
 
 .no-maintenance {
-  color: red; /* 无保养项文本为红色 */
   font-weight: bold;
+  color: red; /* 无保养项文本为红色 */
 }
 
 .has-maintenance {
-  color: #67c23a; /* 有保养项文本为淡绿色 */
   font-weight: bold;
+  color: #67c23a; /* 有保养项文本为淡绿色 */
 }
 
 .table-wrapper {
   width: 100%;
-  overflow-y: hidden;
-  overflow-x: auto !important;
+  overflow: auto hidden !important;
 }
 
 .no-label-radio .el-radio__label {
   display: none;
 }
+
 .no-label-radio .el-radio__inner {
   margin-right: 0;
 }
 
+.fixed-layout-table {
+  ::v-deep(.device-name-column) {
+    overflow: hidden !important;
+    text-overflow: ellipsis !important;
+  }
+
+  ::v-deep(.device-name-column .cell) {
+    display: block !important;
+    overflow: hidden !important;
+    text-overflow: ellipsis !important;
+    white-space: nowrap !important;
+  }
+}
+
+.device-name-cell {
+  width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
 /* 自定义淡绿色按钮 */
 :deep(.custom-green-button) {
+  color: #67c23a;
   background-color: #e1f3d8;
   border-color: #e1f3d8;
-  color: #67c23a;
 }
 
 /* 悬停效果 */
 :deep(.custom-green-button:hover) {
+  color: #5daf34;
   background-color: #d1e8c0;
   border-color: #d1e8c0;
-  color: #5daf34;
 }
 
 /* 点击效果 */
@@ -713,10 +780,10 @@ onUnmounted(() => {
 
 // 分页样式优化 - 弹性位置
 .pagination-container {
-  margin-top: auto; // 将分页推到底部
+  z-index: 10;
   padding: 15px 0 5px;
+  margin-top: auto; // 将分页推到底部
   background: white; // 防止内容重叠
-  z-index: 10;
 }
 
 /* 使感叹号图标与标题对齐 */
@@ -726,8 +793,8 @@ onUnmounted(() => {
   justify-content: center;
 
   .el-tooltip {
-    margin-left: 3px;
     display: inline-flex;
+    margin-left: 3px;
     align-items: center;
 
     .el-icon {
@@ -752,5 +819,4 @@ onUnmounted(() => {
   font-size: 18px;
   color: #e6a23c; /* 使感叹号图标有明显的颜色 */
 }
-
 </style>