v28 第 28 批(12 条):名册分组改标签 / 资源合并为两按钮 / 首页定位与主题色 / 笔记富文本双模式
其中 4 条是**上批遗漏的真 bug**(1/4/8/9),根因已逐条定位:
1. 首页日程没定位到红线 —— 真根因:刻度区间**不含当前时刻** → $showNow=false
→ 红线**整个不渲染**,而定位脚本用同一个越界比例算目标,被 clamp 到底部。
修:把当前小时并进区间端点(现在必然落在区间内)。
2. 「看整月」→「更多日程」+ 日程主题色;3. 「手头在做」→「近期任务」、
「任务看板」→「全部任务」+ 任务主题色(注入 --hd-c,不再写死白底)。
4. 任务复选框提示还在 —— 真根因:**JS 在点击后**给状态徽标挂 title
(`badge.setAttribute('title',…)`),上批只去了静态渲染,静态断言永远抓不到。
5. 名册「分组」→「标签」(用户:一个人可能既是小学同学又是初中同学,没法分组):
新增 person_tags(每人一份、一人多标签),名册改**平铺 + 顶部标签筛选**;
🔴 迁移用**一次性哨兵**(第一版用 NOT EXISTS,实测被"用户清空标签"绕过 → 旧分组名被灌回)。
6. 名册卡片按钮加语义底色。
7. 资源四按钮 → **编辑 / 删除**两颗:三块内容进一个带页签的弹框(信息/附件/共享)。
8. 财务多选数字不变 —— 真根因:前端发 `kinds=a,b`(逗号串),服务端 `(array)` 收成
单元素 → 求交为空 → **静默回落整本账**。修:两种形状都收。
9. 微信读书偶发很慢 —— 真根因:syncNow 扫 60 本 × 每本 1~3 次网关调用(单次超时 20s),
全同步阻塞在列表页请求里。修:总时长预算 + 单次超时 8s + 自动/手动分批。
10. 新增全局可见的联想接口库(6 个实测可用来源)+ 三种新解析类型。
11. 导航右上角「设置」:默认进"添加网址 + 全部网址",四类设置收进 ?set=1 视图。
12. 笔记:段落/清单支持 Markdown(自研渲染器,**不允许原始 HTML**),
实时预览走服务端(前后端只一份规则);底部附件上传;清单多级;
列表改**定尺寸卡片网格**(溢出显示摘要、图片缩放下方);按用户要求**去掉标签侧栏**。
This commit is contained in:
@@ -4571,3 +4571,304 @@ button.btn, a.btn, summary.btn, .seg-btn, .icon-btn, .rv-act-btn, .cs-btn, .bf-b
|
||||
/* 长英文/URL 不要把卡片撑出横向滚动(全站反复栽在这条上) */
|
||||
.note-text, .note-list, .note-title { overflow-wrap: anywhere; }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
v28 用户第 2 / 3 条:首页两块右上角的「更多日程 / 全部任务」按钮
|
||||
要**用所属模块的主题色做背景**(原来一律 .btn-ghost 的白底灰字,
|
||||
与"日程=橙、任务=砖红"的分区色完全看不出关系)。
|
||||
做法:模板把模块色注入 `--hd-c`(见 home.php 的 style 属性),
|
||||
这里只负责"拿这个色当底 + 白字 + 悬停加深"三件事 ——
|
||||
不为日程/任务各写一套(那是两份迟早漂移的样式)。
|
||||
⚠️ 用 color-mix 压暗悬停色而不是写死两个色:模块色在「个人设置」里可改,
|
||||
写死就会出现"用户换了主题色、按钮悬停还是原来的颜色"。
|
||||
============================================================ */
|
||||
.hd-more {
|
||||
background: var(--hd-c, var(--brand));
|
||||
border-color: var(--hd-c, var(--brand));
|
||||
color: #fff;
|
||||
}
|
||||
.hd-more:hover {
|
||||
background: color-mix(in srgb, var(--hd-c, var(--brand)) 82%, #000);
|
||||
border-color: color-mix(in srgb, var(--hd-c, var(--brand)) 82%, #000);
|
||||
color: #fff;
|
||||
}
|
||||
/* 老浏览器不认 color-mix 时的兜底:至少不要变成透明/消失 */
|
||||
@supports not (background: color-mix(in srgb, red 50%, blue)) {
|
||||
.hd-more:hover { background: var(--hd-c, var(--brand)); filter: brightness(.88); }
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
v28 用户第 5 / 6 条:名册「分组」改「标签」+ 卡片按钮要有底色
|
||||
============================================================ */
|
||||
|
||||
/* ---- 顶部标签筛选条(替代原来的分栏)---- */
|
||||
.roster-tagbar {
|
||||
display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
|
||||
margin: 0 0 12px; padding: 10px 12px;
|
||||
border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
background: var(--surface);
|
||||
}
|
||||
.roster-tagbar-k { font-size: 12.5px; color: var(--faint); margin-right: 2px; }
|
||||
.roster-tagbar-clear { margin-left: auto; font-size: 12.5px; }
|
||||
|
||||
/* ---- 平铺列表:卡片单列铺开,不再有"栏"的分隔线 ----
|
||||
⚠️ `.people-grid` 原来在多栏里是 grid;平铺后让它 2 列自适应(宽屏两列、
|
||||
窄屏一列),既不像单列那样长得没边,也不至于把姓名行挤断。
|
||||
用 auto-fill + minmax 而不是写死列数:名册人数从 3 到 1000+ 都用同一套。 */
|
||||
.roster.is-flat .people-grid {
|
||||
display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
@media (max-width: 720px) {
|
||||
.roster.is-flat .people-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* ---- 🔴 用户第 6 条:「名册,每个人后面的按钮,也是要有背景颜色的。」
|
||||
原来三颗按钮全是 .btn-ghost(白底 + 极浅描边),在纸白卡片上几乎看不见边界。
|
||||
给它们各自一个**语义底色**(编辑=品牌淡、标签=中性灰、删除=危险淡),
|
||||
而不是统一刷成一种 —— 一眼能分清哪个是危险动作。 ---- */
|
||||
.person-edit,
|
||||
.person-tag-btn,
|
||||
.person-more-btn {
|
||||
background: var(--line-2);
|
||||
border-color: var(--line);
|
||||
color: var(--ink);
|
||||
}
|
||||
/* 编辑 = 品牌色淡底(主要动作用它) */
|
||||
.person-edit {
|
||||
background: var(--brand-soft, #FDF3EC);
|
||||
border-color: color-mix(in srgb, var(--brand) 28%, transparent);
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
.person-edit:hover { background: color-mix(in srgb, var(--brand) 16%, #fff); }
|
||||
/* 标签 = 中性灰底;有标签时稍深一点,一眼能看出"这个人是有标记的" */
|
||||
.person-tag-btn { background: var(--line-2); color: var(--muted); }
|
||||
.person-tag-btn:hover { background: var(--line); color: var(--ink); }
|
||||
.person-tag-btn.is-none { color: var(--faint); }
|
||||
/* ⋯ = 中性 */
|
||||
.person-more-btn { background: var(--line-2); color: var(--muted); }
|
||||
.person-more-btn:hover { background: var(--line); color: var(--brand); }
|
||||
/* 删除已经是 .btn-danger(自带红底),不动 */
|
||||
|
||||
/* ---- 标签编辑浮层里的候选标签 ---- */
|
||||
.pt-picks { display: flex; flex-wrap: wrap; gap: 6px; }
|
||||
.pt-pick {
|
||||
display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
|
||||
padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px;
|
||||
background: #fff; font-size: 12.5px; color: var(--muted);
|
||||
}
|
||||
.pt-pick:hover { border-color: var(--brand-2); color: var(--brand-ink); }
|
||||
/* 勾上时整颗变实心(不是只动那个小方框)—— 点一下的反馈要一眼看得见 */
|
||||
.pt-pick:has(input:checked) {
|
||||
border-color: var(--brand); background: var(--brand-soft, #FDF3EC);
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
.pt-pick input { accent-color: var(--brand); }
|
||||
|
||||
/* ============================================================
|
||||
v28 用户第 7 条:资源的「编辑」弹框改成带页签(信息 / 附件 / 共享)
|
||||
============================================================ */
|
||||
.res-tabs {
|
||||
display: flex; gap: 4px; padding: 0 16px 10px;
|
||||
border-bottom: 1px solid var(--line); margin-bottom: 12px;
|
||||
}
|
||||
.res-tab {
|
||||
padding: 5px 14px; border: 1px solid transparent; border-radius: var(--radius-s);
|
||||
background: transparent; color: var(--muted); cursor: pointer; font-size: 13.5px;
|
||||
}
|
||||
.res-tab:hover { background: var(--line-2); color: var(--ink); }
|
||||
/* 当前页签:品牌淡底 + 品牌字色(与全站分段控件同一套观感) */
|
||||
.res-tab.is-on {
|
||||
background: var(--brand-soft, #FDF3EC);
|
||||
border-color: color-mix(in srgb, var(--brand) 30%, transparent);
|
||||
color: var(--brand-ink); font-weight: 500;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
v28 用户第 10 条:内置联想接口库(点一下填入表单)
|
||||
============================================================ */
|
||||
.sug-lib { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
|
||||
.sug-lib-item {
|
||||
display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px;
|
||||
padding: 6px 12px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
background: #fff; cursor: pointer; text-align: left;
|
||||
}
|
||||
.sug-lib-item b { font-size: 13px; font-weight: 500; color: var(--ink); }
|
||||
.sug-lib-item span { font-size: 11.5px; color: var(--faint); }
|
||||
.sug-lib-item:hover { border-color: var(--brand-2); }
|
||||
/* 刚被点选的那一个:品牌底 + 品牌边,明确"我选了它" */
|
||||
.sug-lib-item.is-picked {
|
||||
border-color: var(--brand); background: var(--brand-soft, #FDF3EC);
|
||||
}
|
||||
.sug-lib-item.is-picked b { color: var(--brand-ink); }
|
||||
|
||||
/* ============================================================
|
||||
v28 用户第 12 条:笔记 —— 富文本双模式 / 附件 / 多级清单 / 定尺寸卡片网格
|
||||
============================================================ */
|
||||
|
||||
/* ---- 列表页:顶部条(搜索 + 标签),去掉左侧标签栏 ---- */
|
||||
.note-bar { margin-bottom: 12px; }
|
||||
.note-search { margin: 0 0 8px; }
|
||||
.note-tagbar { margin-top: 2px; }
|
||||
|
||||
/* ---- 🔴 定尺寸卡片网格(用户:"一行几个块,但是块大小要确定")----
|
||||
高度**固定**:内容装不下就靠摘要 + 溢出裁切,卡片之间永远整齐。
|
||||
用 auto-fill + minmax 让"一行几个"随宽度自适应,而不是写死列数。 */
|
||||
.note-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.note-card {
|
||||
display: flex; flex-direction: column;
|
||||
/* 固定高度 = 用户要的"块大小确定"。240px 大约放得下:一行头 + 标题 + 3~4 行摘要 + 缩略图 */
|
||||
height: 240px; overflow: hidden;
|
||||
background: var(--surface); border: 1px solid var(--line);
|
||||
border-radius: var(--radius); padding: 12px 14px;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
.note-card:hover { border-color: var(--brand-2); }
|
||||
.note-head { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
|
||||
.note-meta { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1 1 auto; }
|
||||
.note-time { font-size: 11.5px; color: var(--faint); white-space: nowrap; }
|
||||
.note-ops { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
|
||||
.note-ops .inline-form { display: inline; }
|
||||
.note-op {
|
||||
font-size: 12px; padding: 1px 7px; border-radius: 6px; cursor: pointer;
|
||||
border: 1px solid var(--line); background: var(--line-2); color: var(--muted);
|
||||
text-decoration: none; line-height: 1.6;
|
||||
}
|
||||
.note-op:hover { background: var(--line); color: var(--ink); text-decoration: none; }
|
||||
.note-op-del:hover { border-color: var(--red); color: var(--red); background: #FDF2F0; }
|
||||
|
||||
/* 点卡片进编辑(整块可点,但不用 <a> 包全文 —— 里面还有表单与链接) */
|
||||
.note-hit { display: block; flex: 1 1 auto; min-height: 0; overflow: hidden; }
|
||||
.note-hit:hover { text-decoration: none; }
|
||||
.note-title {
|
||||
margin: 8px 0 5px; font-size: 14.5px; font-weight: 500; color: var(--ink);
|
||||
/* 标题最多两行,超出省略 —— 固定高度下不能让它无限长 */
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
||||
}
|
||||
.note-ex {
|
||||
margin: 6px 0 0; font-size: 13px; line-height: 1.6; color: var(--muted);
|
||||
display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
|
||||
}
|
||||
.note-ex-empty { color: var(--faint); font-style: italic; }
|
||||
/* 图片:等比缩放到卡片宽,放在摘要下方(用户:"图片缩放后,放在下面") */
|
||||
.note-thumb { margin-top: 8px; flex: 0 0 auto; overflow: hidden; border-radius: var(--radius-s); }
|
||||
.note-thumb img {
|
||||
width: 100%; height: 88px; object-fit: cover; display: block;
|
||||
border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
}
|
||||
.note-card .note-tags-inline { margin-top: auto; padding-top: 8px; flex: 0 0 auto; }
|
||||
.note-card .note-tag { font-size: 11.5px; padding: 2px 7px; }
|
||||
|
||||
/* ---- 编辑页:模式提示条 ---- */
|
||||
.note-modebar {
|
||||
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
||||
margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--line-2);
|
||||
}
|
||||
.note-modebar code {
|
||||
font-size: 11.5px; background: var(--line-2); padding: 1px 5px;
|
||||
border-radius: 4px; color: var(--ink);
|
||||
}
|
||||
.note-live { margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
|
||||
font-size: 12.5px; color: var(--muted); cursor: pointer; }
|
||||
.note-live input { accent-color: var(--brand); }
|
||||
|
||||
/* ---- 段落的 Markdown 实时预览块 ---- */
|
||||
.note-block-pv {
|
||||
margin-top: 6px; padding: 0 2px; font-size: 14px; line-height: 1.7; color: var(--ink);
|
||||
}
|
||||
.note-block-pv:not(.is-on) { display: none; }
|
||||
/* 预览区左边一条细线,与输入区在视觉上分开(不然分不清哪块是输入、哪块是结果) */
|
||||
.note-block-pv.is-on {
|
||||
border-left: 3px solid var(--brand-soft, #F3D9CB);
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* ---- Markdown 渲染出来的元素(列表页/预览共用同一套)---- */
|
||||
.md-p { margin: 0 0 8px; }
|
||||
.md-p:last-child { margin-bottom: 0; }
|
||||
.md-h { margin: 10px 0 6px; font-weight: 500; color: var(--ink); }
|
||||
h3.md-h { font-size: 16px; }
|
||||
h4.md-h { font-size: 15px; }
|
||||
h5.md-h, h6.md-h { font-size: 14px; }
|
||||
.md-list { margin: 4px 0 8px; padding-left: 22px; }
|
||||
.md-li { margin: 2px 0; }
|
||||
/* 多级清单:子层用空心点,层级一眼可分(用户第 12 条"清单可以多级") */
|
||||
.md-list .md-list { list-style-type: circle; margin: 2px 0 2px; }
|
||||
.md-list .md-list .md-list { list-style-type: square; }
|
||||
.md-quote {
|
||||
margin: 6px 0; padding: 4px 12px; border-left: 3px solid var(--line);
|
||||
color: var(--muted); background: var(--line-2); border-radius: 0 6px 6px 0;
|
||||
}
|
||||
.md-code {
|
||||
background: #F6F4F0; border: 1px solid var(--line); border-radius: 6px;
|
||||
padding: 8px 10px; overflow-x: auto; font-size: 12.5px; line-height: 1.6;
|
||||
font-family: ui-monospace, Consolas, monospace; color: var(--ink);
|
||||
}
|
||||
.md-icode {
|
||||
background: var(--line-2); padding: 1px 5px; border-radius: 4px;
|
||||
font-size: 12.5px; font-family: ui-monospace, Consolas, monospace;
|
||||
}
|
||||
.md-link { color: var(--brand); text-decoration: underline; }
|
||||
.md-hr { border: 0; border-top: 1px solid var(--line); margin: 10px 0; }
|
||||
|
||||
/* ---- 编辑页底部附件区 ---- */
|
||||
.note-files { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
|
||||
.note-file {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
background: #FDFCFA;
|
||||
}
|
||||
.note-file-ico {
|
||||
font-size: 11px; padding: 1px 6px; border-radius: 4px;
|
||||
background: var(--line-2); color: var(--muted); flex: 0 0 auto;
|
||||
}
|
||||
.note-file-nm { flex: 1 1 auto; min-width: 0; font-size: 13.5px; color: var(--ink);
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.note-file-del {
|
||||
flex: 0 0 auto; border: 1px solid var(--line); background: #fff; border-radius: 6px;
|
||||
color: var(--muted); cursor: pointer; padding: 2px 8px; font-size: 12px;
|
||||
}
|
||||
.note-file-del:hover { border-color: var(--red); color: var(--red); }
|
||||
/* 拖放区:虚线框,与全站其它模块的上传区同一观感 */
|
||||
.note-att-drop {
|
||||
border: 1px dashed var(--line); border-radius: var(--radius-s);
|
||||
padding: 14px; text-align: center; background: #FDFCFA;
|
||||
}
|
||||
.note-att-drop.is-over { border-color: var(--brand); background: var(--brand-soft, #FDF3EC); }
|
||||
.note-att-drop input[type=file] { display: none; }
|
||||
.note-att-tip { font-size: 13px; color: var(--muted); }
|
||||
.note-att-tip label { color: var(--brand); cursor: pointer; text-decoration: underline; }
|
||||
|
||||
/* ---- 窄屏:网格收成一列(固定高度在小屏上会显得很挤)---- */
|
||||
@media (max-width: 640px) {
|
||||
.note-grid { grid-template-columns: 1fr; }
|
||||
.note-card { height: auto; min-height: 150px; }
|
||||
}
|
||||
|
||||
/* ---- v28 修:名册卡片在窄屏被"标签按钮"撑破(真机几何探针抓到)----
|
||||
根因:卡片右侧的动作区是一条 flex,里面那颗「标签」按钮的文字是
|
||||
**所有标签拼起来**(`#小学同学 #初中同学 …`),且 `white-space: nowrap` ——
|
||||
标签一多它就无限变宽,把整行、整张卡、整张网格一起顶出视口
|
||||
(实测 360px 下 scrollW=2090,越界元素就是那一串 <a>/<button>)。
|
||||
⇒ 三件事一起做,缺一不可:
|
||||
① 动作区**允许换行**(标签多了折到第二行,而不是往外顶);
|
||||
② 标签按钮**限最大宽度 + 溢出截断**(再长的标签也不会撑破);
|
||||
③ 卡片主体 `min-width: 0`(flex/grid 子项默认 min-width:auto,不肯收缩)。 */
|
||||
.person-actions { flex-wrap: wrap; justify-content: flex-end; }
|
||||
.person-tag-btn {
|
||||
max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.person { min-width: 0; }
|
||||
.person-main { min-width: 0; }
|
||||
.person .pb { min-width: 0; }
|
||||
/* 窄屏更严:动作区整体不参与撑宽,标签按钮再收一档 */
|
||||
@media (max-width: 720px) {
|
||||
.person-actions { max-width: 100%; }
|
||||
.person-tag-btn { max-width: 110px; }
|
||||
/* 姓名那一栏允许收缩并截断,否则长名字也会顶破 */
|
||||
.pname { overflow-wrap: anywhere; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user