Skip to content

Commit fbf0143

Browse files
committed
feat(chat-input): 聊天输入框自动扩大支持自定义高度,桌面端与移动端分别设置
1 parent afb8a95 commit fbf0143

2 files changed

Lines changed: 150 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
### 已变更
88

9-
- 暂无待发布的用户可见变更
9+
- 聊天输入框自动扩大支持自定义高度,桌面端与移动端可分别设置
1010

1111

1212
## [1.32.39] - 2026-07-28

src/index.js

Lines changed: 149 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,113 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
631631
return btn;
632632
};
633633

634+
// 聊天输入框扩大高度配置(桌面/移动端分开存储,预留后续分别调整)
635+
const CHAT_INPUT_HEIGHT_KEY = {
636+
desktop: 'chatInputExpanderHeight',
637+
mobile: 'chatInputExpanderHeightMobile',
638+
};
639+
const CHAT_INPUT_HEIGHT_DEFAULTS = { desktop: 130, mobile: 90 };
640+
const CHAT_INPUT_HEIGHT_RANGE = { min: 40 };
641+
642+
const readChatInputHeight = (key, fallback) => {
643+
try {
644+
const config = JSON.parse(localStorage.getItem('SC_PageActions_Settings') || '{}');
645+
const value = parseInt(config[key], 10);
646+
return isFinite(value) ? value : fallback;
647+
} catch (e) {
648+
return fallback;
649+
}
650+
};
651+
652+
const createChatInputHeightControls = () => {
653+
const row = document.createElement('div');
654+
row.className = 'sc-chat-input-height-row';
655+
row.style.cssText = 'display:grid;grid-template-columns:auto 64px auto;gap:6px;align-items:center;margin-top:6px;font-size:12px;color:var(--sc-panel-fg,#efefef);';
656+
657+
const makeInput = (label, key, fallback) => {
658+
const labelSpan = document.createElement('span');
659+
labelSpan.textContent = label;
660+
labelSpan.style.cssText = 'white-space:nowrap;line-height:24px;';
661+
const input = document.createElement('input');
662+
input.type = 'number';
663+
input.min = CHAT_INPUT_HEIGHT_RANGE.min;
664+
input.step = 10;
665+
input.value = readChatInputHeight(key, fallback);
666+
input.style.cssText = 'width:100%;height:24px;box-sizing:border-box;padding:2px 4px;border:1px solid #666;border-radius:3px;background:rgba(255,255,255,0.08);color:inherit;font-size:12px;';
667+
const unit = document.createElement('span');
668+
unit.textContent = 'px';
669+
unit.style.cssText = 'line-height:24px;';
670+
row.append(labelSpan, input, unit);
671+
return input;
672+
};
673+
674+
const desktopInput = makeInput('桌面端高度:', CHAT_INPUT_HEIGHT_KEY.desktop, CHAT_INPUT_HEIGHT_DEFAULTS.desktop);
675+
const mobileInput = makeInput('移动端高度:', CHAT_INPUT_HEIGHT_KEY.mobile, CHAT_INPUT_HEIGHT_DEFAULTS.mobile);
676+
677+
const clampHeight = (value, fallback) => {
678+
const n = parseInt(value, 10);
679+
if (!isFinite(n)) return fallback;
680+
return Math.max(CHAT_INPUT_HEIGHT_RANGE.min, n);
681+
};
682+
683+
// 按钮短暂变换文字作为操作反馈,随后恢复
684+
const flashButton = (btn, activeText, activeColor, idleText, idleColor) => {
685+
if (btn._flashTimer) clearTimeout(btn._flashTimer);
686+
btn.textContent = activeText;
687+
btn.style.backgroundColor = activeColor;
688+
btn._flashTimer = setTimeout(() => {
689+
btn.textContent = idleText;
690+
btn.style.backgroundColor = idleColor;
691+
}, 1500);
692+
};
693+
694+
const applyBtn = document.createElement('button');
695+
applyBtn.className = 'SimcompaniesRetailCalculation-action-btn';
696+
applyBtn.textContent = '应用';
697+
applyBtn.style.cssText = 'flex:1;background:#2196F3;color:white;border:none;padding:4px 8px;border-radius:3px;cursor:pointer;font-size:12px;';
698+
applyBtn.onclick = (e) => {
699+
e.stopPropagation();
700+
const configKey = 'SC_PageActions_Settings';
701+
let config = {};
702+
try { config = JSON.parse(localStorage.getItem(configKey)) || {}; } catch (err) { config = {}; }
703+
config[CHAT_INPUT_HEIGHT_KEY.desktop] = clampHeight(desktopInput.value, CHAT_INPUT_HEIGHT_DEFAULTS.desktop);
704+
config[CHAT_INPUT_HEIGHT_KEY.mobile] = clampHeight(mobileInput.value, CHAT_INPUT_HEIGHT_DEFAULTS.mobile);
705+
localStorage.setItem(configKey, JSON.stringify(config));
706+
desktopInput.value = config[CHAT_INPUT_HEIGHT_KEY.desktop];
707+
mobileInput.value = config[CHAT_INPUT_HEIGHT_KEY.mobile];
708+
if (typeof window.scChatInputExpanderApplyStyles === 'function') {
709+
window.scChatInputExpanderApplyStyles();
710+
}
711+
flashButton(applyBtn, '✓ 已应用', '#4CAF50', '应用', '#2196F3');
712+
};
713+
714+
const resetBtn = document.createElement('button');
715+
resetBtn.className = 'SimcompaniesRetailCalculation-action-btn';
716+
resetBtn.textContent = '重置';
717+
resetBtn.style.cssText = 'flex:1;background:#607D8B;color:white;border:none;padding:4px 8px;border-radius:3px;cursor:pointer;font-size:12px;';
718+
resetBtn.onclick = (e) => {
719+
e.stopPropagation();
720+
const configKey = 'SC_PageActions_Settings';
721+
let config = {};
722+
try { config = JSON.parse(localStorage.getItem(configKey)) || {}; } catch (err) { config = {}; }
723+
delete config[CHAT_INPUT_HEIGHT_KEY.desktop];
724+
delete config[CHAT_INPUT_HEIGHT_KEY.mobile];
725+
localStorage.setItem(configKey, JSON.stringify(config));
726+
desktopInput.value = CHAT_INPUT_HEIGHT_DEFAULTS.desktop;
727+
mobileInput.value = CHAT_INPUT_HEIGHT_DEFAULTS.mobile;
728+
if (typeof window.scChatInputExpanderApplyStyles === 'function') {
729+
window.scChatInputExpanderApplyStyles();
730+
}
731+
flashButton(resetBtn, '✓ 已重置', '#4CAF50', '重置', '#607D8B');
732+
};
733+
734+
const actionRow = document.createElement('div');
735+
actionRow.style.cssText = 'display:flex;gap:6px;grid-column:1 / -1;margin-top:2px;';
736+
actionRow.append(applyBtn, resetBtn);
737+
row.appendChild(actionRow);
738+
return row;
739+
};
740+
634741
mainMenu.append(
635742
createStatusRow('r1'),
636743
createStatusRow('r2'),
@@ -743,7 +850,7 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
743850
{ type: 'toggle', key: 'landscapeHighlight', label: '地图空闲建筑高亮' },
744851
{ type: 'toggle', key: 'paQuestAnswers', label: 'PA任务答案', defaultEnabled: true },
745852
{ type: 'toggle', key: 'snipboardPreview', label: 'Snipboard图片预览', defaultEnabled: true },
746-
{ type: 'toggle', key: 'chatInputExpander', label: '聊天输入框自动扩大', defaultEnabled: true },
853+
{ type: 'toggle', key: 'chatInputExpander', label: '聊天输入框自动扩大', defaultEnabled: true, heightInput: true },
747854
];
748855
const ITEMS_PER_PAGE = 5;
749856
let currentPage = 0;
@@ -757,7 +864,16 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
757864
let el;
758865
if (item.type === 'factory') { el = item.fn(); }
759866
else { el = createPageActionToggle(item.key, item.label, item.defaultEnabled !== false); }
760-
el.classList.add('sc-toggle-item');
867+
if (item.heightInput) {
868+
const wrap = document.createElement('div');
869+
wrap.className = 'sc-toggle-item';
870+
wrap.style.cssText = 'display:flex;flex-direction:column;';
871+
wrap.appendChild(el);
872+
wrap.appendChild(createChatInputHeightControls());
873+
el = wrap;
874+
} else {
875+
el.classList.add('sc-toggle-item');
876+
}
761877
secBtnGroup.appendChild(el);
762878
}
763879
const controls = document.createElement('div');
@@ -3717,6 +3833,10 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
37173833
var existingStyle = document.getElementById(styleId);
37183834
var isDark = typeof DM === 'function' ? DM() : false;
37193835

