Browse Source

系统对接优化

learshaw 3 months ago
parent
commit
034bce1c54

+ 112 - 31
ems-ui-cloud/src/views/adapter/dljk/index.vue

@@ -162,7 +162,7 @@
                 class="protection-device-table">
                 <el-table-column type="expand">
                   <template slot-scope="props">
-                    <div class="device-detail">
+                    <div class="device-detail" @click.stop>
                       <el-tabs v-model="props.row.detailTab">
                         <!-- 设备属性(合并基础属性和电力属性) -->
                         <el-tab-pane label="设备属性" name="deviceAttrs">
@@ -307,7 +307,7 @@
                             class="sub-device-table">
                             <el-table-column type="expand">
                               <template slot-scope="subProps">
-                                <div class="sub-device-detail">
+                                <div class="sub-device-detail" @click.stop>
                                   <el-tabs v-model="subProps.row.detailTab || 'deviceAttrs'">
                                     <!-- 设备属性(合并测点基础属性和电力属性) -->
                                     <el-tab-pane label="设备属性" name="deviceAttrs">
@@ -508,7 +508,7 @@
                                   trigger="click"
                                   @command="handleSubDeviceCommand"
                                   @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
-                                  <el-button type="text" size="mini">
+                                  <el-button type="text" size="mini" @click.stop>
                                     操作<i class="el-icon-arrow-down el-icon--right"></i>
                                   </el-button>
                                   <el-dropdown-menu slot="dropdown">
@@ -583,7 +583,7 @@
                       trigger="click"
                       @command="handleDeviceCommand"
                       @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
-                      <el-button type="text" size="mini">
+                      <el-button type="text" size="mini" @click.stop>
                         操作<i class="el-icon-arrow-down el-icon--right"></i>
                       </el-button>
                       <el-dropdown-menu slot="dropdown">
@@ -744,8 +744,8 @@
               class="meter-device-table">
               <el-table-column type="expand">
                 <template slot-scope="props">
-                  <div class="device-detail">
-                    <el-tabs v-model="props.row.detailTab || 'deviceAttrs'">
+                  <div class="device-detail" @click.stop>
+                    <el-tabs v-model="props.row.detailTab">
                       <!-- 设备属性(合并基础属性和电力属性) -->
                       <el-tab-pane label="设备属性" name="deviceAttrs">
                         <div class="merged-attrs-container">
@@ -950,7 +950,7 @@
                                       </div>
                                       <el-tooltip :content="getUpdateTimeTooltip(props.row.deviceCode, 'P')" placement="top">
                                         <div class="param-value">
-                                          <span class="value">{{ getDeviceAttr(props.row.deviceCode, 'P') || '0.0' }}</span>
+                                          <span class="value">{{ getDeviceAttr(props.row.deviceCode, 'power') || '0.0' }}</span>
                                           <span class="unit">kW</span>
                                           <span class="update-indicator" :class="getUpdateStatusClass(props.row.deviceCode, 'P')"></span>
                                         </div>
@@ -1180,8 +1180,8 @@
                           class="sub-device-table">
                           <el-table-column type="expand">
                             <template slot-scope="subProps">
-                              <div class="sub-device-detail">
-                                <el-tabs v-model="subProps.row.detailTab || 'deviceAttrs'">
+                              <div class="sub-device-detail" @click.stop>
+                                <el-tabs v-model="subProps.row.detailTab">
                                   <!-- 设备属性(合并测点基础属性和电力属性) -->
                                   <el-tab-pane label="设备属性" name="deviceAttrs">
                                     <div class="merged-attrs-container">
@@ -1440,7 +1440,7 @@
                                                   </div>
                                                   <el-tooltip :content="getUpdateTimeTooltip(subProps.row.deviceCode, 'P')" placement="top">
                                                     <div class="param-value">
-                                                      <span class="value">{{ getDeviceAttr(subProps.row.deviceCode, 'P') || '0.0' }}</span>
+                                                      <span class="value">{{ getDeviceAttr(subProps.row.deviceCode, 'power') || '0.0' }}</span>
                                                       <span class="unit">kW</span>
                                                       <span class="update-indicator" :class="getUpdateStatusClass(subProps.row.deviceCode, 'P')"></span>
                                                     </div>
@@ -1781,7 +1781,7 @@
                                 trigger="click"
                                 @command="handleSubDeviceCommand"
                                 @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
