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:
+66
-2
@@ -2678,6 +2678,28 @@ body[class] .semi-datepicker-day-inhover { background-color: color-mix(in srgb,
|
||||
.kb-st.is-on { box-shadow: inset 0 0 0 1px currentColor; font-weight: 600; }
|
||||
.kb-due.is-late, .kb-late { color: var(--red); }
|
||||
.kb-ico { white-space: nowrap; }
|
||||
|
||||
/* ---- 看板色点(v24 第 26 批 用户第 3 条)----
|
||||
同一个色点两种用法:
|
||||
· `.kb-dot` —— 看板页**列头**上(列本身就是一个看板);
|
||||
· `.tk-board-dot` —— 首页任务行**看板徽标**里(名字前一个小圆点)。
|
||||
都用 `--bc`(board color)传色:色值由服务端按「用户设过的色,否则按名字派生」算好,
|
||||
CSS 不参与任何色值决策(否则"同一个看板在首页和看板页颜色不一样"迟早发生)。 */
|
||||
.kb-dot,
|
||||
.tk-board-dot {
|
||||
display: inline-block; width: 9px; height: 9px; border-radius: 50%;
|
||||
background: var(--bc, var(--line)); flex: 0 0 auto;
|
||||
}
|
||||
.kb-dot { width: 10px; height: 10px; }
|
||||
/* 首页那个看板徽标:名字前带色点,整体仍是原来那颗浅色 pill */
|
||||
.tk-board { display: inline-flex; align-items: center; gap: 5px; }
|
||||
/* 看板设置页的颜色选择器:native color input 默认很宽,收窄到与输入框同高的一小块 */
|
||||
.input-color {
|
||||
width: 34px; height: 30px; padding: 2px; border: 1px solid var(--line);
|
||||
border-radius: var(--radius-s); background: #fff; cursor: pointer; flex: 0 0 auto;
|
||||
}
|
||||
.input-color::-webkit-color-swatch-wrapper { padding: 0; }
|
||||
.input-color::-webkit-color-swatch { border: 0; border-radius: 4px; }
|
||||
.kb-sub { display: flex; align-items: center; gap: 8px; }
|
||||
.kb-bar { flex: 1 1 auto; height: 5px; border-radius: 999px; background: var(--line-2); overflow: hidden; }
|
||||
.kb-bar i { display: block; height: 100%; background: var(--green); }
|
||||
@@ -4198,6 +4220,19 @@ button.btn, a.btn, summary.btn, .seg-btn, .icon-btn, .rv-act-btn, .cs-btn, .bf-b
|
||||
⚠️ `.ag-row` 的高度就是"一小时"(44px);日程块用**百分比 top** 定位,
|
||||
所以刻度数与日程块的比例天然一致(都在同一个容器里算)。 */
|
||||
.ag-allday { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
|
||||
/* 🔴 v24 第 26 批 用户第 2 条:全天区现在是 `.hd-pane` 的**直接子元素**(不在滚动容器内),
|
||||
必须显式声明"不参与伸缩、也不会被压扁":
|
||||
· `flex: 0 0 auto` —— 它是固定高度的一块,绝不与下面的滚动区抢空间;
|
||||
· `max-height: 33%` + 内部滚动 —— 全天日程可以有很多条(节假日、生日都在里面),
|
||||
全铺开会把时段网格挤到看不见;给个上限,超了自己滚。
|
||||
⚠️ 上限用**百分比**(相对 440px 的 pane)而不是固定 px:
|
||||
窄屏时 pane 只有 320px,固定 140px 会占掉近一半(见下面的媒体查询)。
|
||||
⚠️ 这里也要藏滚动条(与 `.hd-pane-body` 同一理由:用户嫌丑)。 */
|
||||
.ag-allday {
|
||||
flex: 0 0 auto; max-height: 33%; overflow-y: auto; overscroll-behavior: contain;
|
||||
scrollbar-width: none; -ms-overflow-style: none;
|
||||
}
|
||||
.ag-allday::-webkit-scrollbar { width: 0; height: 0; }
|
||||
.ag-allday-item {
|
||||
display: flex; align-items: center; gap: 8px; padding: 5px 8px;
|
||||
background: var(--line-2); border-radius: var(--radius-s); font-size: 13.5px; color: var(--ink);
|
||||
@@ -4271,8 +4306,9 @@ button.btn, a.btn, summary.btn, .seg-btn, .icon-btn, .rv-act-btn, .cs-btn, .bf-b
|
||||
这才是"复选框在文字前面"该有的样子。
|
||||
(`.sub-row` 本来就是 center,不用管它。) */
|
||||
.dash-row:has(.tk-check) { align-items: center; }
|
||||
/* 详情页标题前那颗:标题是 22px 大字,复选框要跟着走中线才不悬空 */
|
||||
.page-head h1:has(> .tk-check) { display: inline-flex; align-items: center; gap: 10px; }
|
||||
/* ⚠️ v24 第 26 批 用户第 5 条:**详情页页头的复选框已去掉**(那颗由「标记完成」按钮取代),
|
||||
所以这里原来那条 `.page-head h1:has(> .tk-check)` 一并删除 ——
|
||||
留一条没有使用者的规则,只会让下一个人以为"页头还该有复选框"。 */
|
||||
|
||||
/* 看板页顶上的「三个状态到底什么意思」(用户第 6 条直接问出来的那句话) */
|
||||
.tk-legend {
|
||||
@@ -4401,3 +4437,31 @@ button.btn, a.btn, summary.btn, .seg-btn, .icon-btn, .rv-act-btn, .cs-btn, .bf-b
|
||||
.wr-cat-bar { flex: 1 1 auto; height: 7px; background: var(--line-2); border-radius: 999px; overflow: hidden; }
|
||||
.wr-cat-bar i { display: block; height: 100%; background: var(--brand); border-radius: 999px; }
|
||||
.wr-cat-v { flex: 0 0 auto; font-size: 12px; }
|
||||
|
||||
/* ============================================================
|
||||
v24 第 26 批 用户第 4 条:新增站点时的「可复用站点」提示块
|
||||
(跨用户复用:别人加过同一个 URL,你就能直接搬过来)
|
||||
============================================================ */
|
||||
.nav-reuse {
|
||||
margin: 0 0 12px; padding: 10px 12px;
|
||||
border: 1px solid var(--line-2); border-left: 3px solid var(--brand-2);
|
||||
border-radius: var(--radius-s); background: #FBF7F2;
|
||||
}
|
||||
.nav-reuse-h { font-size: 13px; color: var(--ink); margin-bottom: 8px; }
|
||||
.nav-reuse-list { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
.nav-reuse-item {
|
||||
display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
|
||||
padding: 5px 10px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
background: #fff; font-size: 13px; color: var(--ink);
|
||||
}
|
||||
.nav-reuse-item:hover { border-color: var(--brand-2); }
|
||||
/* .is-on = 已选中(点一下即选中,再点别的会切换过去) */
|
||||
.nav-reuse-item.is-on {
|
||||
border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand);
|
||||
background: var(--brand-soft, #FDF3EC);
|
||||
}
|
||||
.nav-reuse-item .nav-ico { width: 20px; height: 20px; border-radius: 4px; object-fit: contain; }
|
||||
.nav-reuse-nm { white-space: nowrap; }
|
||||
.nav-reuse-f { font-size: 12px; color: var(--muted); margin-top: 8px; }
|
||||
/* 空 img(没有图标可复用)别占位成一个破图框 */
|
||||
.nav-reuse-item img:not([src]) { visibility: hidden; }
|
||||
|
||||
+41
-8
@@ -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(); } });
|
||||
});
|
||||
|
||||
/* ---------- 联想下拉 ---------- */
|
||||
|
||||
Reference in New Issue
Block a user