diff --git a/xiaoshi-pad-climate-card.js b/xiaoshi-pad-climate-card.js index 24b2613..47a64df 100644 --- a/xiaoshi-pad-climate-card.js +++ b/xiaoshi-pad-climate-card.js @@ -20,7 +20,10 @@ class XiaoshiPadClimateCardEditor extends LitElement { _button2SearchTerms: { type: Object }, _filteredButton2Entities: { type: Object }, _showButton2Lists: { type: Object }, - _availableModes: { type: Object } + _availableModes: { type: Object }, + _modeFilterExpanded: { type: Object }, + _modeFilters: { type: Object }, + _buttonConfigExpanded: { type: Object } }; } @@ -152,6 +155,47 @@ class XiaoshiPadClimateCardEditor extends LitElement { if (this.config.show_water_modes === undefined) { this.config.show_water_modes = this._availableModes.hasWaterModes; } + + // 初始化模式过滤器和展开状态(如果没有配置) + if (!this._modeFilters) { + this._modeFilters = {}; + } + if (!this._modeFilterExpanded) { + this._modeFilterExpanded = {}; + } + + // 从配置中恢复过滤器状态,或者初始化默认值 + if (attrs.hvac_modes && attrs.hvac_modes.length > 0) { + this._modeFilters.hvac_modes = {}; + attrs.hvac_modes.forEach(mode => { + // 配置中只有 false 的项,未配置的默认为 true + this._modeFilters.hvac_modes[mode] = this.config.mode_filters?.hvac_modes?.[mode] === false ? false : true; + }); + } + if (attrs.fan_modes && attrs.fan_modes.length > 0) { + this._modeFilters.fan_modes = {}; + attrs.fan_modes.forEach(mode => { + this._modeFilters.fan_modes[mode] = this.config.mode_filters?.fan_modes?.[mode] === false ? false : true; + }); + } + if (attrs.swing_modes && attrs.swing_modes.length > 0) { + this._modeFilters.swing_modes = {}; + attrs.swing_modes.forEach(mode => { + this._modeFilters.swing_modes[mode] = this.config.mode_filters?.swing_modes?.[mode] === false ? false : true; + }); + } + if (attrs.preset_modes && attrs.preset_modes.length > 0) { + this._modeFilters.preset_modes = {}; + attrs.preset_modes.forEach(mode => { + this._modeFilters.preset_modes[mode] = this.config.mode_filters?.preset_modes?.[mode] === false ? false : true; + }); + } + if (attrs.operation_list && attrs.operation_list.length > 0) { + this._modeFilters.operation_list = {}; + attrs.operation_list.forEach(mode => { + this._modeFilters.operation_list[mode] = this.config.mode_filters?.operation_list?.[mode] === false ? false : true; + }); + } } _onTemperatureSearch(e) { @@ -537,6 +581,214 @@ class XiaoshiPadClimateCardEditor extends LitElement { background-color: #ffebee; color: #c62828; } + + .mode-filter-section { + border: 1px solid #e0e0e0; + border-radius: 6px; + padding: 8px; + margin-top: 8px; + background: rgb(0,0,0); + } + + .mode-filter-header { + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; + padding: 4px 0; + } + + .mode-filter-header:hover { + background: rgb(0,0,0); + border-radius: 4px; + } + + .mode-filter-title { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + font-weight: 500; + color: rgb(250, 250, 250); + } + + .mode-filter-icon { + transition: transform 0.2s ease; + color: rgb(250, 250, 250); + } + + .mode-filter-icon.expanded { + transform: rotate(90deg); + } + + .mode-filter-items { + margin-top: 8px; + padding-left: 12px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + gap: 6px; + } + + .mode-filter-item { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 6px; + border-radius: 4px; + background: transparent; + font-size: 11px; + color: rgb(250, 250, 250); + } + + .mode-filter-item:hover { + background: rgba(0, 0, 0, 0.05); + } + + .mode-filter-item input[type="checkbox"] { + cursor: pointer; + } + + .mode-filter-item label { + cursor: pointer; + font-weight: normal; + margin: 0; + color: rgb(250, 250, 250); + } + + .mode-filter-item-expanded { + display: flex; + flex-direction: column; + gap: 4px; + padding: 4px 6px; + border-radius: 4px; + background: transparent; + font-size: 11px; + color: rgb(250, 250, 250); + } + + .mode-filter-item-expanded:hover { + background: rgba(0, 0, 0, 0.05); + } + + .mode-filter-header-row { + display: flex; + align-items: center; + justify-content: space-between; + } + + .mode-filter-left { + display: flex; + align-items: center; + gap: 6px; + } + + .mode-filter-config { + display: flex; + flex-direction: column; + gap: 4px; + padding-left: 24px; + margin-top: 4px; + } + + .mode-config-row { + display: flex; + align-items: center; + gap: 6px; + font-size: 10px; + } + + .mode-config-row input[type="checkbox"] { + cursor: pointer; + } + + .mode-config-row label { + cursor: pointer; + font-weight: normal; + margin: 0; + font-size: 10px; + color: rgb(250, 250, 250); + } + + .mode-config-input { + width: 100%; + padding: 4px 6px; + border: 1px solid #555; + border-radius: 3px; + background: rgba(0, 0, 0, 0.2); + color: rgb(250, 250, 250); + font-size: 10px; + box-sizing: border-box; + } + + .mode-config-input::placeholder { + color: rgba(250, 250, 250, 0.5); + } + + .mode-config-input:focus { + outline: none; + border-color: #4CAF50; + } + + .button-custom-config { + background: transparent; + border-radius: 6px; + padding: 0px; + margin-bottom: 10px; + } + + .config-toggle-icon { + transition: transform 0.2s ease; + color: rgb(250, 250, 250); + font-size: 16px; + } + + .config-toggle-icon.expanded { + transform: rotate(90deg); + } + + .button-config-items { + display: flex; + flex-direction: column; + gap: 4px; + padding-left: 24px; + margin-top: 4px; + } + + .button-config-row { + display: flex; + align-items: center; + gap: 6px; + font-size: 11px; + } + + .button-config-row label { + font-weight: normal; + margin: 0; + color: rgb(250, 250, 250); + font-size: 10px; + white-space: nowrap; + min-width: 80px; + } + + .button-config-input { + flex: 1; + padding: 4px 6px; + border: 1px solid #555; + border-radius: 3px; + background: rgba(0, 0, 0, 0.2); + color: rgb(250, 250, 250); + font-size: 10px; + box-sizing: border-box; + } + + .button-config-input::placeholder { + color: rgba(250, 250, 250, 0.5); + } + + .button-config-input:focus { + outline: none; + border-color: #4CAF50; + } `; } @@ -621,51 +873,68 @@ class XiaoshiPadClimateCardEditor extends LitElement { ` : ''}
${this._availableModes?.hasHvacModes ? html` -
- - 显示模式按钮 +
+
+ + 显示模式按钮 +
+ ${this._renderModeFilter('hvac_modes', '模式筛选')}
` : ''} ${this._availableModes?.hasFanModes ? html` -
- - 显示风速按钮 +
+
+ + 显示风速按钮 +
+ ${this._renderModeFilter('fan_modes', '风速筛选')}
` : ''} ${this._availableModes?.hasSwingModes ? html` -
- - 显示风向按钮 +
+
+ + 显示风向按钮 +
+ ${this._renderModeFilter('swing_modes', '风向筛选')}
` : ''} ${this._availableModes?.hasPresetModes ? html` -
- - 显示水暖毯模式按钮 +
+
+ + 显示水暖毯模式按钮 +
+ ${this._renderModeFilter('preset_modes', '水暖毯模式筛选')}
` : ''} ${this._availableModes?.hasWaterModes ? html` -
- - 显示热水器模式按钮 +
+
+ + 显示热水器模式按钮 +
+ ${this._renderModeFilter('operation_list', '热水器模式筛选')}
` : ''}
+ +
` : ''} @@ -812,6 +1081,19 @@ class XiaoshiPadClimateCardEditor extends LitElement {
+ ${button ? html` +
+
this._toggleButtonConfig('buttons', index)}> + + 自定义配置 +
+ ${this._buttonConfigExpanded?.buttons?.[index] ? html` +
+ ${this._renderButtonConfig('buttons', index)} +
+ ` : ''} +
+ ` : ''} `)} ${(!this.config.buttons || this.config.buttons.length < 7) ? html`
@@ -871,6 +1153,19 @@ class XiaoshiPadClimateCardEditor extends LitElement {
+ ${button2 ? html` +
+
this._toggleButtonConfig('buttons2', index2)}> + + 自定义配置 +
+ ${this._buttonConfigExpanded?.buttons2?.[index2] ? html` +
+ ${this._renderButtonConfig('buttons2', index2)} +
+ ` : ''} +
+ ` : ''} `)} ${(!this.config.buttons2 || this.config.buttons2.length < 7) ? html`
@@ -1019,6 +1314,34 @@ class XiaoshiPadClimateCardEditor extends LitElement { delete this._showButtonLists[index]; } + // 清理该按钮的配置,并重新索引后面的配置 + if (this.config.button_configs && this.config.button_configs.buttons) { + const newButtonConfigs = {}; + Object.keys(this.config.button_configs.buttons).forEach(key => { + const keyIndex = parseInt(key); + if (keyIndex < index) { + // 保留索引小于被删除按钮的配置 + newButtonConfigs[keyIndex] = this.config.button_configs.buttons[key]; + } else if (keyIndex > index) { + // 将索引大于被删除按钮的配置前移 + newButtonConfigs[keyIndex - 1] = this.config.button_configs.buttons[key]; + } + // 等于的被删除按钮的配置不保留 + }); + + // 更新配置 + if (Object.keys(newButtonConfigs).length > 0) { + this.config.button_configs.buttons = newButtonConfigs; + } else { + // 如果没有配置了,删除整个 buttons 配置 + delete this.config.button_configs.buttons; + // 如果 button_configs 为空,删除整个对象 + if (Object.keys(this.config.button_configs).length === 0) { + delete this.config.button_configs; + } + } + } + this.config = { ...this.config, buttons: buttons.length > 0 ? buttons : undefined @@ -1042,6 +1365,34 @@ class XiaoshiPadClimateCardEditor extends LitElement { delete this._showButton2Lists[index2]; } + // 清理该按钮的配置,并重新索引后面的配置 + if (this.config.button_configs && this.config.button_configs.buttons2) { + const newButtonConfigs = {}; + Object.keys(this.config.button_configs.buttons2).forEach(key => { + const keyIndex = parseInt(key); + if (keyIndex < index2) { + // 保留索引小于被删除按钮的配置 + newButtonConfigs[keyIndex] = this.config.button_configs.buttons2[key]; + } else if (keyIndex > index2) { + // 将索引大于被删除按钮的配置前移 + newButtonConfigs[keyIndex - 1] = this.config.button_configs.buttons2[key]; + } + // 等于的被删除按钮的配置不保留 + }); + + // 更新配置 + if (Object.keys(newButtonConfigs).length > 0) { + this.config.button_configs.buttons2 = newButtonConfigs; + } else { + // 如果没有配置了,删除整个 buttons2 配置 + delete this.config.button_configs.buttons2; + // 如果 button_configs 为空,删除整个对象 + if (Object.keys(this.config.button_configs).length === 0) { + delete this.config.button_configs; + } + } + } + this.config = { ...this.config, buttons2: buttons2.length > 0 ? buttons2 : undefined @@ -1213,6 +1564,364 @@ class XiaoshiPadClimateCardEditor extends LitElement { this._fireEvent(); } + _toggleModeFilter(modeType) { + if (!this._modeFilterExpanded) { + this._modeFilterExpanded = {}; + } + this._modeFilterExpanded[modeType] = !this._modeFilterExpanded[modeType]; + this.requestUpdate(); + } + + _toggleModeItem(modeType, mode) { + if (!this._modeFilters) { + this._modeFilters = {}; + } + if (!this._modeFilters[modeType]) { + this._modeFilters[modeType] = {}; + } + this._modeFilters[modeType][mode] = !this._modeFilters[modeType][mode]; + + // 保存过滤配置到 config,只保存 false 的项 + if (!this.config.mode_filters) { + this.config.mode_filters = {}; + } + if (!this.config.mode_filters[modeType]) { + this.config.mode_filters[modeType] = {}; + } + + // 只设置为 false 的模式,不保存 true 的 + if (this._modeFilters[modeType][mode] === false) { + this.config.mode_filters[modeType][mode] = false; + } else { + delete this.config.mode_filters[modeType][mode]; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _toggleShowName(modeType, mode, show) { + if (!this.config.mode_configs) { + this.config.mode_configs = {}; + } + if (!this.config.mode_configs[modeType]) { + this.config.mode_configs[modeType] = {}; + } + if (!this.config.mode_configs[modeType][mode]) { + this.config.mode_configs[modeType][mode] = {}; + } + + if (show) { + delete this.config.mode_configs[modeType][mode].show_name; + } else { + this.config.mode_configs[modeType][mode].show_name = false; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _updateCustomName(modeType, mode, name) { + if (!this.config.mode_configs) { + this.config.mode_configs = {}; + } + if (!this.config.mode_configs[modeType]) { + this.config.mode_configs[modeType] = {}; + } + if (!this.config.mode_configs[modeType][mode]) { + this.config.mode_configs[modeType][mode] = {}; + } + + if (name) { + this.config.mode_configs[modeType][mode].custom_name = name; + } else { + delete this.config.mode_configs[modeType][mode].custom_name; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _toggleShowIcon(modeType, mode, show) { + if (!this.config.mode_configs) { + this.config.mode_configs = {}; + } + if (!this.config.mode_configs[modeType]) { + this.config.mode_configs[modeType] = {}; + } + if (!this.config.mode_configs[modeType][mode]) { + this.config.mode_configs[modeType][mode] = {}; + } + + if (show) { + delete this.config.mode_configs[modeType][mode].show_icon; + } else { + this.config.mode_configs[modeType][mode].show_icon = false; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _updateCustomIcon(modeType, mode, icon) { + if (!this.config.mode_configs) { + this.config.mode_configs = {}; + } + if (!this.config.mode_configs[modeType]) { + this.config.mode_configs[modeType] = {}; + } + if (!this.config.mode_configs[modeType][mode]) { + this.config.mode_configs[modeType][mode] = {}; + } + + if (icon) { + this.config.mode_configs[modeType][mode].custom_icon = icon; + } else { + delete this.config.mode_configs[modeType][mode].custom_icon; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _toggleButtonConfig(buttonType, index) { + if (!this._buttonConfigExpanded) { + this._buttonConfigExpanded = {}; + } + if (!this._buttonConfigExpanded[buttonType]) { + this._buttonConfigExpanded[buttonType] = {}; + } + this._buttonConfigExpanded[buttonType][index] = !this._buttonConfigExpanded[buttonType][index]; + this.requestUpdate(); + } + + _getButtonConfig(buttonType, index) { + if (!this.config.button_configs) { + return null; + } + if (!this.config.button_configs[buttonType]) { + return null; + } + return this.config.button_configs[buttonType][index] || {}; + } + + _updateButtonCustomName(buttonType, index, name) { + if (!this.config.button_configs) { + this.config.button_configs = {}; + } + if (!this.config.button_configs[buttonType]) { + this.config.button_configs[buttonType] = {}; + } + if (!this.config.button_configs[buttonType][index]) { + this.config.button_configs[buttonType][index] = {}; + } + + if (name) { + this.config.button_configs[buttonType][index].custom_name = name; + } else { + delete this.config.button_configs[buttonType][index].custom_name; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _updateButtonCustomIconOn(buttonType, index, icon) { + if (!this.config.button_configs) { + this.config.button_configs = {}; + } + if (!this.config.button_configs[buttonType]) { + this.config.button_configs[buttonType] = {}; + } + if (!this.config.button_configs[buttonType][index]) { + this.config.button_configs[buttonType][index] = {}; + } + + if (icon) { + this.config.button_configs[buttonType][index].custom_icon_on = icon; + } else { + delete this.config.button_configs[buttonType][index].custom_icon_on; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _updateButtonCustomIconOff(buttonType, index, icon) { + if (!this.config.button_configs) { + this.config.button_configs = {}; + } + if (!this.config.button_configs[buttonType]) { + this.config.button_configs[buttonType] = {}; + } + if (!this.config.button_configs[buttonType][index]) { + this.config.button_configs[buttonType][index] = {}; + } + + if (icon) { + this.config.button_configs[buttonType][index].custom_icon_off = icon; + } else { + delete this.config.button_configs[buttonType][index].custom_icon_off; + } + + this._fireEvent(); + this.requestUpdate(); + } + + _renderButtonConfig(buttonType, index) { + if (!this.hass) return html``; + + const buttonId = buttonType === 'buttons' ? (this.config.buttons || [])[index] : (this.config.buttons2 || [])[index]; + if (!buttonId) return html``; + + const entity = this.hass.states[buttonId]; + if (!entity) return html``; + + const domain = buttonId.split('.')[0]; + const config = this._getButtonConfig(buttonType, index) || {}; + + // light/switch/button 类型显示自定义名称、自定义开启图标、自定义关闭图标 + if (['light', 'switch', 'button'].includes(domain)) { + return html` +
+ + this._updateButtonCustomName(buttonType, index, e.target.value)} + class="button-config-input" + /> +
+
+ + this._updateButtonCustomIconOn(buttonType, index, e.target.value)} + class="button-config-input" + /> +
+
+ + this._updateButtonCustomIconOff(buttonType, index, e.target.value)} + class="button-config-input" + /> +
+ `; + } + // select/sensor 类型只显示自定义名称 + else if (['select', 'sensor'].includes(domain)) { + return html` +
+ + this._updateButtonCustomName(buttonType, index, e.target.value)} + class="button-config-input" + /> +
+ `; + } + + return html``; + } + + _renderModeFilter(modeType, title) { + if (!this.hass || !this.config.entity) return html``; + const entity = this.hass.states[this.config.entity]; + if (!entity) return html``; + + const attrs = entity.attributes; + let modes = []; + if (modeType === 'hvac_modes') modes = attrs.hvac_modes || []; + else if (modeType === 'fan_modes') modes = attrs.fan_modes || []; + else if (modeType === 'swing_modes') modes = attrs.swing_modes || []; + else if (modeType === 'preset_modes') modes = attrs.preset_modes || []; + else if (modeType === 'operation_list') modes = attrs.operation_list || []; + + if (modes.length === 0) return html``; + + const isExpanded = this._modeFilterExpanded?.[modeType] || false; + const filters = this._modeFilters?.[modeType] || {}; + const modeConfig = this.config.mode_configs?.[modeType] || {}; + + // 计算选中的数量 + const checkedCount = Object.values(filters).filter(v => v === true).length; + const totalCount = modes.length; + + return html` +
+
this._toggleModeFilter(modeType)}> +
+ + ${title} (${checkedCount}/${totalCount}) +
+
+ ${isExpanded ? html` +
+ ${modes.map(mode => html` +
+
+
+ this._toggleModeItem(modeType, mode)} + /> + +
+
+
+
+ this._toggleShowName(modeType, mode, e.target.checked)} + /> + +
+ this._updateCustomName(modeType, mode, e.target.value)} + class="mode-config-input" + /> +
+ this._toggleShowIcon(modeType, mode, e.target.checked)} + /> + +
+ this._updateCustomIcon(modeType, mode, e.target.value)} + class="mode-config-input" + /> +
+
+ `)} +
+ ` : ''} +
+ `; + } + _fireEvent() { this.dispatchEvent(new CustomEvent('config-changed', { detail: { config: this.config } @@ -1237,6 +1946,9 @@ class XiaoshiPadClimateCardEditor extends LitElement { this._filteredButton2Entities = {}; this._showButton2Lists = {}; this._availableModes = {}; + this._modeFilterExpanded = {}; + this._modeFilters = {}; + this._buttonConfigExpanded = {}; } updated(changedProperties) { @@ -1371,6 +2083,8 @@ class XiaoshiPadClimateCard extends LitElement { display: flex; align-items: center; justify-content: center; + flex-direction: column; + gap: 2px; --mdc-icon-size: 20px; } @@ -1380,6 +2094,11 @@ class XiaoshiPadClimateCard extends LitElement { color: var(--fg-color); } + .mode-button .mode-text { + font-size: 10px; + color: var(--fg-color); + } + .mode-button.active-mode { background: var(--active-color); } @@ -1388,7 +2107,7 @@ class XiaoshiPadClimateCard extends LitElement { display: flex; align-items: center; justify-content: center; - gap: 0px; + gap: 4px; width: 100%; height: 100%; color: var(--fg-color); @@ -1397,7 +2116,7 @@ class XiaoshiPadClimateCard extends LitElement { } .swing-text, .preset-text, .water-text { - font-size: 12px; + font-size: 10px; color: var(--fg-color); } @@ -1918,13 +2637,17 @@ _renderExtraButtons(buttonType = 1) { else if (state === 'fan' || state === 'fan_only') activeColor = 'rgb(0,188,213)'; else if (state === 'auto') activeColor = 'rgb(147,112,219)'; - return buttonsToShow.map(buttonEntityId => { + const buttonConfigKey = buttonType === 1 ? 'buttons' : 'buttons2'; + + return buttonsToShow.map((buttonEntityId, index) => { const entity = this.hass.states[buttonEntityId]; if (!entity) return html``; const domain = buttonEntityId.split('.')[0]; const friendlyName = entity.attributes.friendly_name || ''; - const displayName = friendlyName.slice(0, 4); + const buttonConfig = this.config.button_configs?.[buttonConfigKey]?.[index] || {}; + const customName = buttonConfig.custom_name || friendlyName; + const displayName = customName.slice(0, 4); const displayValueColor = entity.state.includes('低') || entity.state.includes('少') || entity.state.includes('缺') ? 'red' : fgColor; // 根据名称自定义图标 @@ -1946,7 +2669,11 @@ _renderExtraButtons(buttonType = 1) { case 'light': const isActive = entity.state === 'on'; const customIcon = _getCustomIcon(friendlyName, isActive); - const icon = customIcon || (isActive ? 'mdi:toggle-switch' : 'mdi:toggle-switch-off'); + const icon = buttonConfig.custom_icon_on && isActive ? buttonConfig.custom_icon_on + : buttonConfig.custom_icon_off && !isActive ? buttonConfig.custom_icon_off + : customIcon + ? customIcon + : (isActive ? 'mdi:toggle-switch' : 'mdi:toggle-switch-off'); const buttonColor = isActive ? activeColor : fgColor; return html` @@ -1954,7 +2681,7 @@ _renderExtraButtons(buttonType = 1) { class="side-extra-button ${isActive ? 'active-extra' : ''}" @click=${() => this._handleExtraButtonClick(buttonEntityId, domain)} style="--active-color: ${buttonColor}; --bg-color: ${bgColor};" - title="${friendlyName}" + title="${customName}" > ${displayName} @@ -1973,7 +2700,7 @@ _renderExtraButtons(buttonType = 1) { `; case 'button': - const buttonIcon = 'mdi:button-pointer'; + const buttonIcon = buttonConfig.custom_icon_on || buttonConfig.custom_icon_off || 'mdi:button-pointer'; return html` `; }); @@ -2131,11 +2871,23 @@ _renderExtraButtons(buttonType = 1) { const entity = this.hass.states[this.config.entity]; const state = entity ? entity.state : 'off'; const theme = this._evaluateTheme(); + const modeConfigs = this.config.mode_configs?.fan_modes || {}; - return fanModes.map((mode, index) => { + // 应用过滤器 + const filters = this.config.mode_filters?.fan_modes || {}; + const filteredModes = fanModes.filter(mode => filters[mode] !== false); + + return filteredModes.map((mode, index) => { const isActive = mode === currentFanMode; let bgColor = 'rgb(0,0,0)'; - + const config = modeConfigs[mode] || {}; + + // 获取自定义配置 + const showName = config.show_name !== false; + const showIcon = config.show_icon !== false; + const customName = config.custom_name || this._translateFanMode(mode); + const customIcon = config.custom_icon || 'mdi:fan'; + if (isActive) { if (state === 'cool') bgColor = 'rgb(33,150,243)'; else if (state === 'heat') bgColor = 'rgb(254,111,33)'; @@ -2151,13 +2903,15 @@ _renderExtraButtons(buttonType = 1) { @click=${() => this._setFanMode(mode)} style="--active-color: ${bgColor}; background: ${isActive ? bgColor : 'rgb(0,0,0,0)'}" > -
- - ${this._translateFanMode(mode)} +
+ ${showIcon ? html` + + ` : ''} + ${showName ? html`${customName}` : ''}
`; @@ -2170,11 +2924,23 @@ _renderExtraButtons(buttonType = 1) { const entity = this.hass.states[this.config.entity]; const state = entity ? entity.state : 'off'; const theme = this._evaluateTheme(); + const modeConfigs = this.config.mode_configs?.swing_modes || {}; - return swingModes.map(mode => { + // 应用过滤器 + const filters = this.config.mode_filters?.swing_modes || {}; + const filteredModes = swingModes.filter(mode => filters[mode] !== false); + + return filteredModes.map(mode => { const isActive = mode === currentSwingMode; let bgColor = 'rgb(0,0,0,0)'; - + const config = modeConfigs[mode] || {}; + + // 获取自定义配置 + const showName = config.show_name !== false; + const showIcon = config.show_icon !== false; + const customName = config.custom_name || this._translateSwingMode(mode); + const customIcon = config.custom_icon || this._getSwingIcon(mode); + if (isActive) { if (state === 'cool') bgColor = 'rgb(33,150,243)'; else if (state === 'heat') bgColor = 'rgb(254,111,33)'; @@ -2190,8 +2956,8 @@ _renderExtraButtons(buttonType = 1) { style="--active-color: ${bgColor}; background: ${isActive ? bgColor : 'rgb(0,0,0,0)'}" >
- - ${this._translateSwingMode(mode)} + ${showIcon ? html`` : ''} + ${showName ? html`${customName}` : ''}
`; @@ -2204,11 +2970,23 @@ _renderExtraButtons(buttonType = 1) { const entity = this.hass.states[this.config.entity]; const state = entity ? entity.state : 'off'; const theme = this._evaluateTheme(); + const modeConfigs = this.config.mode_configs?.preset_modes || {}; - return presetModes.map(mode => { + // 应用过滤器 + const filters = this.config.mode_filters?.preset_modes || {}; + const filteredModes = presetModes.filter(mode => filters[mode] !== false); + + return filteredModes.map(mode => { const isActive = mode === currentPresetMode; let bgColor = 'rgb(0,0,0,0)'; - + const config = modeConfigs[mode] || {}; + + // 获取自定义配置 + const showName = config.show_name !== false; + const showIcon = config.show_icon !== false; + const customName = config.custom_name || this._translatePresetMode(mode); + const customIcon = config.custom_icon || this._getPresetIcon(mode); + if (isActive) { if (state === 'cool') bgColor = 'rgb(33,150,243)'; else if (state === 'heat') bgColor = 'rgb(254,111,33)'; @@ -2224,8 +3002,8 @@ _renderExtraButtons(buttonType = 1) { style="--active-color: ${bgColor}; background: ${isActive ? bgColor : 'rgb(0,0,0,0)'}" >
- - ${this._translatePresetMode(mode)} + ${showIcon ? html`` : ''} + ${showName ? html`${customName}` : ''}
`; @@ -2238,11 +3016,23 @@ _renderExtraButtons(buttonType = 1) { const entity = this.hass.states[this.config.entity]; const state = entity ? entity.state : 'off'; const theme = this._evaluateTheme(); + const modeConfigs = this.config.mode_configs?.operation_list || {}; - return operation_list.map(mode => { + // 应用过滤器 + const filters = this.config.mode_filters?.operation_list || {}; + const filteredModes = operation_list.filter(mode => filters[mode] !== false); + + return filteredModes.map(mode => { const isActive = mode === operation_mode; let bgColor = 'rgb(0,0,0,0)'; - + const config = modeConfigs[mode] || {}; + + // 获取自定义配置 + const showName = config.show_name !== false; + const showIcon = config.show_icon !== false; + const customName = config.custom_name || mode; + const customIcon = config.custom_icon || 'mdi:water'; + if (isActive) { if (state === 'cool') bgColor = 'rgb(33,150,243)'; else if (state === 'heat') bgColor = 'rgb(254,111,33)'; @@ -2258,7 +3048,8 @@ _renderExtraButtons(buttonType = 1) { style="--active-color: ${bgColor}; background: ${isActive ? bgColor : 'rgb(0,0,0,0)'}" >
- ${mode} + ${showIcon ? html`` : ''} + ${showName ? html`${customName}` : ''}
`;