37 Commits

Author SHA1 Message Date
xiaoshi
da16f27cf2 Update xiaoshi-pad-card.js 2025-11-28 12:15:39 +08:00
xiaoshi
df6a678043 Update xiaoshi-device-ha-info-card.js 2025-11-28 12:15:25 +08:00
xiaoshi
82930f4e41 Update xiaoshi-device-update-card.js 2025-11-28 12:15:06 +08:00
xiaoshi
4a2ffb628d Create xiaoshi-device-consumables-button2.js 2025-11-28 00:31:54 +08:00
xiaoshi
3d5f6028c2 Update xiaoshi-device-todo-card.js 2025-11-27 21:10:40 +08:00
xiaoshi
765b0a1367 Update README.md 2025-11-27 15:50:13 +08:00
xiaoshi
df66608d7f Update xiaoshi-pad-card.js 2025-11-27 15:47:56 +08:00
xiaoshi
6ed3bca2cc Create xiaoshi-device-consumables-button.js 2025-11-27 15:47:20 +08:00
xiaoshi
f1d0b52bd7 Update xiaoshi-pad-card.js 2025-11-27 15:46:51 +08:00
xiaoshi
528eaf1cd1 Create xiaoshi-device-ha-info-card.js 2025-11-27 15:46:02 +08:00
xiaoshi
59268a91f8 Update xiaoshi-device-consumables-card.js 2025-11-27 15:45:29 +08:00
xiaoshi
f768186379 Update xiaoshi-device-balance-card.js 2025-11-26 14:21:37 +08:00
xiaoshi
2371475eca Update xiaoshi-device-consumables-card.js 2025-11-26 14:18:03 +08:00
xiaoshi
befca5ece5 Update xiaoshi-pad-card.js 2025-11-26 14:13:44 +08:00
xiaoshi
24848db29b Update xiaoshi-device-consumables-card.js 2025-11-26 14:13:25 +08:00
xiaoshi
be232dc056 Update README.md 2025-11-26 13:06:57 +08:00
xiaoshi
96fb548262 Update README.md 2025-11-26 13:06:09 +08:00
xiaoshi
16831e5102 Update xiaoshi-pad-card.js 2025-11-26 13:04:30 +08:00
xiaoshi
b05f7de548 Update xiaoshi-device-consumables-card.js 2025-11-26 13:04:02 +08:00
xiaoshi
d8d4389549 Update xiaoshi-device-update-card.js 2025-11-26 12:07:35 +08:00
xiaoshi
bca500c945 Update xiaoshi-device-balance-card.js 2025-11-26 11:56:44 +08:00
xiaoshi
5f36835adb Update xiaoshi-pad-card.js 2025-11-26 01:00:55 +08:00
xiaoshi
05d083c259 Update README.md 2025-11-26 00:59:56 +08:00
xiaoshi
3738b0b092 Update xiaoshi-device-consumables-card.js 2025-11-25 19:51:37 +08:00
xiaoshi
87e9e68b79 Update xiaoshi-pad-card.js 2025-11-25 19:22:55 +08:00
xiaoshi
7ddd378b9a Create xiaoshi-device-consumables-card.js 2025-11-25 19:22:06 +08:00
xiaoshi
23b6e5b8a3 Update xiaoshi-device-balance-card.js 2025-11-25 19:15:23 +08:00
xiaoshi
4067518d0d Update xiaoshi-device-todo-card.js 2025-11-25 18:30:32 +08:00
xiaoshi
53e06aacf7 Update xiaoshi-device-todo-card.js 2025-11-25 13:35:29 +08:00
xiaoshi
9a59c2bb90 Create xiaoshi-device-todo-card.js 2025-11-25 13:34:43 +08:00
xiaoshi
0ae5851361 Update xiaoshi-pad-card.js 2025-11-25 13:34:07 +08:00
xiaoshi
a17033c0f0 Update README.md 2025-11-25 13:33:09 +08:00
xiaoshi
44a1d81265 Update xiaoshi-pad-card.js 2025-11-24 15:34:14 +08:00
xiaoshi
2de0668d37 Update xiaoshi-device-balance-card.js 2025-11-24 15:33:59 +08:00
xiaoshi
a03a54663b Update README.md 2025-11-24 14:59:22 +08:00
xiaoshi
6efa2864cc Update xiaoshi-pad-card.js 2025-11-24 14:56:54 +08:00
xiaoshi
f4a37ff29c Update xiaoshi-device-balance-card.js 2025-11-24 14:55:54 +08:00
9 changed files with 8447 additions and 86 deletions