-                                <el-button type="text" size="mini">
+                                <el-button type="text" size="mini" @click.stop>
                                   操作<i class="el-icon-arrow-down el-icon--right"></i>
                                 </el-button>
                                 <el-dropdown-menu slot="dropdown">
@@ -1917,7 +1917,7 @@
                     trigger="click"
                     @command="handleDeviceCommand"
                     @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
-                    <el-button type="text" size="mini">
+                    <el-button type="text" size="mini" @click.stop>
                       操作<i class="el-icon-arrow-down el-icon--right"></i>
                     </el-button>
                     <el-dropdown-menu slot="dropdown">
@@ -2709,31 +2709,27 @@ export default {
       let totalReactivePower = 0
       let totalApparentPower = 0
 
-      // 遍历每个智能电表主节点
       this.smartMeterDeviceList.forEach(device => {
-        // 获取该主节点下的所有子节点
         const subDevices = this.getSubDevices(device.deviceCode)
 
         if (subDevices && subDevices.length > 0) {
-          // 如果有子节点,累加子节点的功率
           subDevices.forEach(subDevice => {
-            const Pt = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'Pt')) || 0
-            const Qt = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'Qt')) || 0
-            const St = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'St')) || 0
+            const power = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'power')) || 0
+            const Q = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'Q')) || 0
+            const S = parseFloat(this.getDeviceAttr(subDevice.deviceCode, 'S')) || 0
 
-            totalActivePower += Pt
-            totalReactivePower += Qt
-            totalApparentPower += St
+            totalActivePower += power
+            totalReactivePower += Q
+            totalApparentPower += S
           })
         } else {
-          // 如果没有子节点,使用主节点的功率(兼容没有子节点的情况)
-          const Pt = parseFloat(this.getDeviceAttr(device.deviceCode, 'Pt')) || 0
-          const Qt = parseFloat(this.getDeviceAttr(device.deviceCode, 'Qt')) || 0
-          const St = parseFloat(this.getDeviceAttr(device.deviceCode, 'St')) || 0
-
-          totalActivePower += Pt
-          totalReactivePower += Qt
-          totalApparentPower += St
+          const power = parseFloat(this.getDeviceAttr(device.deviceCode, 'power')) || 0
+          const Q = parseFloat(this.getDeviceAttr(device.deviceCode, 'Q')) || 0
+          const S = parseFloat(this.getDeviceAttr(device.deviceCode, 'S')) || 0
+
+          totalActivePower += power
+          totalReactivePower += Q
+          totalApparentPower += S
         }
       })
 
@@ -3024,15 +3020,42 @@ export default {
     // ==================== 表格行点击 ====================
 
     // 保护装置设备行点击
-    handleProtectionDeviceClick(row) {
+    handleProtectionDeviceClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
       this.$refs.protectionTable?.toggleRowExpansion(row)
     },
 
     // 智能电表设备行点击
-    handleMeterDeviceClick(row) {
+    handleMeterDeviceClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
       this.$refs.meterTable?.toggleRowExpansion(row)
     },
 
+    handleSubDeviceRowClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 子表格没有ref,这里不做额外处理,由 @click.stop 阻止冒泡
+    },
+
+    // 处理智能电表子设备行点击 ★★★
+    handleMeterSubDeviceRowClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 子表格没有ref,这里不做额外处理,由 @click.stop 阻止冒泡
+    },
+
     // ==================== 日志查询 ====================
 
     // 标签页切换
@@ -3936,4 +3959,62 @@ pre {
   white-space: pre-line;
   max-width: 200px;
 }
+
+.device-detail {
+  padding: 20px;
+  background: #f9fafc;
+  border-radius: 4px;
+
+  /* Tab样式优化 */
+  ::v-deep .el-tabs__header {
+    margin-bottom: 15px;
+    background: #fff;
+    padding: 0 15px;
+    border-radius: 4px;
+    border: 1px solid #e4e7ed;
+  }
+
+  ::v-deep .el-tabs__nav-wrap::after {
+    height: 1px;
+    background-color: #e4e7ed;
+  }
+
+  ::v-deep .el-tabs__item {
+    height: 40px;
+    line-height: 40px;
+    font-size: 14px;
+
+    &.is-active {
+      color: #409EFF;
+      font-weight: 600;
+    }
+
+    &:hover {
+      color: #409EFF;
+    }
+  }
+
+  ::v-deep .el-tabs__active-bar {
+    background-color: #409EFF;
+  }
+
+  ::v-deep .el-tabs__content {
+    padding: 0;
+  }
+
+  /* 描述列表样式 */
+  ::v-deep .el-descriptions {
+    .el-descriptions__label {
+      background: #fafafa;
+      color: #606266;
+      font-weight: 500;
+      width: 120px;
+    }
+
+    .el-descriptions__content {
+      background: #fff;
+      color: #303133;
+    }
+  }
+}
 </style>