3836+
// 读取自定义扩大高度(桌面/移动端分开存储),未设置时沿用默认值
3837+
var desktopHeight = readCustomHeight('chatInputExpanderHeight', 130);
3838+
var mobileHeight = readCustomHeight('chatInputExpanderHeightMobile', 90);
3839+
37203840
// 依据深浅色模式采用不同的蓝色阴影透明度以保证视觉高级感
37213841
var shadowColor = isDark ? 'rgba(33, 150, 243, 0.5)' : 'rgba(33, 150, 243, 0.3)';
37223842
var styleText = `
@@ -3730,46 +3850,46 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
37303850
37313851
/* 焦点在输入框内时的扩大状态(默认桌面端/平板) */
37323852
.sc-chat-textarea-focused {
3733-
height: 130px !important;
3853+
height: ${desktopHeight}px !important;
37343854
top: 0px !important;
37353855
bottom: 0px !important;
37363856
border-color: #2196F3 !important;
37373857
box-shadow: 0 0 10px ${shadowColor} !important;
37383858
}
37393859
/* 使输入框紧邻的前置高亮渲染 div 的高度同步拉伸,防止文本输入层级错位导致输入法定位失灵被覆盖 */
37403860
.sc-chat-wrap-focused > div {
3741-
height: 130px !important;
3742-
min-height: 130px !important;
3861+
height: ${desktopHeight}px !important;
3862+
min-height: ${desktopHeight}px !important;
37433863
}
37443864
.sc-chat-input-group-focused {
3745-
height: 130px !important;
3865+
height: ${desktopHeight}px !important;
37463866
}
37473867
/* 发送按钮容器高度扩大,并利用 vertical-align 靠底对齐,保持原有 table-cell 布局不被破坏 */
37483868
.sc-chat-btn-focused {
3749-
height: 130px !important;
3869+
height: ${desktopHeight}px !important;
37503870
vertical-align: bottom !important;
37513871
}
37523872
.sc-chat-outer-focused {
3753-
height: 138px !important;
3873+
height: ${desktopHeight + 8}px !important;
37543874
}
37553875
37563876
/* 移动端/小屏幕适配:防止弹出的虚拟键盘和过大输入框遮挡全部屏幕 */
37573877
@media (max-width: 767px) {
37583878
.sc-chat-textarea-focused {
3759-
height: 90px !important;
3879+
height: ${mobileHeight}px !important;
37603880
}
37613881
.sc-chat-wrap-focused > div {
3762-
height: 90px !important;
3763-
min-height: 90px !important;
3882+
height: ${mobileHeight}px !important;
3883+
min-height: ${mobileHeight}px !important;
37643884
}
37653885
.sc-chat-input-group-focused {
3766-
height: 90px !important;
3886+
height: ${mobileHeight}px !important;
37673887
}
37683888
.sc-chat-btn-focused {
3769-
height: 90px !important;
3889+
height: ${mobileHeight}px !important;
37703890
}
37713891
.sc-chat-outer-focused {
3772-
height: 98px !important;
3892+
height: ${mobileHeight + 8}px !important;
37733893
}
37743894
}
37753895
`;
@@ -3784,6 +3904,18 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
37843904
}
37853905
}
37863906

3907+
// 读取自定义扩大高度(px),非法值回退默认,仅保留最小下限防止塌陷
3908+
function readCustomHeight(key, fallback) {
3909+
try {
3910+
var cfg = JSON.parse(localStorage.getItem('SC_PageActions_Settings') || '{}');
3911+
var value = parseInt(cfg[key], 10);
3912+
if (!isFinite(value)) return fallback;
3913+
return Math.max(40, value);
3914+
} catch (e) {
3915+
return fallback;
3916+
}
3917+
}
3918+
37873919
// 识别聊天输入框(通过 DOM 结构与聊天室特有特征判定,不依赖文本内容)
37883920
function isChatInput(el) {
37893921
if (!el || el.tagName !== 'TEXTAREA') return false;
@@ -3980,6 +4112,9 @@ import { createGlobalCustomToggle } from './utils/uiComponents.js';
39804112

39814113
// 立即初始化以注入样式
39824114
init();
4115+
4116+
// 供设置面板在修改自定义高度后立即重新生成样式
4117+
window.scChatInputExpanderApplyStyles = injectStyles;
39834118
})();
39844119

39854120
// ======================

0 commit comments

Comments
 (0)