View File

@@ -24,21 +24,76 @@ max: 80 # 当前地区最大值
mode: 湿度 # 【温度】或者【湿度】
~~~
## 功能2HA版本更新卡(手机平板端通用)
## 功能2HA信息卡(手机平板端通用)
**引用示例**
~~~
type: custom:xiaoshi-update-card
width: 100p%
width: 100%
skip_updates: false #是否包含已跳过的更新
theme: on
~~~
## 功能3HA离线设备卡(手机平板端通用)
**引用示例**
~~~
type: custom:xiaoshi-offline-card
width: 320px
exclude_devices:
- *设备*
exclude_entities:
- *shiti*
~~~
## 功能3电话信息余额卡(手机平板端通用)
**引用示例**
~~~
type: custom:xiaoshi-balance-card
name: 电话余额信息
width: 100%
theme: on
entities:
- entity_id: sensor.999
attribute: null
overrides:
icon: ""
name: ""
unit_of_measurement: ""
warning: ""
- entity_id: input_boolean.777
attribute: friendly_name
overrides:
name: ""
icon: ""
unit_of_measurement: ""
warning: "99"
~~~
## 功能4待办事项卡(手机平板端通用)
**引用示例**
~~~
type: custom:xiaoshi-todo-card
width: 100%
theme: on
entities:
- todo.kuai_di
- todo.ji_shi_ben
~~~
## 功能5耗材信息卡片(手机平板端通用)
**引用示例**
~~~
type: custom:xiaoshi-consumables-card
width: 100%
global_warning: <8
columns: "2"
entities:
- entity_id: input_text.aaa
overrides:
name: 奥斯卡德拉萨达实打实实打实
unit_of_measurement: "%"
warning: <10
conversion: "*2"
icon: ""
- entity_id: input_text.aaa1
- entity_id: input_text.aaa2
- entity_id: input_text.aaa3
- entity_id: input_text.aaa4
- entity_id: input_text.aaa5
- entity_id: input_text.aaa6
- entity_id: input_text.aaa7
~~~

View File

