完美解决限行信息展示问题,通过智能识别尾号组合展示品牌限行状态

在之前的卡片分享(三)中,我分享了一个用于显示城市限行信息的Home Assistant卡片配置。今天,我对这个卡片进行了重大升级!现在,它不仅能显示限行尾号,还能根据尾号动态显示对应的汽车品牌(如福特、大众),并用颜色直观区分限行状态。本文将详细介绍升级内容,并分享完整的配置代码。

升级亮点

  1. 品牌限行提示

    • 当限行尾号为2和7时显示"福特限行"

    • 当限行尾号为4和9时显示"大众限行"

    • 其他尾号组合显示"不限行"

  2. 智能颜色编码

    • 今日限行:品牌限行→红色,不限行→绿色

    • 明日限行:品牌限行→橙色,不限行→绿色

  3. 视觉统一优化

    • 完全一致的卡片尺寸和布局

    • 统一字体大小和间距

    • 专业圆角设计和阴影效果

效果预览

配置代码详解

yaml

type: horizontal-stack
cards:
  # ========== 今日限行卡片 ==========
  - type: custom:button-card
    entity: sensor.traffic_limit_today
    name: 今日限行
    icon: mdi:car
    show_state: true
    show_label: true
    styles:
      card:
        - border-radius: 12px
        - padding: 12px
        - box-shadow: var(--box-shadow)
      grid:
        - grid-template-areas: '"i n" "i s" "i l"'
        - grid-template-columns: 1fr 3fr
      name: 
        - font-weight: bold
        - font-size: 14px
      state:
        - font-size: 13px
      label:
        - font-size: 13px
    
    # 智能状态覆盖 - 解决周末未知问题
    state_display: |
      [[[
        const today = new Date();
        const day = today.getDay(); // 0=周日, 6=周六
        
        // 周末特殊处理
        if (day === 0 || day === 6) {
          return '周末不限行';
        }
        
        // 正常状态显示
        return entity.state;
      ]]]
    
    # 动态品牌信息 + 周末处理
    label: |
      [[[
        const today = new Date();
        const day = today.getDay();
        const days = ['日','一','二','三','四','五','六'];
        
        // 周末显示星期信息
        if (day === 0 || day === 6) {
          return '星期' + days[day];
        }
        
        // 工作日品牌判断
        const state = entity.state;
        const numbers = state.match(/\d/g) || [];
        
        if (numbers.includes('2') && numbers.includes('7')) {
          return '福特限行';
        } else if (numbers.includes('4') && numbers.includes('9')) {
          return '大众限行';
        } else {
          return '不限行';
        }
      ]]]

    # 动态图标颜色
    state:
      # 周末状态 - 绿色
      - operator: template
        value: "[[[ return new Date().getDay() === 0 || new Date().getDay() === 6; ]]]"
        styles:
          icon: 
            - color: "#4CAF50"  # 绿色-安全
      
      # 品牌限行 - 红色
      - operator: template
        value: |
          [[[
            const state = entity.state;
            const numbers = state.match(/\d/g) || [];
            return (numbers.includes('2') && numbers.includes('7')) || 
                   (numbers.includes('4') && numbers.includes('9'));
          ]]]
        styles:
          icon: 
            - color: "#F44336"  # 红色-警示
      
      # 普通不限行 - 绿色
      - operator: template
        value: |
          [[[
            const state = entity.state;
            const numbers = state.match(/\d/g) || [];
            return !(numbers.includes('2') && numbers.includes('7')) && 
                   !(numbers.includes('4') && numbers.includes('9'));
          ]]]
        styles:
          icon: 
            - color: "#4CAF50"  # 绿色-安全

  # ========== 明日限行卡片 ==========
  - type: custom:button-card
    entity: sensor.traffic_limit_tomorrow
    name: 明日限行
    icon: mdi:car-clock
    show_state: true
    show_label: true
    styles:
      card:
        - border-radius: 12px
        - padding: 12px
        - box-shadow: var(--box-shadow)
      grid:
        - grid-template-areas: '"i n" "i s" "i l"'
        - grid-template-columns: 1fr 3fr
      name: 
        - font-weight: bold
        - font-size: 14px
      state:
        - font-size: 13px
      label:
        - font-size: 13px
    
    # 智能状态覆盖 - 解决周末未知问题
    state_display: |
      [[[
        const tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        const day = tomorrow.getDay(); // 0=周日, 6=周六
        
        // 周末特殊处理
        if (day === 0 || day === 6) {
          return '周末不限行';
        }
        
        // 正常状态显示
        return entity.state;
      ]]]
    
    # 动态品牌信息 + 周末处理
    label: |
      [[[
        const tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        const day = tomorrow.getDay();
        const days = ['日','一','二','三','四','五','六'];
        
        // 周末显示星期信息
        if (day === 0 || day === 6) {
          return '星期' + days[day];
        }
        
        // 工作日品牌判断
        const state = entity.state;
        const numbers = state.match(/\d/g) || [];
        
        if (numbers.includes('2') && numbers.includes('7')) {
          return '福特限行';
        } else if (numbers.includes('4') && numbers.includes('9')) {
          return '大众限行';
        } else {
          return '不限行';
        }
      ]]]

    # 动态图标颜色
    state:
      # 周末状态 - 绿色
      - operator: template
        value: |
          [[[
            const tomorrow = new Date();
            tomorrow.setDate(tomorrow.getDate() + 1);
            return tomorrow.getDay() === 0 || tomorrow.getDay() === 6;
          ]]]
        styles:
          icon: 
            - color: "#4CAF50"  # 绿色-安全
      
      # 品牌限行 - 橙色
      - operator: template
        value: |
          [[[
            const state = entity.state;
            const numbers = state.match(/\d/g) || [];
            return (numbers.includes('2') && numbers.includes('7')) || 
                   (numbers.includes('4') && numbers.includes('9'));
          ]]]
        styles:
          icon: 
            - color: "#FF9800"  # 橙色-提醒
      
      # 普通不限行 - 绿色
      - operator: template
        value: |
          [[[
            const state = entity.state;
            const numbers = state.match(/\d/g) || [];
            return !(numbers.includes('2') && numbers.includes('7')) && 
                   !(numbers.includes('4') && numbers.includes('9'));
          ]]]
        styles:
          icon: 
            - color: "#4CAF50"  # 绿色-安全

