找回密码
 立即注册

微信扫码登录

搜索
楼主: hungheo

[UI界面] 手机UI界面分享(08-31更新)

 火... [复制链接]

11

主题

267

回帖

2671

积分

金牌会员

积分
2671
金钱
2388
HASS币
20
 楼主| 发表于 2025-8-26 18:14:41 | 显示全部楼层
本帖最后由 hungheo 于 2025-8-27 22:12 编辑

话费卡片:
屏幕截图 2025-08-26 181222.png
button_card模板:

phone_bill:
    show_state: false
    show_icon: false
    show_name: true
    show_label: true
    tap_action:
      action: none
    label: |
      [[[
        return `账单:${states[variables.cost]?.state}  
                余额:${states[variables.balance]?.state}`
      ]]]
    styles:
      card:
        - background: none
        - padding: 15px 15px 25px 15px
        - border: 0px
        - margin: 0px
        - border-radius: 0px
        - box-shadow: none
        - backdrop-filter: none
      name:
        - color: black
        - font-size: 16px
        - font-weight: bold
        - justify-self: start
        - align-self: center
        - padding-right: 16px
      label:
        - color: grey
        - font-size: 12px
        - justify-self: start
        - align-self: center
        - padding-bottom: 8px
      grid:
        - grid-template-areas: |
            "n"
            "l"
            "gb"
            "min"
        - grid-template-rows: min-content min-content 1fr 1fr
        - grid-template-columns: 1fr
        - row-gap: 2px;
    custom_fields:
      gb:
        card:
          type: custom:button-card
          name: 流量
          template: phone_bill_sub
          variables:
            remaining_sub: '[[[return variables.remaininggb]]]'
            total_sub: '[[[return variables.totalgb]]]'
            units: GB
      min:
        card:
          type: custom:button-card
          name: 分钟
          template: phone_bill_sub
          variables:
            remaining_sub: '[[[return variables.remainingmin]]]'
            total_sub: '[[[return variables.totalmin]]]'
            units: 分钟

  phone_bill_sub:
    show_state: false
    show_icon: false
    show_label: true
    show_name: true
    tap_action:
      action: none
    label: |
      [[[
        return`剩余
          ${states[variables.remaining_sub]?.state} / ${states[variables.total_sub]?.state}${variables.units} 
        `;
      ]]]
    styles:
      grid:
        - grid-template-areas: |
            "n l" 
        - grid-template-rows: 1fr
        - grid-template-columns: min-content 1fr
      card:
        - background: none
        - padding: 0px 0px 10px 0px
        - border: 0px
        - margin: 0px
        - border-radius: 0px
        - box-shadow: none
        - backdrop-filter: none
      name:
        - color: black
        - background: none
        - padding-right: 10px
        - font-size: 14px
        - font-weight: bold
        - justify-self: start
        - align-self: center
      label:
        - background: none
        - color: grey
        - font-size: 12px
        - justify-self: start
        - align-self: end
    extra_styles: |
      [[[
        const remaining = parseFloat(states[variables.remaining_sub]?.state);
        const total = parseFloat(states[variables.total_sub]?.state);
        // 防止除以 0
        const percent = total !== 0 ? Math.round((remaining / total) * 10000) / 100 : 0;
        
        let colorPercent;
        if (percent >= 50) {
          colorPercent = 'var(--light-green-color)';
        } else if (percent >= 30) {
          colorPercent = 'var(--amber-color)';
        } else if (percent >= 15) {
          colorPercent = 'var(--orange-color)';
        } else {
          colorPercent = 'var(--red-color)';
        }
        return `
          #container::before {
            content: " ";
            width: 100%;
            height: 8px;
            bottom: 0px;
            border-radius: 12px;
            background: rgb(220,220,220);
            position: absolute;
            z-index: 0;
          }
          #container::after {
            content: " ";
            width: ${percent}%;
            height: 8px;
            bottom: 0px;
            border-radius: 12px;
            background: ${colorPercent};
            position: absolute;
            z-index: 1;
          }
        `;
      ]]]


