-
Notifications
You must be signed in to change notification settings - Fork 8
[Style] 自适应电池状态监控系统 / Adaptive Battery Monitoring System #16
[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>