@@ -91,6 +91,7 @@ class XiaoshiBalanceCardEditor extends LitElement {
align-items: center;
gap: 8px;
flex: 1;
justify-content: space-between;
}
.entity-details {
@@ -146,10 +147,14 @@ class XiaoshiBalanceCardEditor extends LitElement {
margin-bottom: 8px;
font-size: 12px;
color: #000;
justify-content: space-between;
}
.attribute-config {
margin-top: 4px;
display: flex;
flex-direction: column;
gap: 4px;
}
.attribute-input {
@@ -161,6 +166,32 @@ class XiaoshiBalanceCardEditor extends LitElement {
box-sizing: border-box;
}
.override-config {
display: flex;
align-items: center;
gap: 4px;
margin-top: 2px;
}
.override-checkbox {
margin-right: 4px;
}
.override-input {
flex: 1;
padding: 2px 6px;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 11px;
box-sizing: border-box;
}
.override-label {
font-size: 11px;
color: #666;
white-space: nowrap;
}
.remove-btn {
background: none;
border: none;
@@ -206,16 +237,18 @@ class XiaoshiBalanceCardEditor extends LitElement {
</div>
<div class="form-group">
<label>预警值:低于此值的金额将显示为红色</label>
<label>全局预警条件:当任一实体满足此条件时触发预警</label>
<input
type="number"
type="text"
@change=${this._entityChanged}
.value=${this.config.warning !== undefined ? this.config.warning : 20}
name="warning"
placeholder="默认20"
min="0"
step="0.01"
.value=${this.config.global_warning || ''}
name="global_warning"
placeholder="如: >10, <=5, ==on, ==off, =='hello world'"
/>
<div class="help-text">
全局预警条件:当任一实体满足此条件时,该实体显示为红色预警状态<br>
优先级:明细预警 > 全局预警 > 无预警
</div>
</div>
<div class="form-group">
@@ -249,11 +282,11 @@ class XiaoshiBalanceCardEditor extends LitElement {
@click=${() => this._toggleEntity(entity.entity_id)}
>
<div class="entity-info">
<ha-icon icon="${entity.attributes.icon || 'mdi:help-circle'}"></ha-icon>
<div class="entity-details">
<div class="entity-name">${entity.attributes.friendly_name || entity.entity_id}</div>
<div class="entity-id">${entity.entity_id}</div>
</div>
<ha-icon icon="${entity.attributes.icon || 'mdi:help-circle'}"></ha-icon>
</div>
${this.config.entities && this.config.entities.some(e => e.entity_id === entity.entity_id) ?
html`<ha-icon icon="mdi:check" class="check-icon"></ha-icon>` : ''}
@@ -273,8 +306,8 @@ class XiaoshiBalanceCardEditor extends LitElement {
return html`
<div class="selected-entity-config">
<div class="selected-entity">
<ha-icon icon="${entity?.attributes.icon || 'mdi:help-circle'}"></ha-icon>
<span>${entity?.attributes.friendly_name || entityConfig.entity_id}</span>
<ha-icon icon="${entity?.attributes.icon || 'mdi:help-circle'}"></ha-icon>
<button class="remove-btn" @click=${() => this._removeEntity(index)}>
<ha-icon icon="mdi:close"></ha-icon>
</button>
@@ -287,6 +320,78 @@ class XiaoshiBalanceCardEditor extends LitElement {
placeholder="留空使用实体状态,或输入属性名"
class="attribute-input"
/>
<div class="override-config">
<input
type="checkbox"
class="override-checkbox"
@change=${(e) => this._updateEntityOverride(index, 'icon', e.target.checked)}
.checked=${entityConfig.overrides?.icon !== undefined}
/>
<span class="override-label">图标:</span>
<input
type="text"
class="override-input"
@change=${(e) => this._updateEntityOverrideValue(index, 'icon', e.target.value)}
.value=${entityConfig.overrides?.icon || ''}
placeholder="mdi:icon-name"
?disabled=${entityConfig.overrides?.icon === undefined}
/>
</div>
<div class="override-config">
<input
type="checkbox"
class="override-checkbox"
@change=${(e) => this._updateEntityOverride(index, 'name', e.target.checked)}
.checked=${entityConfig.overrides?.name !== undefined}
/>
<span class="override-label">名称:</span>
<input
type="text"
class="override-input"
@change=${(e) => this._updateEntityOverrideValue(index, 'name', e.target.value)}
.value=${entityConfig.overrides?.name || ''}
placeholder="自定义名称"
?disabled=${entityConfig.overrides?.name === undefined}
/>
</div>
<div class="override-config">
<input
type="checkbox"
class="override-checkbox"
@change=${(e) => this._updateEntityOverride(index, 'unit_of_measurement', e.target.checked)}
.checked=${entityConfig.overrides?.unit_of_measurement !== undefined}
/>
<span class="override-label">单位:</span>
<input
type="text"
class="override-input"
@change=${(e) => this._updateEntityOverrideValue(index, 'unit_of_measurement', e.target.value)}
.value=${entityConfig.overrides?.unit_of_measurement || ''}
placeholder="自定义单位"
?disabled=${entityConfig.overrides?.unit_of_measurement === undefined}
/>
</div>
<div class="override-config">
<input
type="checkbox"
class="override-checkbox"
@change=${(e) => this._updateEntityOverride(index, 'warning', e.target.checked)}
.checked=${entityConfig.overrides?.warning !== undefined}
/>
<span class="override-label">预警:</span>
<input
type="text"
class="override-input"
@change=${(e) => this._updateEntityOverrideValue(index, 'warning', e.target.value)}
.value=${entityConfig.overrides?.warning || ''}
placeholder="如: >10, <=5, ==on, ==off, =='hello world'"
?disabled=${entityConfig.overrides?.warning === undefined}
/>
</div>
</div>
</div>
`;
@@ -294,10 +399,13 @@ class XiaoshiBalanceCardEditor extends LitElement {
` : ''}
</div>
<div class="help-text">
搜索并选择要显示的设备余额实体,支持多选。每个实体可以配置要显示的属性<br>
留空:显示实体状态<br>
输入属性名:显示指定属性的值<br>
单位会自动从实体的 unit_of_measurement 属性获取,默认为"元"
搜索并选择要显示的设备余额实体,支持多选。每个实体可以配置:<br>
属性名:留空使用实体状态,或输入属性名<br>
名称重定义:勾选后可自定义显示名称<br>
图标重定义:勾选后可自定义图标(如 mdi:phone<br>
• 单位重定义:勾选后可自定义单位(如 元、$、kWh 等)<br>
• 预警条件:勾选后设置预警条件,支持 >10, >=10, <10, <=10, ==10, ==on, ==off, =="hello world" 等<br>
• 未勾选重定义时,将使用实体的原始属性值
</div>
</div>
</div>
@@ -358,7 +466,12 @@ class XiaoshiBalanceCardEditor extends LitElement {
newEntities = currentEntities.filter(e => e.entity_id !== entityId);
} else {
// 添加实体
newEntities = [...currentEntities, { entity_id: entityId, attribute: null }];
const newEntity = {
entity_id: entityId,
overrides: undefined
};
// 只有在明确指定属性时才添加 attribute 字段
newEntities = [...currentEntities, newEntity];
}
this.config = {
@@ -398,9 +511,79 @@ class XiaoshiBalanceCardEditor extends LitElement {
const newEntities = [...currentEntities];
if (newEntities[index]) {
const updatedEntity = { ...newEntities[index] };
if (attributeValue.trim()) {
// 只有当属性值不为空时才设置 attribute 字段
updatedEntity.attribute = attributeValue.trim();
} else {
// 如果属性值为空,则移除 attribute 字段
delete updatedEntity.attribute;
}
newEntities[index] = updatedEntity;
}
this.config = {
...this.config,
entities: newEntities
};
this.dispatchEvent(new CustomEvent('config-changed', {
detail: { config: this.config },
bubbles: true,
composed: true
}));
this.requestUpdate();
}
_updateEntityOverride(index, overrideType, enabled) {
const currentEntities = this.config.entities || [];
const newEntities = [...currentEntities];
if (newEntities[index]) {
const overrides = { ...newEntities[index].overrides };
if (enabled) {
// 启用覆盖,设置默认值
overrides[overrideType] = '';
} else {
// 禁用覆盖,删除该属性
delete overrides[overrideType];
}
newEntities[index] = {
...newEntities[index],
attribute: attributeValue.trim() || null
overrides: Object.keys(overrides).length > 0 ? overrides : undefined
};
}
this.config = {
...this.config,
entities: newEntities
};
this.dispatchEvent(new CustomEvent('config-changed', {
detail: { config: this.config },
bubbles: true,
composed: true
}));
this.requestUpdate();
}
_updateEntityOverrideValue(index, overrideType, value) {
const currentEntities = this.config.entities || [];
const newEntities = [...currentEntities];
if (newEntities[index] && newEntities[index].overrides && newEntities[index].overrides[overrideType] !== undefined) {
const overrides = { ...newEntities[index].overrides };
overrides[overrideType] = value.trim();
newEntities[index] = {
...newEntities[index],
overrides: overrides
};
}
@@ -746,14 +929,39 @@ class XiaoshiBalanceCard extends LitElement {
// 尝试从属性中获取单位
if (attributes.unit_of_measurement) {
unit = attributes.unit_of_measurement;
} else {
// 如果实体没有单位,则不显示单位
unit = '';
}
// 应用属性重定义
let friendlyName = attributes.friendly_name || entityId;
let icon = attributes.icon || 'mdi:help-circle';
let warningThreshold = undefined;
// 应用用户自定义的重定义
if (entityConfig.overrides) {
if (entityConfig.overrides.name !== undefined && entityConfig.overrides.name !== '') {
friendlyName = entityConfig.overrides.name;
}
if (entityConfig.overrides.icon !== undefined && entityConfig.overrides.icon !== '') {
icon = entityConfig.overrides.icon;
}
if (entityConfig.overrides.unit_of_measurement !== undefined && entityConfig.overrides.unit_of_measurement !== '') {
unit = entityConfig.overrides.unit_of_measurement;
}
if (entityConfig.overrides.warning !== undefined && entityConfig.overrides.warning !== '') {
warningThreshold = entityConfig.overrides.warning; // 保持原始字符串
}
}
balanceData.push({
entity_id: entityId,
friendly_name: attributes.friendly_name || entityId,
friendly_name: friendlyName,
value: value,
unit: unit,
icon: attributes.icon || 'mdi:help-circle'
icon: icon,
warning_threshold: warningThreshold
});
}
@@ -781,6 +989,54 @@ class XiaoshiBalanceCard extends LitElement {
}
}
_evaluateWarningCondition(value, condition) {
if (!condition) return false;
// 解析条件字符串,支持操作符后可能有空格
const match = condition.match(/^(>=|<=|>|<|==|!=)\s*(.+)$/);
if (!match) return false;
const operator = match[1];
let compareValue = match[2].trim();
// 移除比较值两端的引号(如果有的话)
if ((compareValue.startsWith('"') && compareValue.endsWith('"')) ||
(compareValue.startsWith("'") && compareValue.endsWith("'"))) {
compareValue = compareValue.slice(1, -1);
}
// 尝试将值转换为数字
const numericValue = parseFloat(value);
const numericCompare = parseFloat(compareValue);
// 如果两个值都是数字,进行数值比较
if (!isNaN(numericValue) && !isNaN(numericCompare)) {
switch (operator) {
case '>': return numericValue > numericCompare;
case '>=': return numericValue >= numericCompare;
case '<': return numericValue < numericCompare;
case '<=': return numericValue <= numericCompare;
case '==': return numericValue === numericCompare;
case '!=': return numericValue !== numericCompare;
}
}
// 字符串比较(用于 ==on, ==off, ==66 66 等)
const stringValue = String(value);
const stringCompare = compareValue;
switch (operator) {
case '==': return stringValue === stringCompare;
case '!=': return stringValue !== stringCompare;
case '>': return stringValue > stringCompare;
case '>=': return stringValue >= stringCompare;
case '<': return stringValue < stringCompare;
case '<=': return stringValue <= stringCompare;
}
return false;
}
render() {
if (!this.hass) {
@@ -808,9 +1064,18 @@ class XiaoshiBalanceCard extends LitElement {
html`<div class="no-devices">请配置余额实体</div>` :
html`
${this._oilPriceData.map(balanceData => {
const warningThreshold = this.config.warning || 20;
const numericValue = parseFloat(balanceData.value);
const isWarning = !isNaN(numericValue) && numericValue < warningThreshold;
// 明细预警优先级最高
let isWarning = false;
// 首先检查明细预警,如果存在且满足条件,直接设为预警状态
if (balanceData.warning_threshold && balanceData.warning_threshold.trim() !== '') {
isWarning = this._evaluateWarningCondition(balanceData.value, balanceData.warning_threshold);
} else {
// 只有在没有明细预警时才检查全局预警
if (this.config.global_warning && this.config.global_warning.trim() !== '') {
isWarning = this._evaluateWarningCondition(balanceData.value, this.config.global_warning);
}
}
return html`
<div class="device-item" @click=${() => this._handleEntityClick(balanceData)}>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1305
xiaoshi-device-todo-card.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -68,6 +68,19 @@ class XiaoshiUpdateCardEditor extends LitElement {
</select>
</div>
<div class="form-group">
<label>
<input
type="checkbox"
@change=${this._entityChanged}
.checked=${this.config.skip_updates !== false}
name="skip_updates"
/>
包含已跳过的更新
</label>
<div class="help-text">如果勾选,将包含标记为跳过的版本更新</div>
</div>
</div>
@@ -75,10 +88,17 @@ class XiaoshiUpdateCardEditor extends LitElement {
}
_entityChanged(e) {
const { name, value } = e.target;
if (!value && name !== 'theme' && name !== 'width') return;
const { name, value, type, checked } = e.target;
let finalValue = value;
let finalValue;
// 处理复选框
if (type === 'checkbox') {
finalValue = checked;
} else {
if (!value && name !== 'theme' && name !== 'width') return;
finalValue = value;
}
// 处理不同字段的默认值
if (name === 'width') {
@@ -139,7 +159,6 @@ export class XiaoshiUpdateCard extends LitElement {
align-items: center;
padding: 16px;
background: var(--bg-color, #fff);
border-radius: 12px;
}
@@ -169,7 +188,6 @@ export class XiaoshiUpdateCard extends LitElement {
display: flex;
align-items: center;
justify-content: center;
}
/*标题统计数字*/
@@ -251,7 +269,8 @@ export class XiaoshiUpdateCard extends LitElement {
align-items: center;
padding: 0px;
border-bottom: 1px solid rgb(150,150,150,0.2);
margin: 0 24px 8px 32px;
margin: 0 32px 4px 32px;
padding: 4px 0 0 0;
}
/*设备、实体明细背景*/
@@ -259,7 +278,7 @@ export class XiaoshiUpdateCard extends LitElement {
flex: 1;
overflow-y: auto;
min-height: 0;
padding: 0 0 8px 0;
padding: 4px 0;
}
.device-icon {
@@ -274,7 +293,7 @@ export class XiaoshiUpdateCard extends LitElement {
.device-name {
font-weight: 500;
color: var(--fg-color, #000);
margin-bottom: 4px;
margin: 2px 0;
}
.device-entity {
@@ -286,7 +305,6 @@ export class XiaoshiUpdateCard extends LitElement {
.device-details {
font-size: 10px;
color: var(--fg-color, #000);
margin-top: 4px;
}
.device-last-seen {
@@ -307,13 +325,13 @@ export class XiaoshiUpdateCard extends LitElement {
.no-devices {
text-align: center;
padding: 8px 0 0 0;
padding: 8px 0;
color: var(--fg-color, #000);
}
.loading {
text-align: center;
padding: 0px;
padding: 10px 0px;
color: var(--fg-color, #000);
}
@@ -389,12 +407,12 @@ export class XiaoshiUpdateCard extends LitElement {
/* 备份信息独立容器 */
.backup-info {
padding: 4px 0 4px 16px;
margin: 0 16px 0 30px;
border-bottom: 1px solid rgb(150,150,150,0.2);
margin: 0 32px 8px 32px;
display: grid;
grid-template-columns: auto auto auto;
gap: 4px;
align-items: center;
border-bottom: 1px solid rgb(150,150,150,0.2);
}
`;
}
@@ -449,6 +467,17 @@ export class XiaoshiUpdateCard extends LitElement {
}
}
_handleEntityClick(entity) {
navigator.vibrate(50);
// 点击实体时打开实体详情页
if (entity.entity_id) {
// 使用您建议的第一种方式
const evt = new Event('hass-more-info', { composed: true });
evt.detail = { entityId: entity.entity_id };
this.dispatchEvent(evt);
}
}
async _loadUpdateData() {
if (!this.hass) return;
@@ -459,19 +488,10 @@ export class XiaoshiUpdateCard extends LitElement {
const haUpdates = [];
const otherUpdates = [];
// 获取update.开头的实体更新信息
try {
const entities = Object.values(this.hass.states);
const skipUpdates = this.config.skip_updates !== false; // 默认为true
entities.forEach(entity => {
// 筛选以update.开头的实体
@@ -484,6 +504,15 @@ export class XiaoshiUpdateCard extends LitElement {
attributes.installed_version &&
attributes.latest_version !== attributes.installed_version) {
// 如果不跳过更新检查skipped_version属性
if (!skipUpdates) {
const skippedVersion = attributes.skipped_version;
// 如果skipped_version不为null且等于latest_version则跳过此更新
if (skippedVersion !== null && skippedVersion === attributes.latest_version) {
return; // 跳过此更新
}
}
const updateData = {
name: attributes.friendly_name || entity.entity_id.replace('update.', ''),
current_version: attributes.installed_version,
@@ -493,7 +522,8 @@ export class XiaoshiUpdateCard extends LitElement {
entity_id: entity.entity_id,
title: attributes.title || '',
release_url: attributes.release_url || '',
entity_picture: attributes.entity_picture || ''
entity_picture: attributes.entity_picture || '',
skipped_version: attributes.skipped_version || null
};
// 检查是否为home_assistant开头的实体
@@ -521,14 +551,10 @@ export class XiaoshiUpdateCard extends LitElement {
this._loading = false;
}
_handleRefresh() {
this._loadUpdateData();
navigator.vibrate(50);
}
_handleUpdateClick(update) {
navigator.vibrate(50);
@@ -560,6 +586,10 @@ export class XiaoshiUpdateCard extends LitElement {
if (confirmed) {
this._executeUpdate(update);
// 延迟3秒后刷新数据给更新操作足够时间完成
setTimeout(() => {
this._loadUpdateData();
}, 1000);
}
}
@@ -765,9 +795,6 @@ export class XiaoshiUpdateCard extends LitElement {
return html`${backupElements}`;
}
render() {
if (!this.hass) {
return html`<div class="loading">等待Home Assistant连接...</div>`;
@@ -804,19 +831,9 @@ export class XiaoshiUpdateCard extends LitElement {
${this._renderHAVersionInfo()}
</div>
<!-- 备份信息 -->
<div class="section-divider">
<div class="section-title">
<span> • 备份信息</span>
</div>
</div>
<div class="backup-info">
${this._renderBackupInfo()}
</div>
<div class="devices-list">
${this._loading ?
html`<div class="loading">加载中...</div>` :
html`<div class="loading">HA版本信息加载中...</div>` :
(this._haUpdates.length === 0 && this._otherUpdates.length === 0) ?
html`<div class="no-devices">✅ 所有组件都是最新版本</div>` :
@@ -829,7 +846,7 @@ export class XiaoshiUpdateCard extends LitElement {
</div>
</div>
${this._haUpdates.map(update => html`
<div class="device-item">
<div class="device-item" @click=${() => this._handleEntityClick(update)}>
<div class="device-icon">
<ha-icon icon="${update.icon}"></ha-icon>
</div>
@@ -837,6 +854,7 @@ export class XiaoshiUpdateCard extends LitElement {
<div class="device-name">${update.name}</div>
<div class="device-details">
当前版本: ${update.current_version} → 最新版本: ${update.latest_version}
${update.skipped_version ? html`<span style="color: #ff9800;"> 已跳过版本: ${update.skipped_version}</span>` : ''}
</div>
</div>
<div class="device-last-seen" @click=${(e) => this._handleConfirmUpdate(update, e)}>
@@ -848,12 +866,12 @@ export class XiaoshiUpdateCard extends LitElement {
${this._otherUpdates.length > 0 ? html`
<div class="section-divider">
<div class="section-title">
<span> • 加载项、卡片更新</span>
<span> • HACS更新</span>
<span class="section-count ${this._otherUpdates.length > 0 ? 'non-zero' : 'zero'}">${this._otherUpdates.length}</span>
</div>
</div>
${this._otherUpdates.map(update => html`
<div class="device-item">
<div class="device-item" @click=${() => this._handleEntityClick(update)}>
<div class="device-icon">
<ha-icon icon="${update.icon}"></ha-icon>
</div>
@@ -861,6 +879,7 @@ export class XiaoshiUpdateCard extends LitElement {
<div class="device-name">${update.name}</div>
<div class="device-details">
当前版本: ${update.current_version} → 最新版本: ${update.latest_version}
${update.skipped_version ? html`<span style="color: #ff9800;"> 已跳过版本: ${update.skipped_version}</span>` : ''}
</div>
</div>
<div class="device-last-seen" @click=${(e) => this._handleConfirmUpdate(update, e)}>
@@ -870,8 +889,18 @@ export class XiaoshiUpdateCard extends LitElement {
`)}\n ` : ''}
`
}
</div>
</ha-card>
<!-- 备份信息 -->
<div class="section-divider">
<div class="section-title">
<span> • 备份信息</span>
</div>
</div>
<div class="backup-info">
${this._renderBackupInfo()}
</div>
</ha-card>
`;
}

View File

@@ -1,10 +1,14 @@
console.info("%c 消逝卡-平板端 \n%c v 0.0.5 ", "color: red; font-weight: bold; background: black", "color: white; font-weight: bold; background: black");
console.info("%c 消逝卡-平板端 \n%c v 0.1.4 ", "color: red; font-weight: bold; background: black", "color: white; font-weight: bold; background: black");
const loadCards = async () => {
await import('./xiaoshi-pad-grid-card.js');
await import('./xiaoshi-device-balance-card.js');
await import('./xiaoshi-device-todo-card.js');
await import('./xiaoshi-device-consumables-card.js');
await import('./xiaoshi-device-consumables-button.js');
await import('./xiaoshi-device-ha-info-card.js');
await import('./xiaoshi-device-update-card.js');
await import('./xiaoshi-device-offline-card.js');
await import('./xiaoshi-device-balance-card.js');
window.customCards = window.customCards || [];
window.customCards.push(...cardConfigs);
@@ -17,15 +21,9 @@ const cardConfigs = [
description: '温度分布、湿度分布'
},
{
type: 'xiaoshi-update-card',
name: '消逝卡HA更新监控卡片',
description: '显示需要更新的组件和版本',
preview: true
},
{
type: 'xiaoshi-offline-card',
name: '消逝卡HA离线设备卡片',
description: '显示所有离线的设备和实体',
type: 'xiaoshi-ha-info-card',
name: '消逝卡HA信息卡片',
description: '消逝卡HA信息卡片',
preview: true
},
{
@@ -33,6 +31,18 @@ const cardConfigs = [
name: '消逝电话余额卡',
description: '消逝电话余额卡',
preview: true
},
{
type: 'xiaoshi-todo-card',
name: '消逝待办事项',
description: '消逝待办事项',
preview: true
},
{
type: 'xiaoshi-consumables-card',
name: '消逝耗材统计',
description: '消逝耗材统计',
preview: true
}
];