使用:
如果页面不更新,添加triggers_update
- type: custom:button-card
            show_name: true
            show_state: false
            show_icon: false
            name: 话费账单
            tap_action:
              action: none
            styles:
              grid:
                - grid-template-areas: |
                    "n n"
                    "content1 content2"
                - grid-template-columns: 1fr 1fr
                - row-gap: 8px;
                - grid-template-rows: 38px 138px
              card:
                - padding: 0px
                - height: 184px
                - background: none
                - border: 0px
                - border-radius: 0px
                - margin: 0px
                - box-shadow: none
                - backdrop-filter: none
                - overflow: visible
              name:
                - margin-left: 15px
                - font-size: 18px
                - font-weight: bold
                - justify-self: start
                - align-self: center
            extra_styles: |
              #container::before {
                content: " ";
                width: 100%;
                height: 140px;
                align-self: end;
                border-radius: var(--ha-card-border-radius);
                background: var(--h-rgb-white,var(--disabled-color));
                box-shadow: var(--ha-card-box-shadow);
                position: absolute;
                z-index: 0;
                overflow: visible;
              }
            custom_fields:
              content1:
                card:
                  type: custom:button-card
                  name: 电信189
                  template: phone_bill
                  variables:
                    balance: sensor.telecom4390_balance #替换成自己的ID
                    cost: sensor.telecom4390_currentmonthcost #替换成自己的ID
                    remainingmin: sensor.telecom4390_remainingminutes #替换成自己的ID
                    totalmin: sensor.telecom4390_totalminutes #替换成自己的ID
                    remaininggb: sensor.telecom4390_remaininggb #替换成自己的ID
                    totalgb: sensor.telecom4390_totalgb #替换成自己的ID
              content2:
                card:
                  type: custom:button-card
                  name: 联通185
                  template: phone_bill
                  variables:
                    balance: sensor.unicom_bills_canusebalance #替换成自己的ID
                    cost: sensor.unicom_bills_usedbalance #替换成自己的ID
                    remainingmin: sensor.unicom_bills_canusemin #替换成自己的ID
                    totalmin: sensor.unicom_bills_totalmin #替换成自己的ID
                    remaininggb: sensor.unicom_bills_canusegb #替换成自己的ID
                    totalgb: sensor.unicom_bills_totalgb #替换成自己的ID
如果IOS下有排版错误,请参考https://bbs.hassbian.com/forum.php?mod=redirect&goto=findpost&ptid=29425&pid=692629


回复

使用道具 举报

5

主题

127

回帖

2967

积分

金牌会员

积分
2967
金钱
2835
HASS币
0
发表于 2025-8-26 18:24:01 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

0

主题

32

回帖

138

积分

注册会员

积分
138
金钱
106
HASS币
0
发表于 2025-8-26 18:43:58 | 显示全部楼层
hungheo 发表于 2025-8-26 18:04
话费和日历都是用的nodered+mqtt搞的,没有用其他插件

电信是论坛这个帖子分享的:https://bbs.hassbian ...

感谢老大回复。我也是刚在论坛里面找到了查询电信话费的帖子:https://bbs.hassbian.com/thread-29129-1-1.html。他家对应的github链接上同时还提供了联通号码的插件。我只有电信号码,所以测试了一下,发现一个问题:只能添加一个手机号,不能添加更多。准备去帖子下面问问是什么原因。

如果能提供日历的nodered流,那就太谢谢了,刚好可以再继续对比学习一下。
回复

使用道具 举报

11

主题

267

回帖

2671

积分

金牌会员

积分
2671
金钱
2388
HASS币
20
 楼主| 发表于 2025-8-26 20:35:31 | 显示全部楼层
本帖最后由 hungheo 于 2025-8-26 20:59 编辑
BBGPPR 发表于 2025-8-26 18:43
感谢老大回复。我也是刚在论坛里面找到了查询电信话费的帖子:https://bbs.hassbian.com/thread-29129-1- ...

我没用他的插件,用docker跑的,docker上可以设置多个号码的
屏幕截图 2025-08-26 205753.png
日历我是nodered+mqtt,有了homeassistant插件,好多都没有用mqtt
所以我就发你一个nodered中function节点内容,输出就是完整的农历内容,剩下的你自己搞呀
const lunarDate = lunar.Lunar.fromDate(new Date());
const year = new Date().getFullYear();
const month = (new Date().getMonth() + 1).toString();
const day = new Date().getDate().toString();
const getHoliday = HolidayUtil.HolidayUtil.getHoliday(year, month, day);
const eightCharString = lunarDate.getEightChar().toString();

