Skip to content

Navigation Menu

Sign in
Sign up

[Style] 自适应电池状态监控系统 / Adaptive Battery Monitoring System #16

fenglibo51 started this conversation in Show and tell
Discussion options

[html-card-pro] 自适应电池状态监控系统 / Adaptive Battery Monitoring System

这是一个基于 html-card-pro 打造的 Apple 风格自适应电池状态监控模板。

传统电池卡片通常会将所有设备电量全部混合显示,导致信息过于拥挤。

因此这个模板会自动根据设备当前电量状态进行分层:

  • 低电量预警
  • 中电量提示
  • 电量充足

让用户能够根据自己的需求,自由选择更关注哪一种电量状态,而不是让所有设备同时挤在一个列表中。


This is an Apple-inspired adaptive battery monitoring template built with html-card-pro.

Traditional battery cards usually place every device into a single crowded list.

This template instead automatically separates devices into different battery health tiers:

  • Critical Battery
  • Warning Battery
  • Healthy Battery

This allows users to focus on the battery states they actually care about, instead of mixing all devices into one overwhelming panel.


Preview / 预览

Picsew_20260528222316 红黄卡 绿卡

🔴 Critical Battery / 低电量预警

Picsew_20260528222211

🟠 Warning Battery / 中电量提示

Picsew_20260528222240

🟢 Healthy Battery / 电量充足

Picsew_20260528222248
🇨🇳 中文

✨ 功能特性

  • 自动电量状态分类
  • 自适应设备分组
  • 自动过滤无效实体
  • Friendly Name 自动清洗
  • 动态能源流动画
  • 可折叠设备列表
  • Apple 风格极简 UI
  • Home Assistant 优化
  • 移动端适配
  • 自动过滤 unavailable / unknown 实体
  • 自动筛除 power / voltage / energy 等非电池实体

🔋 电量状态分类

🔴 低电量预警(0~20%)

用于展示需要优先处理的低电量设备。

特点:

  • 红色危险视觉状态
  • 动态能量流下落动画
  • 自动高亮低电量设备
  • 支持折叠大量设备

🟠 中电量提示(20~50%)

用于展示需要关注但暂时无需更换电池的设备。

特点:

  • 橙色提醒状态
  • 能量流上升动画
  • 更柔和的信息提示风格
  • 适合作为日常巡检列表

🟢 电量充足(50~100%)

用于展示当前状态健康的设备。

特点:

  • 绿色安全状态
  • 呼吸式稳定动画
  • 更轻量的信息展示
  • 用于快速确认整体健康状态

🧠 自动文本清洗

模板会自动清理:

  • 电池
  • 电量
  • 低电量
  • Battery Level
  • battery level
  • 干电池
  • 充电

避免设备名称重复污染 UI。

📦 环境要求

  • Home Assistant
  • html-card-pro
  • Battery Sensor Entities

🚀 使用方法

第一步

安装 html-card-pro。

第二步

创建 HTML Card。

第三步

直接粘贴对应版本代码。

第四步

根据自己的实体名称进行调整。

💡 使用建议

  • 红色卡片建议置顶显示
  • 橙色卡片适合日常巡检
  • 绿色卡片更适合作为统计展示
  • 如果设备很多,建议使用折叠模式
  • 平板 Dashboard 效果最佳

🇺🇸 English

✨ Features

  • Automatic battery health classification
  • Adaptive device grouping
  • Automatic invalid entity filtering
  • Friendly name cleanup engine
  • Dynamic animated energy indicators
  • Expandable device drawer
  • Apple-inspired minimal UI
  • Home Assistant optimized
  • Mobile-friendly layout
  • Automatic unavailable / unknown filtering
  • Automatic exclusion of power / voltage / energy entities

🔋 Battery Health Tiers

🔴 Critical Battery (0~20%)

Designed for devices that require immediate attention.

Features:

  • Red critical warning style
  • Dynamic downward energy flow animation
  • Automatic low battery highlighting
  • Expandable large device list

🟠 Warning Battery (20~50%)

Designed for devices that should be monitored but do not yet require battery replacement.

Features:

  • Orange warning state
  • Upward energy flow animation
  • Softer visual feedback
  • Ideal for daily monitoring

🟢 Healthy Battery (50~100%)

Designed for devices with healthy battery levels.

Features:

  • Green healthy status
  • Breathing-style stable animation
  • Lightweight visual presentation
  • Perfect for overall health overview

🧠 Automatic Name Cleanup

The template automatically removes:

  • 电池
  • 电量
  • Battery Level
  • battery level
  • 低电量
  • 干电池
  • 充电

