刷新功能

This commit is contained in:
dada2321
2026-04-19 04:57:36 +08:00
parent a92455bb5f
commit e5ae540a3c
3 changed files with 94 additions and 2 deletions
+20
View File
@@ -0,0 +1,20 @@
# Process
## 2026-04-19
### 今日战利品
- 修复了 163 邮箱顶部“刷新”按钮的识别问题。
- 根因不是插件不知道顶部按钮在哪里,而是它用 DOM 文本做识别时,代码只认“刷新”,但 163 实际渲染出来可能是“刷 新”。
-`163` 邮箱补上了回归测试,确保以后再次遇到这种带空格的按钮文案时,脚本仍然会优先点击顶部工具栏刷新,而不是误退回到“收件箱”。
- 额外补了更直白的刷新分支日志,后续排查时可以直接看出本次命中的是“顶部刷新”“左侧收信”还是“收件箱兜底”。
### 知识地图
- 这一块属于“自动化脚本稳定性”里的 DOM 识别层。
- 老板可以把它理解成:脚本不是靠“看见页面上方那个位置”去点按钮,而是靠“读页面结构里的标签文字和属性”去认目标。
- 所以这里学到的核心不是某一个按钮怎么点,而是“页面自动化里,视觉上像同一个按钮,DOM 文本却可能有空格、换行、图标包裹等变体”,识别逻辑必须做抗噪处理。
- 这部分在大神知识体系里,位置属于:前端页面结构理解 -> 浏览器自动化 -> 选择器与文本匹配鲁棒性。
### 下一步导航
- 可以继续把 163 的删除兜底逻辑也做一次同类检查,因为顶部“删 除”从 DOM 结构看也可能存在同样的空格拆字风险。
- 如果老板接下来还想继续提稳收信成功率,可以再查一层:163 顶部“刷新”点击之后,页面到底有没有真正触发新的列表请求,以及请求完成信号该监听什么。
- 如果要把这一块做成长期稳定方案,下一步适合补“刷新动作观测点”日志,比如记录刷新前后列表首封邮件 ID、请求时间、是否出现 loading。
+13 -2
View File
@@ -461,9 +461,18 @@ if (!isTopFrame) {
async function refreshInbox() {
const toolbarBtns = document.querySelectorAll('.nui-btn .nui-btn-text');
for (const btn of toolbarBtns) {
if (normalizeText(btn.textContent || '') === '刷新') {
// 163 会把“刷 新”拆成带空格的文字,所以这里要先压平空白,
// 不然脚本明明看到了顶部刷新按钮,也会误以为没找到。
const compactLabel = String([
btn.textContent || '',
btn.getAttribute?.('aria-label') || '',
btn.getAttribute?.('title') || '',
].join('')).replace(/\s+/g, '');
if (compactLabel === '刷新') {
simulateClick(btn.closest('.nui-btn') || btn);
console.log(MAIL163_PREFIX, 'Clicked refresh button');
console.log(MAIL163_PREFIX, 'Clicked top toolbar refresh button');
log('[163 邮箱] 已命中顶部工具栏“刷新”按钮');
await sleep(800);
return;
}
@@ -474,6 +483,7 @@ if (!isTopFrame) {
if (normalizeText(btn.textContent || '').includes('收信')) {
simulateClick(btn);
console.log(MAIL163_PREFIX, 'Clicked receive button');
log('[163 邮箱] 未找到顶部刷新,改用左侧“收信”按钮');
await sleep(800);
return;
}
@@ -482,6 +492,7 @@ if (!isTopFrame) {
const inboxLink = findInboxLink();
if (inboxLink) {
simulateClick(inboxLink);
log('[163 邮箱] 未找到顶部刷新或左侧“收信”,回退到点击“收件箱”');
await sleep(800);
return;
}
+61
View File
@@ -146,3 +146,64 @@ return {
assert.equal(result.code, '480382');
assert.deepEqual(api.getOpenedMailIds(), ['mail-1']);
});
test('refreshInbox prefers the top toolbar refresh button even when 163 renders the label as 刷 新', async () => {
const bundle = [
extractFunction('normalizeText'),
extractFunction('refreshInbox'),
].join('\n');
const api = new Function(`
const MAIL163_PREFIX = '[MultiPage:mail-163]';
const clickOrder = [];
const refreshButton = {
tagName: 'DIV',
textContent: '刷 新',
};
const refreshLabel = {
textContent: '刷 新',
closest(selector) {
return selector === '.nui-btn' ? refreshButton : null;
},
};
const inboxLink = {
tagName: 'SPAN',
textContent: '收件箱',
};
const document = {
querySelectorAll(selector) {
if (selector === '.nui-btn .nui-btn-text') return [refreshLabel];
if (selector === '.ra0') return [];
return [];
},
};
function simulateClick(node) {
clickOrder.push(node.textContent);
}
function findInboxLink() {
return inboxLink;
}
async function sleep() {}
function log() {}
${bundle}
return {
refreshInbox,
getClickOrder() {
return clickOrder.slice();
},
};
`)();
await api.refreshInbox();
assert.deepEqual(api.getClickOrder(), ['刷 新']);
});