const Hour = ['子时', '丑时', '寅时', '卯时', '辰时', '巳时', '午时', '未时', '申时', '酉时', '戌时', '亥时'];
const Quater = ['整', '一刻', '二刻', '三刻'];
const now = new Date();
const hour = now.getHours();
const minute = now.getMinutes();
const Time = Math.floor((hour + 1 + (minute >= 30 ? 0.5 : 0)) / 2) % 12;
const ShiChen = Hour[Time] + (Quater[Math.floor(minute / 15)] || '');

const lunarData = {
    Lunar: {
        LYear: lunarDate.getYearShengXiaoByLiChun(),
        LMonth: lunarDate.getMonthInChinese(),
        LDay: lunarDate.getDayInChinese(),
        TimeInGanZhi: lunarDate.getTimeInGanZhi(),
        Week: lunarDate.getWeekInChinese(),
        LJie: lunarDate.getOtherFestivals(),
        TianGanYear: lunarDate.getYearInGanZhiExact(),
        TianGanMonth: lunarDate.getMonthInGanZhiExact(),
        TianGanDay: lunarDate.getDayInGanZhiExact(),
        DayLu: lunarDate.getDayLu(),
        JieQi: lunarDate.getPrevJieQi(true),
        Xiu: lunarDate.getXiu(),
        Animal: lunarDate.getAnimal(),
        XinLuck: lunarDate.getXiuLuck(),
        Zheng: lunarDate.getZheng(),
        Gong: lunarDate.getGong(),
        PengZuGan: lunarDate.getPengZuGan(),
        PengZuZhi: lunarDate.getPengZuZhi(),
        XiShen: lunarDate.getDayPositionXiDesc(),
        YangGui: lunarDate.getDayPositionYangGuiDesc(),
        YinGui: lunarDate.getDayPositionYinGuiDesc(),
        FuShen: lunarDate.getDayPositionFuDesc(),
        CaiShen: lunarDate.getDayPositionCaiDesc(),
        TaiShen: lunarDate.getDayPositionTai(),
        ChongSha: '冲' + lunarDate.getDayChongDesc() + ' 煞' + lunarDate.getDaySha(),
        WinXingNaYear: lunarDate.getYearNaYin(),
        WuxingNaMonth: lunarDate.getMonthNaYin(),
        WuxingNaDay: lunarDate.getDayNaYin(),
        WuXingZhiXing: lunarDate.getDayNaYin() + ' ' + lunarDate.getZhiXing(),
        BaZi: eightCharString,
        Yi: lunarDate.getDayYi(),
        Ji: lunarDate.getDayJi(),
        JiShen: lunarDate.getDayJiShen(),
        XiongShen: lunarDate.getDayXiongSha(),
        YueXiang: lunarDate.getYueXiang(),
    },
    HolidayUtil: {
        JiaQi: getHoliday,
    }
};
msg.topic = "state";
msg.payload = ShiChen;
msg.data = {
    "Lunar": lunarData.Lunar.LMonth + "月" + lunarData.Lunar.LDay,
    "Week": "星期" + lunarData.Lunar.Week,
    "NianGanZhi": lunarData.Lunar.TianGanYear + lunarData.Lunar.LYear + "年",
    "YueGanZhi": lunarData.Lunar.TianGanMonth + "月",
    "RiGanZhi": lunarData.Lunar.TianGanDay + "日",
    "RiLu": lunarData.Lunar.DayLu,
    "JieQi": lunarData.Lunar.JieQi._p.name,
    "DongFangXingXiu": lunarData.Lunar.Gong + "方" + lunarData.Lunar.Xiu + lunarData.Lunar.Zheng + lunarData.Lunar.Animal + "-" + lunarData.Lunar.XinLuck,
    "PengZuGan": lunarData.Lunar.PengZuGan,
    "PengZuZhi": lunarData.Lunar.PengZuZhi,
    "XiShen": lunarData.Lunar.XiShen,
    "YangGui": lunarData.Lunar.YangGui,
    "YinGui": lunarData.Lunar.YinGui,
    "FuShen": lunarData.Lunar.FuShen,
    "CaiShen": lunarData.Lunar.CaiShen,
    "TaiShen": lunarData.Lunar.TaiShen,
    "ChongSha": lunarData.Lunar.ChongSha,
    "WuXingNaYin": lunarData.Lunar.WinXingNaYear + " " + lunarData.Lunar.WuxingNaMonth + " " + lunarData.Lunar.WuxingNaDay,
    "WuXingRi": lunarData.Lunar.WuXingZhiXing + "执位",
    "BaZi": lunarData.Lunar.BaZi,
    "Yi": lunarData.Lunar.Yi.join('. '),
    "Ji": lunarData.Lunar.Ji.join('. '),
    "JiShen": lunarData.Lunar.JiShen.join('. '),
    "XiongShen": lunarData.Lunar.XiongShen.join('. '),
    "YueXiang": lunarData.Lunar.YueXiang + "月",
    "JiaQi": (lunarData.HolidayUtil.JiaQi === null) ? "工作日" : (lunarData.HolidayUtil.JiaQi._p.name || "工作日"),
    "ShiChen": ShiChen
};
return msg