to keep the UI clean and avoid duplicated wording.

📦 Requirements

  • Home Assistant
  • html-card-pro
  • Battery Sensor Entities

🚀 Installation

Step 1

Install html-card-pro.

Step 2

Create a new HTML Card.

Step 3

Paste the corresponding card template.

Step 4

Customize the entity names according to your setup.

💡 Tips

  • Place the critical battery card at the top
  • The warning card is ideal for daily monitoring
  • The healthy card works well as a status overview
  • Use expandable mode if you have many devices
  • Perfect for tablet dashboards

🔴 Critical Battery Card / 低电量预警卡片

点击展开 / Click to expand
{% set ns = namespace(items=[]) %}
{% for s in states.sensor %}
 {% if s.attributes.device_class | default('') == 'battery' %}
 {% if 'power' not in s.entity_id and 'energy' not in s.entity_id and 'voltage' not in s.entity_id and 'consumption' not in s.entity_id %}
 {% if s.state not in ['unavailable', 'unknown', 'none', ''] %}
 {% set pct = s.state | int(-1) %}
 {% if pct >= 0 and pct <= 20 %}
 {% set name = s.attributes.friendly_name | default(s.entity_id) %}
 {# 核心文本切除引擎:一并斩断 电池/电量/低电量/充电/干电池 以及英文 Battery Level #}
 {% set clean_name = name | replace('电池','' ) | replace('电量','') | replace('低电量','') | replace('充电','') | replace('干电池','') | replace('Battery Level','') | replace('battery level','') | trim %}
 
 {% set matched_icon = 'mdi:battery' %}
 {% set ns.items = ns.items + [[pct, clean_name, s.entity_id, matched_icon]] %}
 {% endif %}
 {% endif %}
 {% endif %}
 {% endif %}
{% endfor %}
{% set sorted_items = ns.items | sort(attribute=0) %}
{% set total_count = sorted_items|count %}
<div class="dribbble-luxury-card">
 <div class="card-widget-header">
 <span class="header-left-title">BATTERY · 电池状态监控</span>
 <span class="header-right-status">{{ total_count }} 个设备需要更换电池/充电</span>
 </div>
 <div class="apple-header-main">
 <div class="title-with-indicator">
 <div class="led-embedded-dot"></div>
 <h2>低电量预警</h2>
 </div>
 <div class="apple-badge badge-critical">注意</div>
 </div>
 <div class="card-content-matrix">
 {% if total_count > 0 %}
 <div class="apple-list-vertical">
 {% for item in sorted_items[:5] %}
 {% set current_pct = item[0] %}
 {% if current_pct <= 5 %}
 {% set dynamic_color = '#FF3B30' %} {% set icon_bg = 'rgba(255, 59, 48, 0.08)' %}
 {% elif current_pct <= 12 %}
 {% set dynamic_color = '#FF453A' %} {% set icon_bg = 'rgba(255, 69, 58, 0.06)' %}
 {% else %}
 {% set dynamic_color = '#FF5E55' %} {% set icon_bg = 'rgba(255, 94, 85, 0.05)' %}
 {% endif %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">续航不足,建议及时更换</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot" style="background: linear-gradient(to bottom, rgba(255,59,48,0), {{ dynamic_color }} 50%, rgba(255,59,48,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 {% if total_count > 5 %}
 <details class="apple-adaptive-drawer">
 <summary class="drawer-trigger-bar">
 <span class="trigger-text text-close">▼ 展开其余 {{ total_count - 5 }} 个低电量终端</span>
 <span class="trigger-text text-open">さんかく 收起其余 {{ total_count - 5 }} 个低电量终端</span>
 </summary>
 <div class="drawer-inner-padding-box">
 {% for item in sorted_items[5:] %}
 {% set current_pct = item[0] %}
 {% if current_pct <= 5 %}
 {% set dynamic_color = '#FF3B30' %} {% set icon_bg = 'rgba(255, 59, 48, 0.08)' %}
 {% elif current_pct <= 12 %}
 {% set dynamic_color = '#FF453A' %} {% set icon_bg = 'rgba(255, 69, 58, 0.06)' %}
 {% else %}
 {% set dynamic_color = '#FF5E55' %} {% set icon_bg = 'rgba(255, 94, 85, 0.05)' %}
 {% endif %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">续航不足,建议及时更换</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot" style="background: linear-gradient(to bottom, rgba(255,59,48,0), {{ dynamic_color }} 50%, rgba(255,59,48,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 </div>
 </details>
 {% endif %}
 </div>
 {% else %}
 <div class="apple-empty-banner">
 <svg viewBox="0 0 24 24" class="empty-icon"><path fill="currentColor" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.58,8.08L11,13.67L7.92,10.59L6.5,12L11,16.5Z"/></svg>
 <span>所有设备电量充足 // 运行状态良好</span>
 </div>
 {% endif %}
 </div>
</div>
<style>
:host { --ha-card-background: transparent !important; --ha-card-box-shadow: none !important; --ha-card-border-width: 0px !important; --ha-card-border-color: transparent !important; display: block !important; margin-bottom: 14px !important; }
.dribbble-luxury-card { background: var(--ha-card-background, var(--card-background-color, rgba(255, 255, 255, 0.45))) !important; border-radius: 10px !important; padding: 16px !important; box-sizing: border-box !important; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif !important; position: relative !important; overflow: hidden !important; border: 1px solid var(--ha-card-border-color, var(--divider-color, rgba(0, 0, 0, 0.04))) !important; box-shadow: var(--ha-card-box-shadow, none) !important; }
.card-widget-header { display: flex !important; justify-content: space-between !important; font-size: 10px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; opacity: 0.7 !important; margin-bottom: 12px !important; letter-spacing: 0.3px !important; }
.apple-header-main { display: flex !important; justify-content: space-between !important; align-items: center !important; margin-bottom: 14px !important; }
.title-with-indicator { display: flex !important; align-items: center !important; gap: 8px !important; }
.title-with-indicator h2 { font-size: 15px !important; font-weight: 700 !important; color: var(--primary-text-color, #1d1d1f) !important; margin: 0 !important; letter-spacing: -0.2px !important; }
.apple-badge { font-size: 9px !important; font-weight: 700 !important; padding: 2px 8px !important; border-radius: 10px !important; }
.badge-critical { background: rgba(255, 59, 48, 0.1) !important; color: #ff3b30 !important; }
.led-embedded-dot { width: 5px !important; height: 5px !important; border-radius: 10px !important; background: #ff3b30 !important; box-shadow: 0 0 6px rgba(255, 59, 48, 0.6) !important; animation: dribbble-micro-dot-glow 3.5s infinite ease-in-out !important; }
.apple-list-vertical { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.apple-list-item { background: var(--secondary-background-color, rgba(0, 0, 0, 0.02)) !important; border: 1px solid var(--divider-color, rgba(0, 0, 0, 0.04)) !important; border-radius: 10px !important; padding: 12px 20px 12px 16px !important; display: flex !important; align-items: center !important; justify-content: space-between !important; position: relative !important; overflow: hidden !important; }
.item-pure-glass-bg { position: absolute !important; inset: 0 !important; z-index: 1 !important; pointer-events: none !important; }
.item-left-alignment-box { display: flex !important; align-items: center !important; gap: 10px !important; position: relative !important; z-index: 2 !important; flex: 1 !important; min-width: 0 !important; }
.dribbble-icon-pod { width: 32px !important; height: 32px !important; border-radius: 10px !important; display: flex !important; align-items: center !important; justify-content: center !important; flex-shrink: 0 !important; }
.dribbble-icon-pod ha-icon { --mdc-icon-size: 16px !important; }
.text-meta-box { display: flex !important; flex-direction: column !important; gap: 2px !important; min-width: 0 !important; flex: 1 !important; }
.device-name-text { font-size: 13px !important; font-weight: 600 !important; color: var(--primary-text-color, #1d1d1f) !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; }
.device-sub-text { font-size: 10px !important; color: var(--secondary-text-color, #86868b) !important; font-weight: 500 !important; opacity: 0.8; }
.item-right-energy-zone { display: flex !important; align-items: center !important; gap: 12px !important; position: relative !important; z-index: 2 !important; margin-right: 6px !important; flex-shrink: 0 !important; }
.apple-capsule-rail { width: 42px !important; height: 8px !important; background: repeating-linear-gradient(45deg, var(--divider-color, rgba(0, 0, 0, 0.08)), var(--divider-color, rgba(0, 0, 0, 0.08)) 1.5px, transparent 1.5px, transparent 4px) !important; border-radius: 10px !important; overflow: hidden !important; display: flex !important; }
.apple-capsule-fill { height: 100% !important; border-radius: 10px !important; }
.apple-static-percent { font-size: 13px !important; font-weight: 700 !important; min-width: 32px !important; text-align: right !important; }
.hud-right-edge-track { position: absolute !important; right: 0 !important; top: 0 !important; width: 2.5px !important; height: 100% !important; background: rgba(0, 0, 0, 0.005) !important; z-index: 3 !important; }
.hud-fluid-dot { position: absolute !important; left: 0 !important; width: 100% !important; height: 24px !important; animation: hud-gravity-drop 2.2s infinite linear !important; }
.apple-adaptive-drawer { display: contents !important; }
.apple-adaptive-drawer:not([open]) .drawer-inner-padding-box { position: absolute !important; transform: scale(0) !important; opacity: 0 !important; pointer-events: none !important; }
.apple-adaptive-drawer[open] .drawer-inner-padding-box { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.drawer-trigger-bar { background: var(--secondary-background-color, rgba(0, 0, 0, 0.015)) !important; border: 1px dashed var(--divider-color, rgba(0, 0, 0, 0.06)) !important; border-radius: 10px !important; padding: 10px !important; text-align: center !important; cursor: pointer !important; list-style: none !important; margin-top: 4px !important; order: 999 !important; }
.drawer-trigger-bar::-webkit-details-marker { display: none !important; }
.drawer-trigger-bar:hover { background: rgba(0, 0, 0, 0.03) !important; }
.trigger-text { font-size: 11px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; letter-spacing: 0.2px; }
.drawer-trigger-bar .text-open { display: none !important; }
.drawer-trigger-bar .text-close { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-open { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-close { display: none !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar { border-style: solid !important; background: rgba(0, 0, 0, 0.02) !important; }
.apple-adaptive-drawer .apple-list-item { margin-bottom: 0px !important; }
@keyframes hud-gravity-drop { 0% { top: -35%; opacity: 0; } 25% { opacity: 0.75; } 75% { opacity: 0.75; } 100% { top: 105%; opacity: 0; } }
@keyframes dribbble-micro-dot-glow { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; box-shadow: 0 0 8px rgba(255, 59, 48, 0.8) !important; } }
</style>

🟠 Warning Battery Card / 中电量提示卡片

点击展开 / Click to expand
{% set ns = namespace(items=[]) %}
{% for s in states.sensor %}
 {% if s.attributes.device_class | default('') == 'battery' %}
 {% if 'power' not in s.entity_id and 'energy' not in s.entity_id and 'voltage' not in s.entity_id and 'consumption' not in s.entity_id %}
 {% if s.state not in ['unavailable', 'unknown', 'none', ''] %}
 {% set pct = s.state | int(-1) %}
 {% if pct > 20 and pct <= 50 %}
 {% set name = s.attributes.friendly_name | default(s.entity_id) %}
 {# 核心文本切除引擎:一并斩断 电池/电量/低电量/充电/干电池 以及英文 Battery Level #}
 {% set clean_name = name | replace('电池','' ) | replace('电量','') | replace('低电量','') | replace('充电','') | replace('干电池','') | replace('Battery Level','') | replace('battery level','') | trim %}
 
 {% set matched_icon = 'mdi:battery' %}
 {% set ns.items = ns.items + [[pct, clean_name, s.entity_id, matched_icon]] %}
 {% endif %}
 {% endif %}
 {% endif %}
 {% endif %}
{% endfor %}
{% set sorted_items = ns.items | sort(attribute=0) %}
{% set total_count = sorted_items|count %}
<div class="dribbble-luxury-card">
 <div class="card-widget-header">
 <span class="header-left-title">BATTERY · 电池状态监控</span>
 <span class="header-right-status">{{ total_count }} 个设备电量稍低</span>
 </div>
 <div class="apple-header-main">
 <div class="title-with-indicator">
 <div class="led-embedded-dot"></div>
 <h2>中电量提示</h2>
 </div>
 <div class="apple-badge badge-warning">提示</div>
 </div>
 <div class="card-content-matrix">
 {% if total_count > 0 %}
 <div class="apple-list-vertical">
 {% for item in sorted_items[:5] %}
 {% set current_pct = item[0] %}
 {% set dynamic_color = '#FF9F0A' %}
 {% set icon_bg = 'rgba(255, 159, 10, 0.06)' %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">续航稍低,请留意电量</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot-up" style="background: linear-gradient(to top, rgba(255,159,10,0), {{ dynamic_color }} 50%, rgba(255,159,10,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 {% if total_count > 5 %}
 <details class="apple-adaptive-drawer">
 <summary class="drawer-trigger-bar">
 <span class="trigger-text text-close">▼ 展开其余 {{ total_count - 5 }} 个中电量终端</span>
 <span class="trigger-text text-open">さんかく 收起其余 {{ total_count - 5 }} 个中电量终端</span>
 </summary>
 <div class="drawer-inner-padding-box">
 {% for item in sorted_items[5:] %}
 {% set current_pct = item[0] %}
 {% set dynamic_color = '#FF9F0A' %}
 {% set icon_bg = 'rgba(255, 159, 10, 0.06)' %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">续航稍低,请留意电量</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot-up" style="background: linear-gradient(to top, rgba(255,159,10,0), {{ dynamic_color }} 50%, rgba(255,159,10,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 </div>
 </details>
 {% endif %}
 </div>
 {% else %}
 <div class="apple-empty-banner">
 <svg viewBox="0 0 24 24" class="empty-icon"><path fill="currentColor" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.58,8.08L11,13.67L7.92,10.59L6.5,12L11,16.5Z"/></svg>
 <span>当前无中度消耗设备</span>
 </div>
 {% endif %}
 </div>
</div>
<style>
:host { --ha-card-background: transparent !important; --ha-card-box-shadow: none !important; --ha-card-border-width: 0px !important; --ha-card-border-color: transparent !important; display: block !important; margin-bottom: 14px !important; }
.dribbble-luxury-card { background: var(--ha-card-background, var(--card-background-color, rgba(255, 255, 255, 0.45))) !important; border-radius: 10px !important; padding: 16px !important; box-sizing: border-box !important; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif !important; position: relative !important; overflow: hidden !important; border: 1px solid var(--ha-card-border-color, var(--divider-color, rgba(0, 0, 0, 0.04))) !important; box-shadow: var(--ha-card-box-shadow, none) !important; }
.card-widget-header { display: flex !important; justify-content: space-between !important; font-size: 10px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; opacity: 0.7 !important; margin-bottom: 12px !important; letter-spacing: 0.3px !important; }
.apple-header-main { display: flex !important; justify-content: space-between !important; align-items: center !important; margin-bottom: 14px !important; }
.title-with-indicator { display: flex !important; align-items: center !important; gap: 8px !important; }
.title-with-indicator h2 { font-size: 15px !important; font-weight: 700 !important; color: var(--primary-text-color, #1d1d1f) !important; margin: 0 !important; letter-spacing: -0.2px !important; }
.apple-badge { font-size: 9px !important; font-weight: 700 !important; padding: 2px 8px !important; border-radius: 10px !important; }
.badge-warning { background: rgba(255, 159, 10, 0.1) !important; color: #ff9f0a !important; }
.led-embedded-dot { width: 5px !important; height: 5px !important; border-radius: 10px !important; background: #ff9f0a !important; box-shadow: 0 0 6px rgba(255, 159, 10, 0.6) !important; animation: dribbble-micro-dot-glow 3.5s infinite ease-in-out !important; }
.apple-list-vertical { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.apple-list-item { background: var(--secondary-background-color, rgba(0, 0, 0, 0.02)) !important; border: 1px solid var(--divider-color, rgba(0, 0, 0, 0.04)) !important; border-radius: 10px !important; padding: 12px 20px 12px 16px !important; display: flex !important; align-items: center !important; justify-content: space-between !important; position: relative !important; overflow: hidden !important; }
.item-pure-glass-bg { position: absolute !important; inset: 0 !important; z-index: 1 !important; pointer-events: none !important; }
.item-left-alignment-box { display: flex !important; align-items: center !important; gap: 10px !important; position: relative !important; z-index: 2 !important; flex: 1 !important; min-width: 0 !important; }
.dribbble-icon-pod { width: 32px !important; height: 32px !important; border-radius: 10px !important; display: flex !important; align-items: center !important; justify-content: center !important; flex-shrink: 0 !important; }
.dribbble-icon-pod ha-icon { --mdc-icon-size: 16px !important; }
.text-meta-box { display: flex !important; flex-direction: column !important; gap: 2px !important; min-width: 0 !important; flex: 1 !important; }
.device-name-text { font-size: 13px !important; font-weight: 600 !important; color: var(--primary-text-color, #1d1d1f) !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; }
.device-sub-text { font-size: 10px !important; color: var(--secondary-text-color, #86868b) !important; font-weight: 500 !important; opacity: 0.8; }
.item-right-energy-zone { display: flex !important; align-items: center !important; gap: 12px !important; position: relative !important; z-index: 2 !important; margin-right: 6px !important; flex-shrink: 0 !important; }
.apple-capsule-rail { width: 42px !important; height: 8px !important; background: repeating-linear-gradient(45deg, var(--divider-color, rgba(0, 0, 0, 0.08)), var(--divider-color, rgba(0, 0, 0, 0.08)) 1.5px, transparent 1.5px, transparent 4px) !important; border-radius: 10px !important; overflow: hidden !important; display: flex !important; }
.apple-capsule-fill { height: 100% !important; border-radius: 10px !important; }
.apple-static-percent { font-size: 13px !important; font-weight: 700 !important; min-width: 32px !important; text-align: right !important; }
.hud-right-edge-track { position: absolute !important; right: 0 !important; top: 0 !important; width: 2.5px !important; height: 100% !important; background: rgba(0, 0, 0, 0.005) !important; z-index: 3 !important; }
.hud-fluid-dot-up { position: absolute !important; left: 0 !important; width: 100% !important; height: 24px !important; animation: hud-gravity-rise 2.2s infinite linear !important; }
.apple-adaptive-drawer { display: contents !important; }
.apple-adaptive-drawer:not([open]) .drawer-inner-padding-box { position: absolute !important; transform: scale(0) !important; opacity: 0 !important; pointer-events: none !important; }
.apple-adaptive-drawer[open] .drawer-inner-padding-box { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.drawer-trigger-bar { background: var(--secondary-background-color, rgba(0, 0, 0, 0.015)) !important; border: 1px dashed var(--divider-color, rgba(0, 0, 0, 0.06)) !important; border-radius: 10px !important; padding: 10px !important; text-align: center !important; cursor: pointer !important; list-style: none !important; margin-top: 4px !important; order: 999 !important; }
.drawer-trigger-bar::-webkit-details-marker { display: none !important; }
.drawer-trigger-bar:hover { background: rgba(0, 0, 0, 0.03) !important; }
.trigger-text { font-size: 11px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; letter-spacing: 0.2px; }
.drawer-trigger-bar .text-open { display: none !important; }
.drawer-trigger-bar .text-close { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-open { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-close { display: none !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar { border-style: solid !important; background: rgba(0, 0, 0, 0.02) !important; }
.apple-adaptive-drawer .apple-list-item { margin-bottom: 0px !important; }
@keyframes hud-gravity-rise { 0% { top: 105%; opacity: 0; } 25% { opacity: 0.75; } 75% { opacity: 0.75; } 100% { top: -35%; opacity: 0; } }
@keyframes dribbble-micro-dot-glow { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; box-shadow: 0 0 8px rgba(255, 159, 10, 0.8) !important; } }
</style>

🟢 Healthy Battery Card / 电量充足卡片

点击展开 / Click to expand
{% set ns = namespace(items=[]) %}
{% for s in states.sensor %}
 {% if s.attributes.device_class | default('') == 'battery' %}
 {% if 'power' not in s.entity_id and 'energy' not in s.entity_id and 'voltage' not in s.entity_id and 'consumption' not in s.entity_id %}
 {% if s.state not in ['unavailable', 'unknown', 'none', ''] %}
 {% set pct = s.state | int(-1) %}
 {% if pct > 50 and pct <= 100 %}
 {% set name = s.attributes.friendly_name | default(s.entity_id) %}
 {# 核心文本切除引擎:一并斩断 电池/电量/低电量/充电/干电池 以及英文 Battery Level #}
 {% set clean_name = name | replace('电池','' ) | replace('电量','') | replace('低电量','') | replace('充电','') | replace('干电池','') | replace('Battery Level','') | replace('battery level','') | trim %}
 
 {% set matched_icon = 'mdi:battery' %}
 {% set ns.items = ns.items + [[pct, clean_name, s.entity_id, matched_icon]] %}
 {% endif %}
 {% endif %}
 {% endif %}
 {% endif %}
{% endfor %}
{% set sorted_items = ns.items | sort(attribute=0, reverse=true) %}
{% set total_count = sorted_items|count %}
<div class="dribbble-luxury-card">
 <div class="card-widget-header">
 <span class="header-left-title">BATTERY · 电池状态监控</span>
 <span class="header-right-status">{{ total_count }} 个设备状态良好</span>
 </div>
 <div class="apple-header-main">
 <div class="title-with-indicator">
 <div class="led-embedded-dot"></div>
 <h2>电量充足</h2>
 </div>
 <div class="apple-badge badge-healthy">安全</div>
 </div>
 <div class="card-content-matrix">
 {% if total_count > 0 %}
 <div class="apple-list-vertical">
 {% for item in sorted_items[:5] %}
 {% set current_pct = item[0] %}
 {% set dynamic_color = '#30D158' %}
 {% set icon_bg = 'rgba(48, 209, 88, 0.06)' %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">能源充沛,续航无忧</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot-pure-static" style="background: linear-gradient(to bottom, rgba(48,209,88,0), {{ dynamic_color }} 50%, rgba(48,209,88,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 {% if total_count > 5 %}
 <details class="apple-adaptive-drawer">
 <summary class="drawer-trigger-bar">
 <span class="trigger-text text-close">▼ 展开其余 {{ total_count - 5 }} 个充足电量终端</span>
 <span class="trigger-text text-open">さんかく 收起其余 {{ total_count - 5 }} 个充足电量终端</span>
 </summary>
 <div class="drawer-inner-padding-box">
 {% for item in sorted_items[5:] %}
 {% set current_pct = item[0] %}
 {% set dynamic_color = '#30D158' %}
 {% set icon_bg = 'rgba(48, 209, 88, 0.06)' %}
 <div class="apple-list-item" clickAction="more-info" clickEntity="{{ item[2] }}">
 <div class="item-pure-glass-bg"></div>
 <div class="item-left-alignment-box">
 <div class="dribbble-icon-pod" style="background: {{ icon_bg }} !important; color: {{ dynamic_color }} !important;">
 <ha-icon icon="{{ item[3] }}"></ha-icon>
 </div>
 <div class="text-meta-box">
 <span class="device-name-text">{{ item[1] }}</span>
 <span class="device-sub-text">能源充沛,续航无忧</span>
 </div>
 </div>
 <div class="item-right-energy-zone">
 <div class="apple-capsule-rail">
 <div class="apple-capsule-fill" style="width: {{ current_pct }}%; background: {{ dynamic_color }} !important;"></div>
 </div>
 <span class="apple-static-percent" style="color: {{ dynamic_color }} !important;">{{ current_pct }}%</span>
 </div>
 <div class="hud-right-edge-track">
 <div class="hud-fluid-dot-pure-static" style="background: linear-gradient(to bottom, rgba(48,209,88,0), {{ dynamic_color }} 50%, rgba(48,209,88,0)) !important;"></div>
 </div>
 </div>
 {% endfor %}
 </div>
 </details>
 {% endif %}
 </div>
 {% else %}
 <div class="apple-empty-banner">
 <svg viewBox="0 0 24 24" class="empty-icon"><path fill="currentColor" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.58,8.08L11,13.67L7.92,10.59L6.5,12L11,16.5Z"/></svg>
 <span>暂无高电量设备</span>
 </div>
 {% endif %}
 </div>
</div>
<style>
:host { --ha-card-background: transparent !important; --ha-card-box-shadow: none !important; --ha-card-border-width: 0px !important; --ha-card-border-color: transparent !important; display: block !important; margin-bottom: 14px !important; }
.dribbble-luxury-card { background: var(--ha-card-background, var(--card-background-color, rgba(255, 255, 255, 0.45))) !important; border-radius: 10px !important; padding: 16px !important; box-sizing: border-box !important; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif !important; position: relative !important; overflow: hidden !important; border: 1px solid var(--ha-card-border-color, var(--divider-color, rgba(0, 0, 0, 0.04))) !important; box-shadow: var(--ha-card-box-shadow, none) !important; }
.card-widget-header { display: flex !important; justify-content: space-between !important; font-size: 10px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; opacity: 0.7 !important; margin-bottom: 12px !important; letter-spacing: 0.3px !important; }
.apple-header-main { display: flex !important; justify-content: space-between !important; align-items: center !important; margin-bottom: 14px !important; }
.title-with-indicator { display: flex !important; align-items: center !important; gap: 8px !important; }
.title-with-indicator h2 { font-size: 15px !important; font-weight: 700 !important; color: var(--primary-text-color, #1d1d1f) !important; margin: 0 !important; letter-spacing: -.2px !important; }
.apple-badge { font-size: 9px !important; font-weight: 700 !important; padding: 2px 8px !important; border-radius: 10px !important; }
.badge-healthy { background: rgba(52,199,89,.1) !important; color: #30d158 !important; }
.led-embedded-dot { width: 5px !important; height: 5px !important; border-radius: 10px !important; background: #30d158 !important; box-shadow: 0 0 6px rgba(48,209,88,.6) !important; animation: dribbble-micro-dot-glow 3.5s infinite ease-in-out !important; }
.apple-list-vertical { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.apple-list-item { background: var(--secondary-background-color, rgba(0, 0, 0, 0.02)) !important; border: 1px solid var(--divider-color, rgba(0, 0, 0, 0.04)) !important; border-radius: 10px !important; padding: 12px 20px 12px 16px !important; display: flex !important; align-items: center !important; justify-content: space-between !important; position: relative !important; overflow: hidden !important; }
.item-pure-glass-bg { position: absolute !important; inset: 0 !important; z-index: 1 !important; pointer-events: none !important; }
.item-left-alignment-box { display: flex !important; align-items: center !important; gap: 10px !important; position: relative !important; z-index: 2 !important; flex: 1 !important; min-width: 0 !important; }
.dribbble-icon-pod { width: 32px !important; height: 32px !important; border-radius: 10px !important; display: flex !important; align-items: center !important; justify-content: center !important; flex-shrink: 0 !important; }
.dribbble-icon-pod ha-icon { --mdc-icon-size: 16px !important; }
.text-meta-box { display: flex !important; flex-direction: column !important; gap: 2px !important; min-width: 0 !important; flex: 1 !important; }
.device-name-text { font-size: 13px !important; font-weight: 600 !important; color: var(--primary-text-color, #1d1d1f) !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; }
.device-sub-text { font-size: 10px !important; color: var(--secondary-text-color, #86868b) !important; font-weight: 500 !important; opacity: .8; }
.item-right-energy-zone { display: flex !important; align-items: center !important; gap: 12px !important; position: relative !important; z-index: 2 !important; margin-right: 6px !important; flex-shrink: 0 !important; }
.apple-capsule-rail { width: 42px !important; height: 8px !important; background: repeating-linear-gradient(45deg, var(--divider-color, rgba(0, 0, 0, 0.08)), var(--divider-color, rgba(0, 0, 0, 0.08)) 1.5px, transparent 1.5px, transparent 4px) !important; border-radius: 10px !important; overflow: hidden !important; display: flex !important; }
.apple-capsule-fill { height: 100% !important; border-radius: 10px !important; }
.apple-static-percent { font-size: 13px !important; font-weight: 700 !important; min-width: 32px !important; text-align: right !important; }
.hud-right-edge-track { position: absolute !important; right: 0 !important; top: 0 !important; width: 2.5px !important; height: 100% !important; background: rgba(0, 0, 0, 0.005) !important; z-index: 3 !important; }
.hud-fluid-dot-pure-static { position: absolute !important; left: 0 !important; width: 100% !important; height: 36px !important; top: calc(50% - 18px) !important; animation: hud-traditional-pure-breath 4.5s infinite ease-in-out !important; animation-delay: -2.25s !important; will-change: opacity, filter !important; transform: translateZ(0) !important; backface-visibility: hidden !important; pointer-events: none !important; }
.apple-adaptive-drawer { display: contents !important; }
.apple-adaptive-drawer:not([open]) .drawer-inner-padding-box { position: absolute !important; transform: scale(0) !important; opacity: 0 !important; pointer-events: none !important; }
.apple-adaptive-drawer[open] .drawer-inner-padding-box { display: flex !important; flex-direction: column !important; gap: 8px !important; }
.drawer-trigger-bar { background: var(--secondary-background-color, rgba(0, 0, 0, 0.015)) !important; border: 1px dashed var(--divider-color, rgba(0, 0, 0, 0.06)) !important; border-radius: 10px !important; padding: 10px !important; text-align: center !important; cursor: pointer !important; list-style: none !important; margin-top: 4px !important; order: 999 !important; }
.drawer-trigger-bar::-webkit-details-marker { display: none !important; }
.drawer-trigger-bar:hover { background: rgba(0, 0, 0, 0.03) !important; }
.trigger-text { font-size: 11px !important; font-weight: 600 !important; color: var(--secondary-text-color, #86868b) !important; letter-spacing: .2px; }
.drawer-trigger-bar .text-open { display: none !important; }
.drawer-trigger-bar .text-close { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-open { display: inline !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar .text-close { display: none !important; }
.apple-adaptive-drawer[open] .drawer-trigger-bar { border-style: solid !important; background: rgba(0, 0, 0, 0.02) !important; }
@keyframes hud-traditional-pure-breath { 0%,100% { opacity: .12; filter: blur(0px); transform: scaleY(.92); } 50% { opacity: .92; filter: blur(.45px); transform: scaleY(1.08); } }
@keyframes dribbble-micro-dot-glow { 0%,100% { opacity: .5; } 50% { opacity: 1; box-shadow: 0 0 8px rgba(48, 209, 88, .8) !important; } }
</style>
You must be logged in to vote

Replies: 0 comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
1 participant

AltStyle によって変換されたページ (->オリジナル) /