+ 85 - 15
ems-ui-cloud/src/views/adapter/nhjc/index.vue

@@ -214,7 +214,8 @@
               ref="deviceTable">
               <el-table-column type="expand">
                 <template slot-scope="props">
-                  <div class="device-detail">
+                  <!-- ★★★ 关键修复:添加 @click.stop 阻止事件冒泡 ★★★ -->
+                  <div class="device-detail" @click.stop>
                     <el-tabs v-model="props.row.detailTab">
                       <el-tab-pane label="设备属性" name="attrs">
                         <el-descriptions :column="2" border size="small">
@@ -275,7 +276,7 @@
                     trigger="click"
                     @command="handleDeviceCommand"
                     @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
-                    <el-button type="text" size="mini">
+                    <el-button type="text" size="mini" @click.stop>
                       操作<i class="el-icon-arrow-down el-icon--right"></i>
                     </el-button>
                     <el-dropdown-menu slot="dropdown">
@@ -338,10 +339,13 @@
               border
               stripe
               v-loading="baDeviceLoading"
+              @row-click="handleBaDeviceRowClick"
+              ref="baDeviceTable"
               style="margin-top: 15px;">
               <el-table-column type="expand" width="50">
                 <template slot-scope="props">
-                  <div class="ba-device-detail">
+                  <!-- ★★★ 关键修复:添加 @click.stop 阻止事件冒泡 ★★★ -->
+                  <div class="device-detail" @click.stop>
                     <el-tabs v-model="props.row.detailTab">
                       <!-- 基础属性 -->
                       <el-tab-pane label="基础属性" name="base">
@@ -410,7 +414,7 @@
                           :key="option.value"
                           size="mini"
                           type="primary"
-                          @click="executeBaDeviceAbility(scope.row, ability, option.value)"
+                          @click.stop="executeBaDeviceAbility(scope.row, ability, option.value)"
                           :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey, option.value)">
                           {{ option.key }}
                         </el-button>
@@ -421,7 +425,7 @@
                         :key="ability.abilityKey"
                         size="mini"
                         type="primary"
-                        @click="handleBaDeviceAbilityClick(scope.row, ability)"
+                        @click.stop="handleBaDeviceAbilityClick(scope.row, ability)"
                         :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey)"
                         style="margin: 2px;">
                         {{ ability.abilityName }}
@@ -432,7 +436,7 @@
                         :key="ability.abilityKey"
                         size="mini"
                         type="primary"
-                        @click="executeBaDeviceAbility(scope.row, ability, null)"
+                        @click.stop="executeBaDeviceAbility(scope.row, ability, null)"
                         :loading="isBaAbilityExecuting(scope.row.deviceCode, ability.abilityKey)"
                         style="margin: 2px;">
                         {{ ability.abilityName }}
@@ -1570,11 +1574,26 @@ export default {
       }
     },
 
-    // 处理设备行点击
-    handleDeviceClick(row) {
+    // ★★★ 修复:处理设备行点击 - 只在非展开区域时才切换展开状态 ★★★
+    handleDeviceClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
       this.$refs.deviceTable?.toggleRowExpansion(row)
     },
 
+    // ★★★ 新增:处理楼控设备行点击 ★★★
+    handleBaDeviceRowClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
+      this.$refs.baDeviceTable?.toggleRowExpansion(row)
+    },
+
     // ========== 楼控设备相关方法 ==========
 
     // 处理楼控设备类型切换
@@ -1610,7 +1629,7 @@ export default {
 
         this.baDeviceList = deviceData.map(device => ({
           ...device,
-          detailTab: 'state'
+          detailTab: 'state'  // 默认显示状态属性tab
         }))
 
         // 3. 批量加载设备属性值
@@ -1991,13 +2010,69 @@ export default {
     }
   }
 