技术解析

1. 智能尾号识别系统

javascript

const numbers = state.match(/\d/g) || [];

这行代码使用正则表达式/\d/g从传感器状态中提取所有数字,无论状态信息如何变化(如"限行尾号:2和7"或"2,7限行"),都能准确识别尾号数字。

2. 品牌匹配逻辑

javascript

if (numbers.includes('2') && numbers.includes('7')) {
    return '福特限行';
} else if (numbers.includes('4') && numbers.includes('9')) {
    return '大众限行';
} else {
    return '不限行';
}

此逻辑核心是检查尾号组合:

  • 同时存在2和7 → 福特限行

  • 同时存在4和9 → 大众限行

  • 其他组合 → 不限行

3. 动态颜色系统

今日限行卡片

yaml

- operator: template
  styles:
    icon: 
      - color: "#F44336"  # 品牌限行→红色
- operator: template
  styles:
    icon: 
      - color: "#4CAF50"  # 不限行→绿色

明日限行卡片

yaml

- operator: template
  styles:
    icon: 
      - color: "#FF9800"  # 品牌限行→橙色
- operator: template
  styles:
    icon: 
      - color: "#4CAF50"  # 不限行→绿色

颜色选择遵循UX设计原则:

  • 红色(#F44336):立即注意,今日风险

  • 橙色(#FF9800):未来提醒,注意规划

  • 绿色(#4CAF50):安全状态,畅通无阻

4. 统一视觉设计

yaml

styles:
  card:
    - border-radius: 12px   # 现代圆角设计
    - padding: 12px         # 舒适内边距
    - box-shadow: var(--box-shadow) # 深度效果
    
  grid:
    - grid-template-areas: '"i n" "i s" "i l"' # 三行布局
    - grid-template-columns: 1fr 3fr # 黄金比例分割
    
  name: 
    - font-weight: bold
    - font-size: 14px   # 统一标题大小
    
  state:
    - font-size: 13px   # 统一状态信息大小
    
  label:
    - font-size: 13px   # 统一品牌信息大小

5. 智能周末处理系统(更新)

yaml

// 今日卡片周末检测
const today = new Date();
const day = today.getDay();
if (day === 0 || day === 6) {
  return '周末不限行';
}

// 明日卡片周末检测
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const tomorrowDay = tomorrow.getDay();
if (tomorrowDay === 0 || tomorrowDay === 6) {
  return '周末不限行';
}

使用指南

  1. 前提条件

    • 安装并配置好 button-card 自定义组件

    • 确保有 sensor.traffic_limit_todaysensor.traffic_limit_tomorrow 实体

  2. 安装步骤

    markdown

    1. 复制完整配置代码
    2. 在HA仪表盘编辑模式中添加"手动卡片"
    3. 粘贴配置并保存
    4. 刷新页面查看效果
  3. 自定义选项

    • 更改品牌规则:修改JavaScript判断逻辑

    • 添加新品牌

      javascript

      } else if (numbers.includes('1') && numbers.includes('6')) {
          return '宝马限行';
    • 调整颜色:修改十六进制颜色值

升级价值

  1. 信息更直观

    • 品牌名称比数字组合更容易理解

    • 颜色编码提供即时视觉反馈

  2. 决策更高效

    • 一眼识别是否影响自己的车辆

    • 提前规划明日出行方案

  3. 界面更专业

    • 统一的设计语言提升整体美感

    • 响应式布局适应各种屏幕尺寸

结语

这次升级将简单的限行信息展示转变为智能的出行决策助手。通过动态识别尾号组合并关联汽车品牌,再辅以科学的颜色编码系统,让用户能够瞬间理解限行信息对自己的影响。

小贴士:这个系统可以轻松扩展支持更多品牌,只需简单修改模板中的判断逻辑即可。欢迎在评论区分享你的自定义版本!

配置最后更新时间:2025年7月21日
兼容版本:Home Assistant 2025.6+
依赖组件button-card