修:选了「自定义」却看不到码率框(焦点还在下拉上,列表不重建)
页面为了让定时刷新不冲掉用户正在填的内容,列表在「焦点还在列表里」时不重建。 但原生 select 选完一项后焦点会留在下拉上,于是选了「自定义」以后列表一直不重建, 那个码率框要等用户点到别处才出现 —— 看起来就是「选了自定义根本没地方填」。 - 选到「自定义」时当场把码率框建出来并聚焦(不用等服务端回来和下一次重建), 切走时当场收掉。 - 顺带把「不重建」的条件收紧成「只有正在列表里的文本框里打字时才跳过」: 下拉和勾选都是改完立即提交的,之前它们也会一直卡住重建, 连带「录播中/弹幕中」的徽标也要点到别处才刷新。 - 框里的初始值:填过自定义就用上次那个数(切走再切回来不会被改成当前档位), 没填过才用现在实际在用的那一档。 验证方式也换了:回归脚本里改用「点开下拉 + 键盘选最后一项」这种真实操作 (Playwright 的 select_option 不保留焦点,正是它让这个 bug 漏了过去), 新增「选完立刻就有框」「焦点直接落在框里」「切走即收掉」「切回带着上次的值」四条断言; verify_streamer_br.py 33 项、verify_qualities.py 全过,verify_settings.py / verify_danmu_match.py 无回归,go test ./...、gofmt、go vet 干净。
This commit is contained in:
@@ -746,8 +746,11 @@ async function refresh(){
|
||||
}).join("");
|
||||
var list = document.getElementById("st");
|
||||
var sig = JSON.stringify(st.streamers);
|
||||
// 数据没变化不重建;正在列表里操作时也跳过
|
||||
if(sig !== stSig && !list.contains(document.activeElement)){
|
||||
// 只有「正在列表里的文本框里打字」才跳过重建:下拉和勾选都是改完立即提交的,
|
||||
// 一直卡着不重建会让「选了自定义该出现的码率框」「录播中的徽标」迟迟不刷新
|
||||
var ae = document.activeElement;
|
||||
var typing = !!(ae && list.contains(ae) && ae.tagName === "INPUT" && ae.type !== "checkbox");
|
||||
if(sig !== stSig && !typing){
|
||||
stSig = sig;
|
||||
// 重建前记下用户改过、还没提交的自定义码率,建完抄回去(填错的不用留)
|
||||
var keepNum = {};
|
||||
@@ -1289,6 +1292,36 @@ async function delUid(uid){
|
||||
if(!confirm("确定删除 uid " + uid + " 并停止其录制?")) return;
|
||||
post("/api/streamer/remove", {uid: uid});
|
||||
}
|
||||
// 选到「自定义」时当场把码率框建出来:列表在「正在文本框里打字」时不会重建,
|
||||
// 光等服务端回来是看不到输入框的,用户会以为没地方填。顺带把焦点放进去,直接就能敲数字
|
||||
function showBrNum(row, sel, focus){
|
||||
var el = row.querySelector("input.brnum");
|
||||
if(el){
|
||||
if(focus){ el.focus(); el.select(); }
|
||||
return el;
|
||||
}
|
||||
var uid = parseInt(sel.dataset.uid, 10);
|
||||
var cur = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid; })[0];
|
||||
el = document.createElement("input");
|
||||
el.type = "text";
|
||||
el.className = "brnum";
|
||||
el.dataset.uid = String(uid);
|
||||
el.inputMode = "numeric";
|
||||
el.placeholder = "Kbps";
|
||||
el.title = "自定义:取不超过这个码率的最高档";
|
||||
// 初始值:填过自定义就用上次那个数(切走再切回来不该被改掉),没填过就用现在实际在用的那一档,
|
||||
// 免得切过去的一瞬间变成最低档
|
||||
var v = cur ? (cur.bitrate || 0) : 0;
|
||||
if(!(v > 0) && cur) v = cur.qualityBitrate || 0;
|
||||
el.value = v;
|
||||
sel.parentNode.insertBefore(el, sel.nextSibling);
|
||||
if(focus){ el.focus(); el.select(); }
|
||||
return el;
|
||||
}
|
||||
function hideBrNum(row){
|
||||
var el = row.querySelector("input.brnum");
|
||||
if(el && el.parentNode) el.parentNode.removeChild(el);
|
||||
}
|
||||
// 读一行里选的档位:pref 是下拉的值;自定义时把输入框里的码率一起带上,
|
||||
// 输入框不在(刚切到自定义、或不是自定义)就不带 bitrate,服务端会保留原来填的值
|
||||
function rowQuality(row){
|
||||
@@ -1302,11 +1335,11 @@ function rowQuality(row){
|
||||
v = parseInt(num.value.trim(), 10);
|
||||
if(isNaN(v) || v < 0) return null;
|
||||
}else{
|
||||
// 刚切到自定义、输入框还没建出来:用「现在实际用到的档位码率」当起点,
|
||||
// 免得切过去的一瞬间掉到最低档(uid 可能还没设过自定义值)
|
||||
var uid = parseInt(sel.dataset.uid, 10);
|
||||
var cur = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid; })[0];
|
||||
v = cur ? (cur.qualityBitrate || cur.bitrate || 0) : 0;
|
||||
// 兜底:填过自定义就用上次那个数,没填过就用现在实际在用的那一档
|
||||
var uid0 = parseInt(sel.dataset.uid, 10);
|
||||
var cur0 = (lastSt && lastSt.streamers ? lastSt.streamers : []).filter(function(s){ return s.uid === uid0; })[0];
|
||||
v = cur0 ? (cur0.bitrate || 0) : 0;
|
||||
if(!(v > 0) && cur0) v = cur0.qualityBitrate || 0;
|
||||
}
|
||||
out.bitrate = v;
|
||||
}
|
||||
@@ -1328,6 +1361,9 @@ document.addEventListener("change", async function(e){
|
||||
// 档位下拉是选完立即生效的(正在录制时会自动换档重录)
|
||||
var uid3 = parseInt(t.dataset.uid, 10);
|
||||
var row3 = t.closest(".row");
|
||||
// 选到「自定义」当场把码率框建出来并聚焦,切走就收掉(不依赖列表重建,见 showBrNum)
|
||||
if(t.value === "custom") showBrNum(row3, t, true);
|
||||
else hideBrNum(row3);
|
||||
var q3 = rowQuality(row3);
|
||||
if(!q3){ showMsg(false, "自定义档位的码率必须是大于等于 0 的数字"); return; }
|
||||
q3.uid = uid3;
|
||||
|
||||
Reference in New Issue
Block a user