+  /* ★★★ 统一的展开行详情样式 ★★★ */
   .device-detail {
     padding: 20px;
-    background: #f5f7fa;
+    background: #f9fafc;
+    border-radius: 4px;
+
+    /* Tab样式优化 */
+    ::v-deep .el-tabs__header {
+      margin-bottom: 15px;
+      background: #fff;
+      padding: 0 15px;
+      border-radius: 4px;
+      border: 1px solid #e4e7ed;
+    }
+
+    ::v-deep .el-tabs__nav-wrap::after {
+      height: 1px;
+      background-color: #e4e7ed;
+    }
+
+    ::v-deep .el-tabs__item {
+      height: 40px;
+      line-height: 40px;
+      font-size: 14px;
+
+      &.is-active {
+        color: #409EFF;
+        font-weight: 600;
+      }
+
+      &:hover {
+        color: #409EFF;
+      }
+    }
+
+    ::v-deep .el-tabs__active-bar {
+      background-color: #409EFF;
+    }
+
+    ::v-deep .el-tabs__content {
+      padding: 0;
+    }
 
     h5 {
       margin: 15px 0 10px 0;
       color: #303133;
+      font-size: 14px;
+      font-weight: 600;
+    }
+
+    /* 描述列表样式 */
+    ::v-deep .el-descriptions {
+      .el-descriptions__label {
+        background: #fafafa;
+        color: #606266;
+        font-weight: 500;
+        width: 120px;
+      }
+
+      .el-descriptions__content {
+        background: #fff;
+        color: #303133;
+      }
     }
   }
 
@@ -2007,11 +2082,6 @@ export default {
     margin-bottom: 15px;
   }
 