屏幕截图 2025-08-26 205753.png
回复

使用道具 举报

0

主题

32

回帖

138

积分

注册会员

积分
138
金钱
106
HASS币
0
发表于 2025-8-26 20:59:32 | 显示全部楼层
hungheo 发表于 2025-8-26 20:35
我没用他的插件,用docker跑的,docker上可以设置多个号码的

日历我是nodered+mqtt,有了homeassistant插 ...

感谢支援。我这个小白啥都不懂,慢慢摸索中。目前title已经搞定。之前还有很多出错的问题,后来才知道是因为很多自定义的虚拟按钮没有添加造成的,知道了原因后边的就相对容易一些了,毕竟你的代码真的是很不错,哈哈!
回复

使用道具 举报

11

主题

267

回帖

2671

积分

金牌会员

积分
2671
金钱
2388
HASS币
20
 楼主| 发表于 2025-8-26 21:05:31 | 显示全部楼层
BBGPPR 发表于 2025-8-26 20:59
感谢支援。我这个小白啥都不懂,慢慢摸索中。目前title已经搞定。之前还有很多出错的问题,后来才知道是 ...

慢慢来,我也是小白,大家多交流
里面确实有些虚拟按钮,脚本和统计传感器
回复

使用道具 举报

0

主题

1

回帖

21

积分

新手上路

积分
21
金钱
20
HASS币
0
发表于 2025-8-26 23:24:36 | 显示全部楼层
一直更新的博主不多
回复

使用道具 举报

0

主题

14

回帖

155

积分

注册会员

积分
155
金钱
141
HASS币
0
发表于 2025-8-27 14:41:08 | 显示全部楼层
这个的看看
回复

使用道具 举报

0

主题

32

回帖

138

积分

注册会员

积分
138
金钱
106
HASS币
0
发表于 2025-8-27 22:00:15 | 显示全部楼层
本帖最后由 BBGPPR 于 2025-8-27 22:04 编辑
hungheo 发表于 2025-8-26 21:05
慢慢来,我也是小白,大家多交流
里面确实有些虚拟按钮,脚本和统计传感器 ...

发现了一个小bug,我用AI找了一下解决办法。
            extra_styles: |
              #container::before {
                content: " ";
                width: 100%;
                height: 140px;
                align-self: end;
                border-radius: var(--ha-card-border-radius);
                background: var(--h-rgb-white,var(--disabled-color));
                box-shadow: var(--ha-card-box-shadow);
                position: absolute;
                z-index: 0;
                overflow: visible;
              }
上面这段代码同时使用了position: absolute;和align-self: end;,在某些特定情况下会出现无法对齐的情况,尤其是苹果系统下,排版会混乱。解决办法是:把align-self: end;改成right: 10px; /* 或 left/bottom/top 等 */,排版就没问题了。
在老大的代码这里我换成了:bottom: 0px;这段代码来替换align-self: end;

评分

参与人数 1金钱 +10 收起 理由
hungheo + 10 感谢楼主分享!

查看全部评分

回复

使用道具 举报

11

主题

267

回帖

2671

积分

金牌会员

积分
2671
金钱
2388
HASS币
20
 楼主| 发表于 2025-8-27 22:11:17 | 显示全部楼层
BBGPPR 发表于 2025-8-27 22:00
发现了一个小bug,我用AI找了一下解决办法。
            extra_styles: |
              #container::bef ...

很有可能呀,我用的是Android和chrome浏览器,IOS没有试过
如果要保险一点的话,再套个button card就不会了

用extra_styles其实要复杂一点,我是觉得不想套太多层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian ( 晋ICP备17001384号-1 )

GMT+8, 2025-9-8 22:06 , Processed in 0.137476 second(s), 16 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表