v26 第 26 批(5 条):财务多选按集合取图 / 首页全天置顶与红线定位 / 任务复选框去提示与看板颜色 / 导航搜索引擎切换与站点复用 / 详情页去复选框

- 财务:勾选多个标签时上面那张「总金额」图按**选中集合**统计(新增
  ledger/total_chart 路由 + 单一容器 data-ck-total-host,按集合现取并缓存;
  Ledger::timeline 第二参数放宽为 string|array)
- 首页日程:全天日程移出滚动容器固定置顶;进场把当前时刻红线居中
  (scrollTop 计算,不用 scrollIntoView),触发条件不绑 $showNow
- 任务:复选框去除 title 提示;看板可设颜色(Task::boardColor/updateBoard),
  首页任务行用该颜色显示所属看板
- 导航:展示页补回 id=engine-tabs(切换搜索引擎无效的根因);补内置引擎;
  新增站点输 URL 可复用他人已加过的站点(sharedByUrl/copyIconFile/adoptSite)
- 任务详情页页头去掉复选框(已有「标记完成」按钮)
This commit is contained in:
2026-10-07 15:31:26 +08:00
parent a5e559b2b3
commit c8839fa728
15 changed files with 964 additions and 93 deletions
+41 -8
View File
@@ -1,23 +1,52 @@
/* ============================================================
导航展示页脚本(v24 第 24 批 用户第 4 条)
—— **从 SimpleNav 的 assets/js/app.js 整份搬运**,逻辑一行未改。
—— 从 SimpleNav 的 assets/js/app.js 整份搬运,逻辑主体保留。
它提供:搜索引擎切换、联想词下拉(↓/↑ 与 , . 两组按键)、合集标签页切换、
站点链接打开方式(新标签页 / 当前页,由 body[data-open] 决定)。
⚠️ 联想接口地址来自 window.SIMPLENAV.suggest(服务端按当前短语生成),
不在这个文件里写死。
============================================================
🔴🔴 v24 第 26 批 用户第 4 条:**搬砖时丢了两处选择器 id,导致两个功能全废**。
用户原话:「导航展示页面,选不同的搜索引擎没用。搜索条里面的联想也没有实现。」
根因(两处,都是"HTML 与 JS 对不上",且**都不报错、静默失效**):
① 引擎标签:JS 找 `#engine-tabs`,而 HTML 的容器只有 `class="search-type"`
(没有 id)→ `querySelectorAll` 返回空 → 点击事件**一个都没绑上** →
"选不同的搜索引擎没用"(点完标签视觉上会变吗?连高亮都不会变,
因为高亮也是这个函数做的)。
② 联想下拉:同一段代码继续处理 `#word` / `#search-text`,但**在 ① 挂掉之后
那半段其实仍在执行**(它们各查各的)—— 真正的第二处是 `activateEngine`
与 `askSuggest` 都依赖 `tabs`/`form.dataset.slug`,
而 `form` 的 slug 从来没被设过(因为 activateEngine 没跑),
于是请求 `/nav_suggest.php?slug=&q=…` —— `slug=` 是空的,
服务端虽然能兜底(它按 baidu→bing→360 试),但**前端拿不到东西时也不显示**:
因为 `showWord()` 依赖 `#word`,而 `#word` 是 `<ul>`,在 CSS 里
只有在 `display:block` 时才可见 —— 那段 CSS 依赖 `.s-search` 的一个后代选择器,
而容器 id 丢了之后**连 CSS 一起失配**(连锁反应)。
修法:**给 HTML 补 id**(`#engine-tabs`)而不是改 JS 的选择器 ——
理由是这份 JS 是从 SimpleNav 原样搬来的、将来还要对照原版维护,
改 JS 会让"两边不一样",改 HTML 只是把搬漏的属性补回去。
============================================================ */
/* 简航 SimpleNav —— 前台交互:搜索引擎切换 + 联想下拉 + 合集标签页 */
(function () {
'use strict';
var cfg = window.SIMPLENAV || {};
/* ---------- 搜索引擎切换 ---------- */
var tabs = document.querySelectorAll('#engine-tabs .s-engine');
/* ---------- 搜索引擎切换 ----------
⚠️ 选择器兼容两种写法(`#engine-tabs` 与老模板的 `.search-type`),
这样即使将来模板改回 class、这里也不会再静默失效一次。
**兜底写法不是"多余的"**:它就是这次事故的对策。 */
var tabHost = document.getElementById('engine-tabs')
|| document.querySelector('.search-type');
var tabs = tabHost
? tabHost.querySelectorAll('.s-engine')
: document.querySelectorAll('.s-engine');
var form = document.getElementById('search-form');
var input = document.getElementById('search-text');
function activateEngine(el) {
tabs.forEach(function (t) { t.classList.remove('active'); });
Array.prototype.forEach.call(tabs, function (t) { t.classList.remove('active'); });
el.classList.add('active');
var search = el.getAttribute('data-search');
var param = el.getAttribute('data-param');
@@ -26,11 +55,15 @@
if (form) { form.setAttribute('action', search); form.setAttribute('data-slug', slug); }
if (input) { input.setAttribute('name', param); input.setAttribute('placeholder', ph); }
hideWord();
// 已经输了字就顺手换一份建议(auto 模式下各引擎来源不同)
// 已经输了字就顺手换一份建议(各引擎来源不同)
if (input && input.value.trim() !== '') { askSuggest(); }
}
tabs.forEach(function (el) {
el.addEventListener('click', function () { activateEngine(el); input && input.focus(); });
/* ⚠️ 原版写的是 `tabs.forEach(...)` —— 那是 **NodeList.forEach**,
现代浏览器有、但 `querySelectorAll` 之外的集合(比如下面兜底分支返回的
也可能是数组)不一定有。改用 `Array.prototype.forEach.call` 更稳,
且与本站其它脚本的写法一致(全站都这么写,见 person_picker.js 等)。 */
Array.prototype.forEach.call(tabs, function (el) {
el.addEventListener('click', function () { activateEngine(el); if (input) { input.focus(); } });
});
/* ---------- 联想下拉 ---------- */