-  .ba-device-detail {
-    padding: 20px;
-    background: #f5f7fa;
-  }
-
   .log-filter {
     margin-bottom: 20px;
     padding: 15px;

+ 139 - 13
ems-ui-cloud/src/views/adapter/pv/index.vue

@@ -97,7 +97,7 @@
     <el-card class="detail-card">
       <el-tabs v-model="activeTab" @tab-click="handleTabClick">
         <!-- 系统属性标签页 - 包含采集器和实时监控 -->
-        <el-tab-pane label="系统属性" name="attributes">
+        <el-tab-pane label="系统总览" name="overview">
           <div class="tab-content">
             <!-- 实时监控面板 -->
             <div class="monitor-panel">
@@ -190,8 +190,8 @@
                 ref="collectorTable">
                 <el-table-column type="expand">
                   <template slot-scope="props">
-                    <div class="device-detail">
-                      <el-tabs v-model="props.row.detailTab || 'base'">
+                    <div class="device-detail" @click.stop>
+                      <el-tabs v-model="props.row.detailTab">
                         <!-- 基础属性标签页 -->
                         <el-tab-pane label="基础属性" name="base">
                           <el-descriptions :column="2" border size="small" class="collector-descriptions">
@@ -311,13 +311,68 @@
                     </el-tag>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" width="80" align="center">
+
+              </el-table>
+            </div>
+          </div>
+        </el-tab-pane>
+
+        <el-tab-pane label="系统属性" name="attributes">
+          <div class="tab-content">
+            <!-- 协议信息 -->
+            <div class="attr-section" v-if="baseAttrs.length > 0">
+              <h4 class="section-title">
+                <i class="el-icon-connection"></i>
+                协议信息
+              </h4>
+              <el-table :data="baseAttrs" border stripe>
+                <el-table-column prop="attrName" label="属性名称" width="200"></el-table-column>
+                <el-table-column label="属性值">
                   <template slot-scope="scope">
-                    <el-button type="text" size="mini" @click.stop="handleCollectorClick(scope.row)">
-                      详情
-                    </el-button>
+                    <!-- 服务地址:显示为链接样式 -->
+                    <span v-if="scope.row.attrKey === 'url'" class="url-text">
+              {{ scope.row.attrValue }}
+            </span>
+                    <!-- token:按密码字段处理 -->
+                    <span v-else-if="scope.row.attrKey === 'token'" style="display: inline-flex; align-items: center;">
+              <span>{{ tokenVisible ? scope.row.attrValue : '••••••••••••••••••••••••••••••••' }}</span>
+              <i
+                class="el-icon-view"
+                @click.stop="tokenVisible = !tokenVisible"
+                :title="tokenVisible ? '隐藏令牌' : '显示令牌'"
+                :style="{
+                  marginLeft: '10px',
+                  cursor: 'pointer',
+                  fontSize: '16px',
+                  color: tokenVisible ? '#409EFF' : '#C0C4CC'
+                }"
+              ></i>
+            </span>
+                    <!-- 其他字段:正常显示 -->
+                    <span v-else>{{ scope.row.attrValue || '-' }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+
+            <!-- 状态信息 -->
+            <div class="attr-section" v-if="stateAttrs.length > 0">
+              <h4 class="section-title">
+                <i class="el-icon-info"></i>
+                状态信息
+              </h4>
+              <el-table :data="stateAttrs" border stripe>
+                <el-table-column prop="attrName" label="属性名称" width="200"></el-table-column>
+                <el-table-column label="属性值">
+                  <template slot-scope="scope">
+                    <el-tag v-if="scope.row.attrKey === 'interfaceStatus'"
+                            :type="scope.row.attrValue === '1' ? 'success' : 'danger'">
+                      {{ scope.row.attrValue === '1' ? '正常' : '异常' }}
+                    </el-tag>
+                    <span v-else>{{ scope.row.attrValueName || scope.row.attrValue || '-' }}</span>
                   </template>
                 </el-table-column>
+                <el-table-column prop="updateTime" label="更新时间" width="180"></el-table-column>
               </el-table>
             </div>
           </div>
@@ -415,8 +470,8 @@
               ref="inverterTable">
               <el-table-column type="expand">
                 <template slot-scope="props">
-                  <div class="device-detail">
-                    <el-tabs v-model="props.row.detailTab || 'base'">
+                  <div class="device-detail" @click.stop>
+                    <el-tabs v-model="props.row.detailTab">
                       <!-- 基础属性标签页 -->
                       <el-tab-pane label="基础属性" name="base">
                         <el-descriptions :column="2" border size="small" class="inverter-descriptions">
@@ -745,7 +800,7 @@
               <el-table-column label="操作" width="100" align="center">
                 <template slot-scope="scope">
                   <el-dropdown trigger="click" @command="handleInverterAbilityCommand">
-                    <el-button type="text" size="mini" @click="loadInverterAbilities(scope.row)">
+                    <el-button type="text" size="mini" @click.stop="loadInverterAbilities(scope.row)">
                       操作<i class="el-icon-arrow-down el-icon--right"></i>
                     </el-button>
                     <el-dropdown-menu slot="dropdown">
@@ -1063,7 +1118,7 @@ export default {
       // 系统状态
       systemStatus: '1',
       // 当前标签页
-      activeTab: 'attributes',
+      activeTab: 'overview',
       // 系统能力
       systemAbilities: [],
       abilityLoading: false,
@@ -1080,6 +1135,10 @@ export default {
       inverterModel: null,
       inverterAbilities: {},
       currentInverterAbilities: [],
+      baseAttrs: [],
+      stateAttrs: [],
+      // token可见状态(新增)
+      tokenVisible: false,
       // 设备统计
       deviceStats: {
         total: 0,
@@ -1268,6 +1327,11 @@ export default {
         const attrRes = await getObjAttr(3, this.systemCode)
         const attrData = attrRes.data
 
+        // ===== 新增:保存基础属性和状态属性 =====
+        this.baseAttrs = attrData.Base || []
+        this.stateAttrs = attrData.State || []
+        // ========================================
+
         // 设置系统状态
         if (attrData.State) {
           const statusAttr = attrData.State.find(attr => attr.attrKey === 'interfaceStatus')
@@ -1554,12 +1618,22 @@ export default {
     },
 
     // 处理采集器行点击
-    handleCollectorClick(row) {
+    handleCollectorClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
       this.$refs.collectorTable?.toggleRowExpansion(row)
     },
 
     // 处理逆变器行点击
-    handleInverterClick(row) {
+    handleInverterClick(row, column, event) {
+      // 如果点击的是展开列本身(箭头),让默认行为处理
+      if (column && column.type === 'expand') {
+        return
+      }
+      // 手动切换展开状态
       this.$refs.inverterTable?.toggleRowExpansion(row)
     },
 
@@ -2164,6 +2238,15 @@ export default {
     min-height: 400px;
   }
 
+  .attr-section {
+    margin-bottom: 30px;
+
+    .url-text {
+      color: #409EFF;
+      font-family: monospace;
+    }
+  }
+
   .section-title {
     margin: 20px 0 15px 0;
     color: #303133;
@@ -2552,4 +2635,47 @@ export default {
 .dialog-footer {
   text-align: right;
 }
+
+.device-detail {
+  padding: 20px;
+  background: #f5f7fa;
+  border-radius: 4px;
+
+  // ✨ 添加这些Tab样式优化
+  ::v-deep .el-tabs__header {
+    margin-bottom: 15px;
+    background: #fff;
+    padding: 0 15px;
+    border-radius: 4px;
+    border: 1px solid #e4e7ed;
+  }
+
+  ::v-deep .el-tabs__nav-wrap::after {
+    height: 1px;
+    background-color: #e4e7ed;
+  }
+
+  ::v-deep .el-tabs__item {
+    height: 40px;
+    line-height: 40px;
+    font-size: 14px;
+
+    &.is-active {
+      color: #409EFF;
+      font-weight: 600;
+    }
+
+    &:hover {
+      color: #409EFF;
+    }
+  }
+
+  ::v-deep .el-tabs__active-bar {
+    background-color: #409EFF;
+  }
+
+  ::v-deep .el-tabs__content {
+    padding: 0;
+  }
+}
 </style>

+ 95 - 19
ems-ui-cloud/src/views/adapter/zm/index.vue

@@ -198,8 +198,8 @@
                 ref="concentratorTable">
                 <el-table-column type="expand">
                   <template slot-scope="props">
-                    <div class="device-detail">
-                      <el-tabs v-model="props.row.detailTab || 'base'">
+                    <div class="device-detail" @click.stop>
+                      <el-tabs v-model="props.row.detailTab">
                         <!-- 基础属性标签页 -->
                         <el-tab-pane label="基础属性" name="base">
                           <el-descriptions :column="2" border size="small" class="concentrator-descriptions">
@@ -390,9 +390,20 @@
                     <span v-if="scope.row.attrKey === 'url'" class="url-text">
                       {{ scope.row.attrValue }}
                     </span>
-                    <span v-else-if="scope.row.attrKey === 'password'">
-                      ••••••••
-                    </span>
+                    <span v-else-if="scope.row.attrKey === 'password'" style="display: inline-flex; align-items: center;">
+                      <span>{{ passwordVisible ? scope.row.attrValue : '••••••••' }}</span>
+                      <i
+                        class="el-icon-view"
+                        @click.stop="passwordVisible = !passwordVisible"
+                        :title="passwordVisible ? '隐藏密码' : '显示密码'"
+                        :style="{
+                            marginLeft: '10px',
+                            cursor: 'pointer',
+                            fontSize: '16px',
+                            color: passwordVisible ? '#409EFF' : '#C0C4CC'
+                            }"
+                        ></i>
+                      </span>
                     <span v-else>{{ scope.row.attrValue || '-' }}</span>
                   </template>
                 </el-table-column>
@@ -550,7 +561,7 @@
               <!-- 灯杆展开:显示灯组列表 -->
               <el-table-column type="expand">
                 <template slot-scope="props">
-                  <div class="lamp-pole-detail">
+                  <div class="lamp-pole-detail" @click.stop>
                     <!-- 灯组列表表格 -->
                     <el-table
                       :data="getLampGroupList(props.row.deviceCode)"
@@ -558,14 +569,14 @@
                       stripe
                       size="small"
                       row-key="deviceCode"
-                      @row-click="(row) => handleLampGroupClick(row, props.$index)"
+                      @row-click="(row, column, event) => handleLampGroupClick(row, column, event, props.$index)"
                       :ref="`lampGroupTable_${props.$index}`"
                       class="lamp-group-table">
                       <!-- 灯组展开:显示灯组属性和能力 -->
                       <el-table-column type="expand" width="40">
                         <template slot-scope="scope">
-                          <div class="lamp-group-detail">
-                            <el-tabs v-model="scope.row.detailTab || 'attrs'">
+                          <div class="lamp-group-detail" @click.stop>
+                            <el-tabs v-model="scope.row.detailTab">
                               <!-- 灯组属性标签页 -->
                               <el-tab-pane label="灯组属性" name="attrs">
                                 <!-- 状态属性 -->
@@ -750,7 +761,7 @@
                       <el-table-column label="操作" width="100" align="center">
                         <template slot-scope="scope">
                           <el-dropdown trigger="click" @command="handleLampGroupAbilityCommand">
-                            <el-button type="text" size="mini" @click="loadLampGroupAbilities(scope.row)">
+                            <el-button type="text" size="mini" @click.stop="loadLampGroupAbilities(scope.row)">
                               操作<i class="el-icon-arrow-down el-icon--right"></i>
                             </el-button>
                             <el-dropdown-menu slot="dropdown">
@@ -806,7 +817,7 @@
               <el-table-column label="操作" width="100" align="center">
                 <template slot-scope="scope">
                   <el-dropdown trigger="click" @command="handleLampPoleAbilityCommand">
-                    <el-button type="text" size="mini" @click="loadLampPoleAbilities(scope.row)">
+                    <el-button type="text" size="mini" @click.stop="loadLampPoleAbilities(scope.row)">
                       操作<i class="el-icon-arrow-down el-icon--right"></i>
                     </el-button>
                     <el-dropdown-menu slot="dropdown">
@@ -1167,15 +1178,21 @@ export default {
       lampPoleList: [],
       lampPoleLoading: false,
       lampPoleAttrs: {},
-      lampPoleModel: null, // 灯杆物模型
-      lampPoleAbilities: {}, // 灯杆能力列表(按deviceCode存储)
-      currentLampPoleAbilities: [], // 当前操作的灯杆能力列表
+      // 密码可见状态
+      passwordVisible: false,
+      // 灯杆物模型
+      lampPoleModel: null,
+      // 灯杆能力列表
+      lampPoleAbilities: {},
+      // 当前操作的灯杆能力列表
+      currentLampPoleAbilities: [],
       // 灯组设备列表(所有灯组)
       lampGroupList: [],
       lampGroupAttrs: {},
       lampGroupModel: null,
       lampGroupAbilities: {},
-      currentLampGroupAbilities: [], // 当前操作的灯组能力列表
+      // 当前操作的灯组能力列表
+      currentLampGroupAbilities: [],
       // 灯组统计
       totalLampCount: 0,
       onlineLampCount: 0,
@@ -2028,7 +2045,8 @@ export default {
       const lampGroups = this.getLampGroupCodesFromPole(poleCode)
       return lampGroups.map(item => ({
         deviceCode: item.deviceCode,
-        deviceModel: item.modelCode
+        deviceModel: item.modelCode,
+        detailTab: 'attrs'
       }))
     },
 
@@ -2122,12 +2140,18 @@ export default {
     },
 
     // 处理灯杆行点击
-    handleLampPoleClick(row) {
+    handleLampPoleClick(row, column, event) {
+      if (column && column.type === 'expand') {
+        return
+      }
       this.$refs.lampPoleTable?.toggleRowExpansion(row)
     },
 
     // 处理灯组行点击
-    handleLampGroupClick(row, poleIndex) {
+    handleLampGroupClick(row, column, event, poleIndex) {
+      if (column && column.type === 'expand') {
+        return
+      }
       const tableRef = this.$refs[`lampGroupTable_${poleIndex}`]
       if (tableRef && tableRef[0]) {
         tableRef[0].toggleRowExpansion(row)
@@ -2378,7 +2402,10 @@ export default {
     },
 
     // 处理集中器行点击
-    handleConcentratorClick(row) {
+    handleConcentratorClick(row, column, event) {
+      if (column && column.type === 'expand') {
+        return
+      }
       this.$refs.concentratorTable?.toggleRowExpansion(row)
     },
 
@@ -3270,4 +3297,53 @@ export default {
 .dialog-footer {
   text-align: right;
 }
+
+.device-detail,
+.lamp-pole-detail,
+.lamp-group-detail {
+  padding: 20px;
+  background: #f9fafc;
+  border-radius: 4px;
+
+  ::v-deep .el-tabs__header {
+    background: #fff;
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+    margin-bottom: 15px;
+    padding: 0 10px;
+  }
+
+  ::v-deep .el-tabs__item {
+    height: 40px;
+    line-height: 40px;
+    font-size: 14px;
+
+    &.is-active {
+      color: #409EFF;
+      font-weight: bold;
+    }
+  }
+
+  ::v-deep .el-tabs__nav-wrap::after {
+    display: none;
+  }
+}
+
+// 密码字段样式
+.password-field {
+  display: inline-flex;
+  align-items: center;
+  gap: 8px;
+
+  .password-toggle-icon {
+    cursor: pointer;
+    color: #909399;
+    font-size: 16px;
+    transition: color 0.3s;
+
+    &:hover {
+      color: #409EFF;
+    }
+  }
+}
 </style>