2026-09-30 00:49:53 +08:00
|
|
|
|
/* ============================================================
|
|
|
|
|
|
家书 FamilyBook · 界面样式
|
|
|
|
|
|
配色取自图标:宣纸米 / 砖红封面 / 深褐书脊 / 纸白
|
|
|
|
|
|
原则:扁平、留白充足、字重克制(正文 400,标题 500-600)
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
:root {
|
|
|
|
|
|
--paper: #F7F3EA;
|
|
|
|
|
|
--surface: #FFFFFF;
|
|
|
|
|
|
--ink: #2C231D;
|
|
|
|
|
|
--muted: #7E6B5A;
|
|
|
|
|
|
--faint: #A8988A;
|
|
|
|
|
|
--brand: #A84A28;
|
|
|
|
|
|
--brand-2: #C96F45;
|
|
|
|
|
|
--brand-ink:#6E3820;
|
|
|
|
|
|
--green: #6F9E5C;
|
|
|
|
|
|
--red: #C0533F;
|
2026-10-10 22:13:20 +08:00
|
|
|
|
/* 🔴 v40(用户 2026-10-10):「影院管理部分…编辑使用蓝色的背景,删除使用红色的背景。」
|
|
|
|
|
|
⇒ 新增一个中性的"操作蓝"(不是链接蓝、也不是模块品牌色)—— 它是**语义色**:
|
|
|
|
|
|
蓝=编辑、红=删除,全站统一,跟着模块换肤也不该变。
|
|
|
|
|
|
⚠️ 暖纸底上要够暗才压得住白字:这里取 #2F6FB0(对比度 ≈ 4.9:1)。 */
|
|
|
|
|
|
--blue: #2F6FB0;
|
2026-10-11 10:12:11 +08:00
|
|
|
|
/* 🔴 v41(用户 2026-10-10):旅程详情页四种动作按钮各一种底色
|
|
|
|
|
|
(计划=蓝 / 实际=绿 / 编辑=黄 / 删除=红)。蓝、绿(--green)、红已有;
|
|
|
|
|
|
这里补"编辑黄"。
|
|
|
|
|
|
⚠️ 纯黄(#FFD400 之类)配白字几乎看不清(对比度 ≈ 1.3:1)。
|
|
|
|
|
|
取偏琥珀的深黄 #B8860B(DarkGoldenrod 系),暖纸底上白字对比度 ≈ 3.6:1,
|
|
|
|
|
|
且不会和品牌暖棕 (`--brand` #A84A28) 混淆 —— 后者明显更红。
|
|
|
|
|
|
⚠️ "实际=绿"用既有的 `--green` (#6F9E5C),它在白字下对比度 ≈ 3.0:1,
|
|
|
|
|
|
深一步更保险 —— 见 `.btn-actual` 里单独取的 #4E7C3F(≈ 4.6:1)。 */
|
|
|
|
|
|
--yellow: #B8860B;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
--line: rgba(44, 35, 29, .10);
|
|
|
|
|
|
--line-2: rgba(44, 35, 29, .06);
|
|
|
|
|
|
--radius: 16px;
|
|
|
|
|
|
--radius-s: 10px;
|
|
|
|
|
|
--shadow: 0 1px 2px rgba(44, 35, 29, .05);
|
|
|
|
|
|
--shadow-l: 0 4px 16px rgba(44, 35, 29, .08);
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 动作按钮的统一度量 ----
|
|
|
|
|
|
用户提过三次「设置按钮和记一场电影按钮高度要一致」。为杜绝再犯,
|
|
|
|
|
|
这里把按钮高度拆成 4 个变量,并算出唯一的高度:
|
|
|
|
|
|
--act-h = 上下内边距 + 行高 + 上下边框 = 9*2 + 14*1.7 + 1*2 = 43.8px
|
|
|
|
|
|
文字按钮靠 padding + line-height 自然撑到这个高度;
|
|
|
|
|
|
**只有图标的方形按钮**(.btn-icon)显式写高度,但取的是同一个 --act-h,
|
|
|
|
|
|
这样两边永远相等,改一处就同步。 */
|
|
|
|
|
|
--act-pad-y: 9px;
|
|
|
|
|
|
--act-pad-x: 16px;
|
|
|
|
|
|
--act-font: 14px;
|
|
|
|
|
|
--act-line: 1.7;
|
|
|
|
|
|
--act-h: calc(var(--act-pad-y) * 2 + var(--act-font) * var(--act-line) + 1px * 2);
|
2026-09-30 00:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
|
|
|
|
|
|
|
|
html, body { height: 100%; }
|
|
|
|
|
|
|
|
|
|
|
|
body {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
background: var(--paper);
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
font: 15px/1.7 -apple-system, BlinkMacSystemFont, "PingFang SC",
|
|
|
|
|
|
"Microsoft YaHei", "Hiragino Sans GB", sans-serif;
|
|
|
|
|
|
-webkit-font-smoothing: antialiased;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
a { color: var(--brand); text-decoration: none; }
|
|
|
|
|
|
a:hover { text-decoration: underline; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 顶栏 ---------------- */
|
|
|
|
|
|
.topbar {
|
|
|
|
|
|
position: sticky; top: 0; z-index: 20;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border-bottom: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.topbar-inner {
|
|
|
|
|
|
max-width: 1080px; margin: 0 auto; padding: 0 24px;
|
|
|
|
|
|
height: 60px; display: flex; align-items: center; gap: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.brand { display: flex; align-items: center; gap: 10px; color: var(--ink); }
|
|
|
|
|
|
.brand:hover { text-decoration: none; }
|
|
|
|
|
|
.brand img { width: 30px; height: 30px; border-radius: 8px; display: block; }
|
|
|
|
|
|
.brand span { font-size: 16px; font-weight: 600; letter-spacing: .5px; }
|
|
|
|
|
|
|
|
|
|
|
|
.nav { display: flex; gap: 4px; margin-left: 8px; }
|
|
|
|
|
|
.nav a {
|
|
|
|
|
|
padding: 6px 12px; border-radius: 999px; color: var(--muted);
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav a:hover { background: var(--line-2); text-decoration: none; }
|
|
|
|
|
|
.nav a.on { background: var(--brand); color: #fff; }
|
|
|
|
|
|
|
|
|
|
|
|
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 12px; }
|
|
|
|
|
|
.who { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 14px; }
|
2026-09-30 11:06:22 +08:00
|
|
|
|
/* 姓名 + 头像是个下拉菜单的「把手」——hover 时给点反馈,让人知道它可点 */
|
|
|
|
|
|
.who-menu { position: relative; }
|
|
|
|
|
|
.who-menu > summary { list-style: none; cursor: pointer; padding: 4px 6px; border-radius: 999px; }
|
|
|
|
|
|
.who-menu > summary::-webkit-details-marker { display: none; }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.who-menu > summary:hover { } /* 统一段处理 */
|
2026-09-30 11:06:22 +08:00
|
|
|
|
.who-menu > summary:hover .who-name { color: var(--brand); }
|
|
|
|
|
|
.who-menu[open] > summary { background: var(--line-2); }
|
|
|
|
|
|
.who-menu[open] > summary .caret { transform: rotate(180deg); }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.who img { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; }
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.who img { transition: box-shadow .15s ease; }
|
2026-09-30 11:06:22 +08:00
|
|
|
|
.who-menu > summary:hover img { box-shadow: 0 0 0 2px var(--brand-2); }
|
|
|
|
|
|
/* 那个小三角:没有它,用户不知道"名字能点开" */
|
|
|
|
|
|
.caret {
|
|
|
|
|
|
width: 0; height: 0; margin-left: -2px;
|
|
|
|
|
|
border-left: 4px solid transparent; border-right: 4px solid transparent;
|
|
|
|
|
|
border-top: 5px solid var(--faint);
|
|
|
|
|
|
transition: transform .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.menu-list {
|
|
|
|
|
|
position: absolute; right: 0; top: calc(100% + 8px); z-index: 30;
|
|
|
|
|
|
min-width: 148px; padding: 6px;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius-s); box-shadow: var(--shadow-l);
|
|
|
|
|
|
display: flex; flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
.menu-list a {
|
|
|
|
|
|
padding: 8px 12px; border-radius: 8px; color: var(--ink);
|
|
|
|
|
|
font-size: 14px; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.menu-list a:hover { background: var(--line-2); text-decoration: none; color: var(--brand); }
|
|
|
|
|
|
/* 退出放在最下面并隔一条线:它是"离开",和上面几个"改点什么"不是一类动作 */
|
|
|
|
|
|
.menu-list .menu-exit {
|
|
|
|
|
|
margin-top: 4px; padding-top: 9px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
border-radius: 0 0 8px 8px; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.menu-list .menu-exit:hover { color: var(--brand); }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
/* ---- 观影页的「设置」下拉:图标按钮 + 永远贴右 ----
|
|
|
|
|
|
用户明确要求(2026-10-01):
|
|
|
|
|
|
· 去掉「设置」二字,只留**三条横线**图标(☰);
|
|
|
|
|
|
· 在**所有页面都排在最右侧**(位置统一);
|
|
|
|
|
|
· 点开后的每条条目,**文字前都要有图标**;
|
|
|
|
|
|
· 除设置外,其它按钮都要**有颜色**,跟设置区分开。
|
|
|
|
|
|
贴右的做法:`margin-left:auto` 把它推到动作区最右端 —— 这样无论各页把片段
|
|
|
|
|
|
require 在 actions 的哪个位置(有的写在最前、有的写在最后),它都贴右,
|
|
|
|
|
|
不必逐页调顺序,也就不会有"某个页面漏了"的情况。 */
|
|
|
|
|
|
.movie-set { position: relative; margin-left: auto; }
|
2026-10-01 12:11:43 +08:00
|
|
|
|
.movie-set > summary {
|
2026-10-01 19:35:48 +08:00
|
|
|
|
list-style: none; cursor: pointer; display: inline-flex; align-items: center;
|
|
|
|
|
|
justify-content: center; gap: 6px;
|
2026-10-01 12:11:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
.movie-set > summary::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.movie-set[open] > summary { border-color: var(--brand); color: var(--brand); }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* 方形图标按钮:只有图标、无文字。高度**必须**取 --act-h,
|
|
|
|
|
|
与「记一场电影」等实心按钮同高(那个高度由 --act-pad-y/--act-font/--act-line 推出)。
|
|
|
|
|
|
⚠️ 别在这里另写一个数字(曾写死 40px,比文字按钮的 43.8px 矮了 3.8px,被用户连续投诉)。 */
|
|
|
|
|
|
.btn-icon {
|
|
|
|
|
|
background: #fff; color: var(--ink); border: 1px solid var(--line);
|
|
|
|
|
|
padding: 0 !important; width: var(--act-h); height: var(--act-h); min-width: var(--act-h);
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.btn-icon:hover { color: var(--brand); border-color: var(--brand); } /* 底色交给统一段 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.btn-icon svg { display: block; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 观影设置菜单:从右上角改成**按钮下方右对齐**(按钮贴右,菜单也贴右才不会跑出屏外) */
|
|
|
|
|
|
.movie-set .menu-list { left: auto; right: 0; top: calc(100% + 8px); }
|
|
|
|
|
|
.movie-set .menu-list a { display: flex; align-items: center; gap: 10px; }
|
|
|
|
|
|
.movie-set .menu-list a .mi { flex: 0 0 16px; color: var(--muted); }
|
|
|
|
|
|
.movie-set .menu-list a:hover .mi,
|
|
|
|
|
|
.movie-set .menu-list a.on .mi { color: currentColor; }
|
2026-10-01 12:11:43 +08:00
|
|
|
|
.movie-set .menu-list a.on { color: var(--brand); background: var(--line-2); }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 日程页的设置下拉(v24 用户 2026-10-03 第 4、5 条)----
|
|
|
|
|
|
它比观影/任务那个 ☰ 内容多:里面有个**表单**(默认视图 + 显示哪些本子)。
|
|
|
|
|
|
本子清单会随共享/新建变长,所以给列表一个最大高度 + 滚动,
|
|
|
|
|
|
否则菜单会顶出屏幕、底下的「保存」按钮够不着。 */
|
|
|
|
|
|
.cal-set .menu-list { min-width: 260px; max-width: min(320px, 92vw); }
|
|
|
|
|
|
.cal-set-list { padding: 10px; gap: 0; }
|
|
|
|
|
|
.cal-set-form { display: block; }
|
|
|
|
|
|
.cal-set-block { padding: 6px 2px; }
|
|
|
|
|
|
.cal-set-block + .cal-set-block { border-top: 1px solid var(--line-2); margin-top: 4px; }
|
|
|
|
|
|
.cal-set-h { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
|
|
|
|
|
|
.cal-set-views { display: flex; gap: 12px; flex-wrap: wrap; }
|
|
|
|
|
|
.cal-set-view { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; cursor: pointer; }
|
|
|
|
|
|
.cal-set-view input { accent-color: var(--brand); }
|
|
|
|
|
|
/* 本子清单:最多占 42vh,超了内部滚动 —— 菜单本身不滚,否则保存按钮会被推出可视区 */
|
|
|
|
|
|
.cal-set-books { max-height: 42vh; overflow-y: auto; }
|
|
|
|
|
|
.cal-set-book {
|
|
|
|
|
|
display: flex; align-items: center; gap: 7px; padding: 5px 4px;
|
|
|
|
|
|
font-size: 13px; cursor: pointer; border-radius: 6px; white-space: normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-set-book:hover { background: var(--line-2); }
|
|
|
|
|
|
.cal-set-book input { accent-color: var(--brand); flex: 0 0 auto; }
|
|
|
|
|
|
.cal-set-book .color-preview { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
|
|
|
|
|
|
.cal-set-book .cal-name { overflow: hidden; text-overflow: ellipsis; }
|
|
|
|
|
|
.cal-set-book .node-badge { margin-left: auto; flex: 0 0 auto; }
|
|
|
|
|
|
.cal-set-foot { margin-top: 10px; }
|
|
|
|
|
|
.cal-set-foot .btn { width: 100%; justify-content: center; }
|
|
|
|
|
|
.cal-set-links { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line-2); }
|
|
|
|
|
|
.cal-set-links a { display: flex; align-items: center; gap: 10px; white-space: normal; }
|
|
|
|
|
|
.cal-set-links a .mi { flex: 0 0 16px; color: var(--muted); }
|
|
|
|
|
|
.cal-set-links a:hover .mi { color: currentColor; }
|
|
|
|
|
|
|
2026-10-14 14:30:37 +08:00
|
|
|
|
/* 点了日历空白处就建日程(能力保留,见 templates/calendar/index.php 的 data-new-at)。
|
|
|
|
|
|
🔴 v48(用户 2026-10-14 第 3 条):「现在鼠标放在视图上时,变成了一个十字。
|
|
|
|
|
|
我感觉这个没必要,不用有这样的变化。」
|
|
|
|
|
|
⇒ **去掉十字光标**。原来给 `.rt-writable`(能写的人)挂 `cursor: crosshair`
|
|
|
|
|
|
是想"让人看出这里能点",但用户明确不要这个视觉变化。
|
|
|
|
|
|
⚠️ 只删光标、**不删能力**:点击建日程的 JS 与 `data-new-at` 一律不动
|
|
|
|
|
|
(那是第 2 条要修好、而不是要撤掉的东西)。
|
|
|
|
|
|
⚠️ 连 `.rt-writable` 类本身也留着 —— 它还被别处引用,且是"这个人能不能写"
|
|
|
|
|
|
这一状态在 DOM 上的标记位,删类名会牵连样式与断言。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.link-quiet { color: var(--muted); font-size: 14px; }
|
|
|
|
|
|
.link-quiet:hover { color: var(--brand); }
|
2026-10-14 14:30:37 +08:00
|
|
|
|
/* 长得像链接的**按钮**(v48)。`.link-quiet` 本来是给 <a>/<summary> 写的,
|
|
|
|
|
|
直接套在 <button> 上会带上浏览器的灰底/边框/内边距 ⇒ 与旁边的链接不一致。
|
|
|
|
|
|
这里把按钮的外观清成纯文字,只保留"可点"的观感(颜色/下划线走 .link-quiet)。 */
|
|
|
|
|
|
button.btn-inline {
|
|
|
|
|
|
background: none; border: 0; padding: 0; margin: 0;
|
|
|
|
|
|
font: inherit; line-height: inherit; cursor: pointer;
|
|
|
|
|
|
}
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
/* 顶栏里的文字一律不许换行 —— 一换行就是「首/页」「名/册」竖排,很难看 */
|
|
|
|
|
|
.nav a, .topbar-right a, .who-name { white-space: nowrap; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 布局 ---------------- */
|
|
|
|
|
|
.container { max-width: 1080px; margin: 0 auto; padding: 28px 24px 64px; }
|
|
|
|
|
|
.container-narrow { max-width: 560px; margin: 0 auto; padding: 28px 24px 64px; }
|
|
|
|
|
|
|
|
|
|
|
|
.page-head { display: flex; align-items: flex-end; gap: 16px; margin-bottom: 20px; }
|
|
|
|
|
|
.page-head h1 { font-size: 22px; font-weight: 600; margin: 0; }
|
|
|
|
|
|
.page-head .sub { color: var(--muted); font-size: 14px; }
|
2026-10-01 17:42:15 +08:00
|
|
|
|
.page-head .actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
/* ---- 页头动作区的完整规格见**文件靠后**的「页头动作区」一节 ----
|
|
|
|
|
|
刻意放后面:.btn / .btn-ghost / .btn-icon 等基类定义在文件中部,
|
|
|
|
|
|
CSS 同特异性「后写的赢」——放这里会被它们覆盖(踩过:设置按钮被染成品牌底、
|
|
|
|
|
|
btn-ghost 仍是白的)。此处只留布局,样式集中在后面一处,便于对照。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
.section { margin-top: 28px; }
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
font-size: 15px; font-weight: 600; margin: 0 0 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.section-title .hint { font-weight: 400; color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 卡片 ---------------- */
|
|
|
|
|
|
.card {
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-pad { padding: 20px; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
/* 相邻的两块之间一定要有缝 —— 影院管理页「添加影院」与「影院列表」、
|
|
|
|
|
|
年度报告的几张卡,曾经紧贴成一个整块,看不出是两个东西。
|
|
|
|
|
|
统一在这里给间距,而不是每个页面各写一次(写一次就会漏一处)。 */
|
|
|
|
|
|
.card + .card { margin-top: 18px; }
|
|
|
|
|
|
/* ⚠️ 上面**只写 .card + .card**:.section 自己有 margin-top:28px,
|
|
|
|
|
|
若在这里再写 `.card + .section { margin-top:18px }`,特异性 0,2,0 会压过
|
|
|
|
|
|
`.section` 的 0,1,0,反而把原本 28px 的间距改小 —— 修 A 不能顺手弄坏 B。 */
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* 🔴🔴 v24 第 25 批 用户第 3 条:**并排的两块不该再吃这条"相邻间距"**。
|
|
|
|
|
|
用户原话:「日程和任务看板,两个模块,现在有点错位,一个高,一个低,
|
|
|
|
|
|
应该完全一样才对。」
|
|
|
|
|
|
|
|
|
|
|
|
根因(实测,不是猜):`.home-duo` 里左右两块**都是 `.card`**、且在 DOM 里互为
|
|
|
|
|
|
紧邻兄弟 → `.card + .card` 命中**第二块** → 给它加了 `margin-top:18px`。
|
|
|
|
|
|
grid 的 `align-items: stretch` 让两块**高度**相等(那个数是对的),
|
|
|
|
|
|
但第二块被整体推下去 18px —— 于是"一样高、却一高一低"。
|
|
|
|
|
|
(我上一版只调了 `.home-duo` 的 align-items 与高度,没动这条,
|
|
|
|
|
|
真机探针才把 18px 这个偏移量量出来 —— 光看代码是看不出来的。)
|
|
|
|
|
|
|
|
|
|
|
|
⇒ 并排容器里的 `.card` 一律不吃相邻间距(间距由 `gap` 统一给)。
|
|
|
|
|
|
用 `:first-child` 之外的兄弟选择器把它们点掉,且**特异性要比 0,2,0 高**。 */
|
|
|
|
|
|
.home-duo > .card { margin-top: 0; }
|
|
|
|
|
|
.home-duo > .card + .card { margin-top: 0; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
/* 首页头图 */
|
|
|
|
|
|
.hero {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); box-shadow: var(--shadow);
|
|
|
|
|
|
padding: 26px 28px;
|
|
|
|
|
|
display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hero-logo { width: 64px; height: 64px; border-radius: 16px; flex: 0 0 auto; }
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.hero-main { flex: 1 1 240px; min-width: 0; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.hero h1 { font-size: 24px; font-weight: 600; margin: 0 0 4px; }
|
|
|
|
|
|
.hero .motto { color: var(--muted); margin: 0; font-size: 14px; }
|
2026-09-30 09:44:55 +08:00
|
|
|
|
/* 那句小字到底是谁的:自己写的那句要标一下,否则用户会以为这是系统统一发的 */
|
|
|
|
|
|
.motto-from {
|
|
|
|
|
|
display: inline-block; margin-left: 6px; padding: 0 7px;
|
|
|
|
|
|
border-radius: 999px; background: var(--line-2);
|
|
|
|
|
|
font-size: 11px; color: var(--faint);
|
|
|
|
|
|
}
|
|
|
|
|
|
.motto-edit { margin-left: 8px; font-size: 12px; color: var(--brand-2); white-space: nowrap; }
|
|
|
|
|
|
/* 详情页顶部引用本人的一句话 */
|
|
|
|
|
|
.motto-line {
|
|
|
|
|
|
margin: -8px 0 16px; padding-left: 12px;
|
|
|
|
|
|
border-left: 3px solid var(--brand-2);
|
|
|
|
|
|
color: var(--muted); font-size: 14px;
|
|
|
|
|
|
}
|
2026-10-03 11:30:48 +08:00
|
|
|
|
/* ⚠️ .hero-stats / .stat 已随用户 2026-10-03 第 3 条撤掉首页那三个统计,
|
|
|
|
|
|
这里保留规则本身(其它页面可能还在用 .stat 这个类名),不再由首页引用。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.hero-stats { margin-left: auto; display: flex; gap: 28px; }
|
|
|
|
|
|
.stat { text-align: center; }
|
|
|
|
|
|
.stat b { display: block; font-size: 24px; font-weight: 600; line-height: 1.2; }
|
|
|
|
|
|
.stat span { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
|
2026-10-03 11:30:48 +08:00
|
|
|
|
/* 用户第 3 条:标题下那句个人 slogan */
|
|
|
|
|
|
.hero-slogan { color: var(--muted); margin: 4px 0 0; font-size: 14px; }
|
|
|
|
|
|
/* 用户第 3 条:「我的资料 / 我的家谱」换成**图标按钮**(原来是一排文字按钮)。
|
|
|
|
|
|
margin-left:auto 把它推到最右,与原来统计块的位置一致。 */
|
|
|
|
|
|
.hero-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
|
|
|
|
|
.icon-btn {
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
width: 40px; height: 40px; border-radius: 12px;
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--surface); color: var(--muted);
|
|
|
|
|
|
transition: border-color .15s ease, color .15s ease, background .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.icon-btn:hover {
|
2026-10-06 03:14:18 +08:00
|
|
|
|
color: var(--brand); border-color: var(--brand-2);
|
|
|
|
|
|
/* 底色交给文末「全站悬停统一」段(中性薄雾) */
|
|
|
|
|
|
background: var(--hov-veil, rgba(44,35,29,.05));
|
2026-10-03 11:30:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
.icon-btn svg { display: block; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 用户第 3 条:首页的统计信息块(问候 + 天气 + 几个数字) ---- */
|
2026-10-07 05:52:40 +08:00
|
|
|
|
/* ⚠️ v24 第 24 批:这里原有 6 条 `.home-brief*` 旧规则(纵向排列的问候/天气/数字),
|
|
|
|
|
|
本批把首页信息面板改成"左边内容 + 右边天气贴右端"的横排结构后,
|
|
|
|
|
|
那 6 条**全部成了死样式**(模板里已经没有任何元素用 home-brief-hello /
|
|
|
|
|
|
home-brief-weather / home-brief-stats / w-icon / w-temp / w-desc)。
|
|
|
|
|
|
⇒ 就地删掉,不留"两处定义同一个东西":
|
|
|
|
|
|
上批(第 23 批)就是因为"末尾追加、旧规则留着",漏了 flex-direction,
|
|
|
|
|
|
四个按钮竖排把标题行撑到 175px —— 那个坑的成因正是**旧规则没删**。
|
|
|
|
|
|
新结构见文件末尾「v24 第 24 批 …首页信息面板」那一段(.hb-* / .hb-weather)。 */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 用户第 3 条:首页的模块小结卡 ---- */
|
|
|
|
|
|
.mod-cards {
|
|
|
|
|
|
display: grid; gap: 12px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.mod-card {
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 6px;
|
|
|
|
|
|
padding: 14px 16px; border-radius: var(--radius);
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--surface);
|
|
|
|
|
|
border-left: 3px solid var(--mc, var(--brand));
|
|
|
|
|
|
color: var(--ink); text-decoration: none;
|
|
|
|
|
|
transition: box-shadow .15s ease, border-color .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mod-card:hover { box-shadow: var(--shadow); text-decoration: none; }
|
|
|
|
|
|
.mod-card-head { display: flex; align-items: center; gap: 8px; color: var(--mc, var(--brand)); }
|
|
|
|
|
|
.mod-card-icon { display: inline-flex; flex: 0 0 auto; }
|
|
|
|
|
|
.mod-card-name { font-size: 13px; font-weight: 600; }
|
|
|
|
|
|
.mod-card-big { font-size: 20px; font-weight: 600; color: var(--ink); }
|
|
|
|
|
|
.mod-card-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
|
|
|
|
.mod-card-lines li { font-size: 12.5px; color: var(--muted); }
|
|
|
|
|
|
|
2026-09-30 00:49:53 +08:00
|
|
|
|
/* ---------------- 成员卡 ---------------- */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
/* 用户 2026-10-03 第 4 条:名册从「卡片网格」改成**竖向列表**——
|
|
|
|
|
|
一行一个人,左边头像、中间姓名+关系+手机号/生日、右边操作。
|
|
|
|
|
|
列表形态下拖动排序也更直观(上下移动,不会像网格那样左右跳)。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.people-grid {
|
2026-10-03 11:30:48 +08:00
|
|
|
|
display: flex; flex-direction: column; gap: 8px; margin-top: 4px;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
}
|
2026-10-04 08:56:40 +08:00
|
|
|
|
/* ⚠️ 整行是**一条 flex**:[拖柄] [头像+信息(占满剩下的)] [右侧动作]。
|
|
|
|
|
|
原来右侧的「编辑 / ⋯」各自写死 right:46px / right:8px 绝对定位,
|
|
|
|
|
|
于是再往里加第三个按钮只能继续猜偏移、且「分组」按钮宽度随分组名变化必然重叠;
|
|
|
|
|
|
改 flex 之后按钮自然排开,姓名那边也不用靠 padding-right 让位了。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.person {
|
2026-10-04 08:56:40 +08:00
|
|
|
|
display: flex; align-items: stretch; color: var(--ink); position: relative;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
2026-10-03 11:30:48 +08:00
|
|
|
|
border-radius: var(--radius-s);
|
|
|
|
|
|
transition: border-color .15s ease, box-shadow .15s ease;
|
2026-10-04 08:56:40 +08:00
|
|
|
|
/* v24 第 9 批 #5:千人名册不「卡死」的关键 —— 屏外的卡片浏览器直接跳过
|
|
|
|
|
|
布局/绘制(4 万+ DOM 节点的排版是一次性成本的大头)。
|
|
|
|
|
|
contain-intrinsic-size 给屏外卡片一个估算高度撑滚动条,
|
|
|
|
|
|
auto 前缀让浏览器记住真实渲染高度,滚过后就精确了。
|
|
|
|
|
|
⚠️ 拖动排序用的是实时 getBoundingClientRect:目标被自动滚进视口时
|
|
|
|
|
|
content-visibility 会立刻出真实布局,落点计算不受影响(drag probe 已验证)。 */
|
|
|
|
|
|
content-visibility: auto;
|
|
|
|
|
|
contain-intrinsic-size: auto 68px;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
}
|
2026-10-03 11:30:48 +08:00
|
|
|
|
.person:hover { border-color: var(--brand-2); box-shadow: var(--shadow); }
|
|
|
|
|
|
/* 头像:列表里用小方图(正方形、cover 裁切),不再是整块大图 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.person .ph {
|
2026-10-03 11:30:48 +08:00
|
|
|
|
background: #F1E7D6; overflow: hidden;
|
|
|
|
|
|
width: 52px; height: 52px; border-radius: 8px; flex: 0 0 auto;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
.person .ph img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
2026-10-03 11:30:48 +08:00
|
|
|
|
.person .person-main {
|
|
|
|
|
|
display: flex; align-items: center; gap: 12px;
|
|
|
|
|
|
padding: 10px 12px; color: var(--ink); text-decoration: none;
|
2026-10-04 08:56:40 +08:00
|
|
|
|
flex: 1 1 auto; min-width: 0; /* 剩下的宽度都给它,按钮那头不挤它 */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
.person .pb { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.person .pname { font-weight: 600; font-size: 15px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
|
|
|
|
.person .pmeta { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
|
|
|
|
|
|
/* 中间那几个"重要信息":手机 / 生日 */
|
|
|
|
|
|
.person .pfacts { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 4px; font-size: 13px; }
|
|
|
|
|
|
.person .pfact { color: var(--ink); display: inline-flex; align-items: baseline; gap: 5px; }
|
|
|
|
|
|
.person .pfact-k {
|
|
|
|
|
|
color: var(--muted); font-size: 11px; padding: 1px 5px; border-radius: 4px;
|
|
|
|
|
|
background: var(--line-2);
|
|
|
|
|
|
}
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* ⚠️⚠️ 过滤用的行必须能真的藏起来。
|
|
|
|
|
|
`[hidden]` 的 display:none 是**浏览器默认样式**,优先级最低 —— 只要作者样式里
|
|
|
|
|
|
给同一个元素写了 display(.person 是 display:block、.pp-item 是 flex、
|
|
|
|
|
|
.att-item 是 inline-flex…),就会把它盖掉:元素"标注了 hidden 却照样显示",
|
|
|
|
|
|
于是「输入即筛选」看着完全没反应(列表一条都不少)。
|
|
|
|
|
|
这个坑本项目已经踩过两次(.att-item、.pp-item),所以统一写成一条通则:
|
|
|
|
|
|
凡是靠 [hidden] 隐藏的列表行,都必须在作者样式里显式再声明一次。 */
|
|
|
|
|
|
[data-search][hidden],
|
|
|
|
|
|
.pick-row[hidden],
|
|
|
|
|
|
.person[hidden] { display: none !important; }
|
|
|
|
|
|
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.badge {
|
|
|
|
|
|
display: inline-block; padding: 1px 8px; border-radius: 999px;
|
|
|
|
|
|
font-size: 11px; font-weight: 500; line-height: 1.7;
|
|
|
|
|
|
background: var(--line-2); color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.badge-admin { background: #F6E3D7; color: var(--brand-ink); }
|
|
|
|
|
|
.badge-open { background: #E6F0DC; color: #4A7226; }
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.badge-me { background: var(--brand); color: #fff; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
2026-09-30 09:44:55 +08:00
|
|
|
|
/* 生日条 —— 一个人可能同时出两条(农历与阳历不在同一天),
|
|
|
|
|
|
落在同一天时并成一条、kinds 里挂多个标签,正好对应"要分别提醒"。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.bdays { display: flex; gap: 12px; flex-wrap: wrap; }
|
|
|
|
|
|
.bday {
|
2026-09-30 09:44:55 +08:00
|
|
|
|
display: flex; align-items: center; gap: 12px;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
2026-09-30 09:44:55 +08:00
|
|
|
|
border-radius: var(--radius); padding: 10px 18px 10px 10px;
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
color: var(--ink); text-decoration: none;
|
|
|
|
|
|
transition: transform .15s ease, box-shadow .15s ease;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
}
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.bday:hover { transform: translateY(-2px); box-shadow: var(--shadow-l); text-decoration: none; }
|
|
|
|
|
|
.bday img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.bday b { font-weight: 500; }
|
|
|
|
|
|
.bday .d { color: var(--brand); font-size: 13px; }
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.bday-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 3px; }
|
|
|
|
|
|
.bday-date { font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
/* 「身份证生日 / 阳历生日 / 农历生日」的标签,首页与详情页共用 */
|
|
|
|
|
|
.bd-kind {
|
|
|
|
|
|
display: inline-block; padding: 0 7px; border-radius: 999px;
|
|
|
|
|
|
font-size: 11px; line-height: 1.8;
|
|
|
|
|
|
background: var(--line-2); color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.bd-kind-id { background: #E6F0DC; color: #4A7226; }
|
|
|
|
|
|
.bd-kind-solar { background: #F6E3D7; color: var(--brand-ink); }
|
|
|
|
|
|
.bd-kind-lunar { background: #E8E4F2; color: #55477E; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 详情页的三个生日 */
|
|
|
|
|
|
.bd-list { list-style: none; margin: 0; padding: 0; }
|
|
|
|
|
|
.bd-list li { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; flex-wrap: wrap; }
|
|
|
|
|
|
.bd-list .bd-val { font-variant-numeric: tabular-nums; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---------------- 表单 ---------------- */
|
|
|
|
|
|
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
2026-10-01 12:11:43 +08:00
|
|
|
|
/* ⚠️ min-width:0 是必需的(v11 实测踩到):.field 是 grid 项,默认 min-width:auto
|
|
|
|
|
|
会被内部 <select> 的**最长选项文字**撑开 —— 高级搜索页在 360/375px 下整页横向溢出
|
|
|
|
|
|
(scrollW 390 > clientW 360),而「影院」下拉正是长选项。给了 0 之后列才能收进版心,
|
|
|
|
|
|
下拉自身由 width:100% 跟着收。与 .hero-main / .person-move .select 同一套做法。 */
|
|
|
|
|
|
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.field.full { grid-column: 1 / -1; }
|
|
|
|
|
|
.field label { font-size: 13px; color: var(--muted); font-weight: 500; }
|
|
|
|
|
|
.field .tip { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.input, .select, textarea.input {
|
|
|
|
|
|
width: 100%; padding: 10px 12px; font: inherit; font-size: 14px;
|
|
|
|
|
|
color: var(--ink); background: #fff;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
transition: border-color .15s ease, box-shadow .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.input:focus, .select:focus, textarea.input:focus {
|
|
|
|
|
|
outline: none; border-color: var(--brand);
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(168, 74, 40, .12);
|
|
|
|
|
|
}
|
|
|
|
|
|
textarea.input { min-height: 76px; resize: vertical; }
|
|
|
|
|
|
.err { color: var(--red); font-size: 12px; }
|
|
|
|
|
|
|
|
|
|
|
|
.btn {
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
2026-10-01 19:35:48 +08:00
|
|
|
|
padding: var(--act-pad-y) var(--act-pad-x);
|
|
|
|
|
|
font: inherit; font-size: var(--act-font); line-height: var(--act-line); font-weight: 500;
|
2026-09-30 00:49:53 +08:00
|
|
|
|
border-radius: var(--radius-s); border: 1px solid transparent; cursor: pointer;
|
|
|
|
|
|
background: var(--brand); color: #fff; transition: background .15s ease;
|
|
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.btn:hover { text-decoration: none; } /* 底色交给文末「全站悬停统一」段(同色系加深) */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.btn-ghost { background: #fff; color: var(--ink); border-color: var(--line); }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.btn-ghost:hover { } /* 同上:中性薄雾 + 边框微显,见文末统一段 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.btn-danger { background: #fff; color: var(--red); border-color: rgba(192,83,63,.35); }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.btn-danger:hover { } /* 同上(危险类走薄雾带一点红) */
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* v24 第 19 批 用户第 7 条:行程行的动作按钮要**看得出颜色**——
|
|
|
|
|
|
「修改是黄色背景,完成绿色,未成行红色」。
|
|
|
|
|
|
⚠️ 这三个是**实心**色块(不是 .btn-danger 那种淡红描边):用户说的是背景色,
|
|
|
|
|
|
要的是"一眼分得清哪个是哪个"。所以单独定义,不去改 .btn-danger 的既有语义
|
|
|
|
|
|
(全站十来处「删除」都在用它,改成实心会到处变样)。 */
|
|
|
|
|
|
.btn-warn { background: #E8A33D; color: #fff; border-color: transparent; }
|
|
|
|
|
|
.btn-ok { background: #5E9E4E; color: #fff; border-color: transparent; }
|
|
|
|
|
|
.btn-del { background: #C0533F; color: #fff; border-color: transparent; }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
/* ⚠️ 这三个的 hover 统一交给文件靠后的「第 20 批 全站悬停统一」那一段
|
|
|
|
|
|
(有底色的一律 `filter: brightness(.92)` 同色系加深,不再各写一个色值)。 */
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.btn-sm { padding: 5px 12px; font-size: 13px; }
|
|
|
|
|
|
.btn-row { display: flex; gap: 10px; margin-top: 20px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 详情 ---------------- */
|
|
|
|
|
|
.detail { display: grid; grid-template-columns: 260px 1fr; gap: 24px; }
|
|
|
|
|
|
.detail-photo {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 16px; text-align: center;
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-photo img {
|
|
|
|
|
|
width: 100%; aspect-ratio: 1/1; object-fit: cover;
|
|
|
|
|
|
border-radius: 12px; display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-photo .name { font-size: 18px; font-weight: 600; margin: 14px 0 4px; }
|
|
|
|
|
|
.detail-photo .sub { color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- v24 第 11 批 #3:详情页改「名片卡 + 全宽堆叠」----
|
|
|
|
|
|
⚠️ 旧的 .detail 是 260px + 1fr 两栏,头像卡比右栏矮得多 → 头像下面留一大片空白。
|
|
|
|
|
|
现在头像与基本信息并排成一张名片,其余内容全宽往下排。 */
|
|
|
|
|
|
.pcard {
|
|
|
|
|
|
display: flex; align-items: flex-start; gap: 18px;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); box-shadow: var(--shadow);
|
|
|
|
|
|
padding: 18px 20px; margin-bottom: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pcard-avatar { flex: 0 0 auto; }
|
|
|
|
|
|
.pcard-avatar img {
|
|
|
|
|
|
width: 108px; height: 108px; object-fit: cover;
|
|
|
|
|
|
border-radius: 12px; display: block; background: var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.pcard-main { flex: 1 1 auto; min-width: 0; padding-top: 2px; }
|
|
|
|
|
|
.pcard-name {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
font-size: 21px; font-weight: 600; margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pcard-real { font-size: 13px; font-weight: 400; color: var(--muted); }
|
|
|
|
|
|
.pcard-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.pcard-chip {
|
|
|
|
|
|
display: inline-block; padding: 3px 10px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--ink); font-size: 12.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-stack { display: flex; flex-direction: column; gap: 18px; }
|
|
|
|
|
|
.detail-stack > div { min-width: 0; }
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
.pcard { flex-direction: column; align-items: center; text-align: center; }
|
|
|
|
|
|
.pcard-name, .pcard-meta { justify-content: center; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.kv { display: flex; flex-direction: column; }
|
|
|
|
|
|
.kv-row {
|
|
|
|
|
|
display: grid; grid-template-columns: 96px 1fr; gap: 12px;
|
|
|
|
|
|
padding: 12px 0; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.kv-row:last-child { border-bottom: 0; }
|
|
|
|
|
|
.kv-row dt { color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
.kv-row dd { margin: 0; font-size: 14px; word-break: break-all; }
|
|
|
|
|
|
.mono { font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; letter-spacing: .5px; }
|
|
|
|
|
|
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* ---- 工作经历(详情页,用户 2026-10-03 第 4 条)----
|
|
|
|
|
|
一个人可以有多段,逐条列出来;"现在还在那儿"的那段排最前并带徽标。 */
|
|
|
|
|
|
.job-history { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.job-history-item {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
word-break: normal; /* ⚠️ .kv-row dd 上有 break-all,这里要收回来,
|
|
|
|
|
|
否则"中国海洋大学"会被从中间断开 */
|
|
|
|
|
|
}
|
|
|
|
|
|
.job-history-item .job-org { font-weight: 600; }
|
|
|
|
|
|
.job-history-item .job-title { color: var(--brand-ink); }
|
|
|
|
|
|
.job-history-item .job-span { font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
/* 「我对他的私人备注」那一块:淡一点,别和"公开资料"抢注意力 */
|
|
|
|
|
|
.my-note-card { background: #FCFAF6; }
|
|
|
|
|
|
|
2026-09-30 00:49:53 +08:00
|
|
|
|
/* ---------------- 提示 ---------------- */
|
|
|
|
|
|
.flash { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
|
|
|
|
|
|
.flash-item {
|
|
|
|
|
|
padding: 10px 14px; border-radius: var(--radius-s); font-size: 14px;
|
|
|
|
|
|
background: #E6F0DC; color: #3D6B1F;
|
|
|
|
|
|
}
|
|
|
|
|
|
.flash-item.err { background: #F8DDDA; color: #A1341F; }
|
|
|
|
|
|
|
|
|
|
|
|
.empty {
|
|
|
|
|
|
background: var(--surface); border: 1px dashed var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 40px 20px; text-align: center;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.empty b { display: block; color: var(--ink); font-weight: 500; margin-bottom: 4px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 登录 / 安装 ---------------- */
|
|
|
|
|
|
.auth-wrap {
|
|
|
|
|
|
min-height: 100vh; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
padding: 40px 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.auth-card {
|
|
|
|
|
|
width: 100%; max-width: 400px; background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 20px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
padding: 32px;
|
|
|
|
|
|
}
|
2026-09-30 09:44:55 +08:00
|
|
|
|
/* 图标 + 「用手机号登录你的家书」+ 家庭名,整块水平居中。
|
|
|
|
|
|
⚠️ 只有这一块居中:下面的表单仍然左对齐(label 左对齐才好读),
|
|
|
|
|
|
「忘记密码」那行本来就是居中,所以视觉上不会歪。 */
|
|
|
|
|
|
.auth-head { text-align: center; }
|
|
|
|
|
|
.auth-card .logo {
|
|
|
|
|
|
display: block; margin: 0 auto 14px;
|
|
|
|
|
|
width: 56px; height: 56px; border-radius: 14px;
|
|
|
|
|
|
}
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.auth-card h1 { font-size: 20px; font-weight: 600; margin: 0 0 4px; }
|
|
|
|
|
|
.auth-card .lead { color: var(--muted); font-size: 14px; margin: 0 0 24px; }
|
|
|
|
|
|
.auth-card .btn { width: 100%; margin-top: 20px; }
|
|
|
|
|
|
.auth-foot { margin-top: 18px; font-size: 13px; color: var(--muted); text-align: center; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 其他 ---------------- */
|
|
|
|
|
|
.muted { color: var(--muted); }
|
|
|
|
|
|
.small { font-size: 13px; }
|
|
|
|
|
|
.nowrap { white-space: nowrap; }
|
|
|
|
|
|
.search { display: flex; gap: 8px; margin-bottom: 16px; }
|
|
|
|
|
|
.search .input { max-width: 260px; }
|
|
|
|
|
|
|
2026-10-10 00:26:42 +08:00
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
日期 + 时:分 组合控件(templates/_datetime.php)—— v37 重做
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
形态(用户 2026-10-09 第 4 次反馈点名要的):
|
|
|
|
|
|
日期 = 年 / 月 / 日 三个原生下拉;时间 = 时 : 分 两个原生下拉。
|
|
|
|
|
|
起止两端默认同一行,放不下时自动换到下一行(flex-wrap,见 .dt-cols)。
|
|
|
|
|
|
|
|
|
|
|
|
为什么把浏览器自带的 <input type=date> 换掉:
|
|
|
|
|
|
它的日历弹层是浏览器自己画的,我们碰不到 DOM、也控制不了流程;
|
|
|
|
|
|
Chrome 在"点顶部 2026年 10月 切到年月视图"之后要靠用户再点一次日期或
|
|
|
|
|
|
按 Esc 才回得到日期视图,各家还不一致 → 用户遇到的就是"选完年月就卡住、
|
|
|
|
|
|
选不了日"。三个原生下拉选完即生效,不需要任何确定按钮。
|
|
|
|
|
|
|
|
|
|
|
|
这一整段不再有"未升级就藏原生控件"的逻辑(v24~v36 有过)。
|
|
|
|
|
|
服务端给的就是最终形态,JS 只负责绑事件 —— 所以"JS 没跑 / 加载失败"时
|
|
|
|
|
|
控件依然完整可用,不是"骨架占位"。
|
|
|
|
|
|
============================================================================ */
|
2026-09-30 09:44:55 +08:00
|
|
|
|
.dt-input { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
2026-10-12 15:31:03 +08:00
|
|
|
|
/* 🔴 v44:内联标签(`_datetime.php` 的 `$dtLabel`)—— 让"日期范围:"与最新控件
|
|
|
|
|
|
**同一行**。宽度与观影式 `.mv-lb`(62px)一致,右对齐、冒号由 `::after` 给,
|
|
|
|
|
|
与「日历本」「标题」那几行的标签左缘对齐。
|
|
|
|
|
|
⚠️ 它是 `.dt-input` 的**兄弟节点**(不是子节点)—— 见 `_datetime.php` 里的说明:
|
|
|
|
|
|
放进去会被"收起原生端点"那条规则一起 clip 掉。选择器用 `+`(紧随其后)。 */
|
|
|
|
|
|
.dt-inline-lab {
|
|
|
|
|
|
flex: 0 0 auto; width: 62px; text-align: right;
|
|
|
|
|
|
font-size: 14px; font-weight: 600; color: var(--ink);
|
|
|
|
|
|
line-height: 1.4; word-break: keep-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ 它同时带 `.mv-lb`(在 `.mv-row` 里时由那条规则给固定宽度与冒号);
|
|
|
|
|
|
这里再写一遍是为了**不在 `.mv-row` 里**(编辑整页那种两列排版)也成立。 */
|
|
|
|
|
|
.dt-inline-lab::after { content: ':'; font-weight: 400; color: var(--muted); }
|
|
|
|
|
|
.dt-inline-lab > i { font-style: normal; color: var(--red, #C0392B); margin-left: 1px; }
|
|
|
|
|
|
/* 范围组里带标签时:标签在前、控件在后,横向排(`.dt-range.dt-cols` 已是 flex row) */
|
|
|
|
|
|
.dt-range > .dt-inline-lab { flex: 0 0 62px; }
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.dt-inline-lab { flex: 0 0 52px; width: 52px; font-size: 13px; }
|
|
|
|
|
|
}
|
2026-10-04 08:56:40 +08:00
|
|
|
|
.dt-input .dt-native { display: contents; }
|
|
|
|
|
|
.dt-input .dt-semi { display: none; flex: 1 1 220px; min-width: 0; }
|
2026-10-10 00:26:42 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 日期:年 / 月 / 日 三个下拉 ---- */
|
|
|
|
|
|
.dt-date-sel { display: flex; align-items: center; gap: 4px; min-width: 0; }
|
|
|
|
|
|
.dt-input .dt-year,
|
|
|
|
|
|
.dt-input .dt-month,
|
|
|
|
|
|
.dt-input .dt-day {
|
|
|
|
|
|
padding: 9px 6px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--surface); color: var(--ink); font: inherit; font-size: 13.5px;
|
|
|
|
|
|
font-variant-numeric: tabular-nums; cursor: pointer; min-width: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 年最宽(4 位数 + 箭头),月/日短一些 —— 省下来的宽度留给时:分 */
|
|
|
|
|
|
.dt-input .dt-year { flex: 0 1 86px; }
|
|
|
|
|
|
.dt-input .dt-month { flex: 0 1 66px; }
|
|
|
|
|
|
.dt-input .dt-day { flex: 0 1 64px; }
|
|
|
|
|
|
/* 隐藏的 `*_date` 真正的字段(提交契约)—— 它必须留在 DOM 里 */
|
|
|
|
|
|
.dt-input input.dt-date[type="hidden"] { display: none; }
|
|
|
|
|
|
/* 旧「原生 date 框」形态($dtDateType='native' 时才出现)保留样式 */
|
|
|
|
|
|
.dt-input .dt-date:not([type="hidden"]) {
|
|
|
|
|
|
flex: 1 1 150px; min-width: 0; cursor: pointer;
|
|
|
|
|
|
padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--surface); color: var(--ink); font: inherit;
|
|
|
|
|
|
accent-color: var(--brand);
|
|
|
|
|
|
}
|
|
|
|
|
|
.dt-input .dt-date:not([type="hidden"])::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .65; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 时间:时 : 分 ---- */
|
|
|
|
|
|
.dt-time { display: flex; align-items: center; gap: 3px; flex: 0 0 auto; }
|
|
|
|
|
|
.dt-input .dt-hour,
|
|
|
|
|
|
.dt-input .dt-minute,
|
|
|
|
|
|
.dt-input .dt-second {
|
|
|
|
|
|
padding: 9px 6px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--surface); color: var(--ink); font: inherit; font-size: 13.5px;
|
|
|
|
|
|
font-variant-numeric: tabular-nums; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dt-input .dt-colon { color: var(--muted); font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 必填但没填时描红(由 app.js 的 guardRequired 打类) */
|
|
|
|
|
|
.dt-input.dt-missing .dt-year,
|
|
|
|
|
|
.dt-input.dt-missing .dt-month,
|
|
|
|
|
|
.dt-input.dt-missing .dt-day,
|
|
|
|
|
|
.dt-input.dt-missing .dt-date { border-color: #C0392B !important; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
起止范围(.dt-range):两端一行优先,放不下才换行
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
用户原话(2026-10-09 第 4 次反馈):
|
|
|
|
|
|
现在开始和结束时间分在了两行,导致日期这个特别特别的长,后面的时和分又
|
|
|
|
|
|
非常非常的短,非常不协调。所以这两个日期如果能放一排,如果能放得下的话,
|
|
|
|
|
|
就应该放一排。因为日期和时间,分和时和分的这个长度基本上是固定的,
|
|
|
|
|
|
所以你可以判断一下它到底能不能一行,能不能放得下。如果能放下的话就放在一行。
|
|
|
|
|
|
如果在手机上,比如说它这个页面非常窄,它就可以把它挤到下一行。
|
|
|
|
|
|
但是现在不要让它默认显示在两行上,应该默认显示在一行上才对。
|
|
|
|
|
|
|
|
|
|
|
|
⇒ 做法:flex 容器 + flex-wrap。每端有一个最小的可用宽度(.dt-part 的
|
|
|
|
|
|
min-width),浏览器在每次布局时自己判断放不放得下;放得下 → 一行;
|
|
|
|
|
|
放不下 → 第二端自然掉到下一行。
|
|
|
|
|
|
⚠️ 不用 JS 量宽度:字体没加载完 / 容器动画中都会量错,窗口缩放还要重算;
|
|
|
|
|
|
flex-wrap 是浏览器布局的一部分,永远是对的。
|
|
|
|
|
|
⚠️ .dt-range 的标签只在组上留一个(见 _event_fields.php 的说明):
|
|
|
|
|
|
两端是同一个范围的两个端点,各挂一个标签会变成"看着像两个字段"的错觉。 */
|
|
|
|
|
|
.dt-range { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.dt-range-label { font-size: 14px; color: var(--ink); font-weight: 600; }
|
|
|
|
|
|
/* 升级(= app.js 挂上 .dt-cols)之后:两端并排、必要才换行 */
|
|
|
|
|
|
.dt-range.dt-cols {
|
|
|
|
|
|
flex-direction: row; flex-wrap: wrap; align-items: center;
|
|
|
|
|
|
gap: 10px 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 两端的"最小可用宽度":日期(年+月+日) + 时:分 摆得下。
|
|
|
|
|
|
值取 250px —— 实测"年(86)+月(66)+日(64)+时:分(约 96)+间距"约 330px 才舒服,
|
|
|
|
|
|
但最小可用是 250px(会各自压缩一点),这样在常见的 560px+ 容器里
|
|
|
|
|
|
两端(250×2 + 18 间距 = 518)肯定放得下 → 默认就是一行。 */
|
|
|
|
|
|
.dt-range.dt-cols > .dt-input,
|
|
|
|
|
|
.dt-range.dt-cols > .field { flex: 1 1 250px; min-width: 250px; display: flex; }
|
|
|
|
|
|
.dt-range.dt-cols > .field { flex-direction: column; gap: 6px; }
|
|
|
|
|
|
/* 标签占满整行(不然它会跟第一端挤在一起) */
|
|
|
|
|
|
.dt-range.dt-cols > .dt-range-label { flex: 1 1 100%; }
|
|
|
|
|
|
/* 极窄屏:两端各自铺满一行(用户说的"手机上就挤到下一行") */
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.dt-range.dt-cols > .dt-input,
|
|
|
|
|
|
.dt-range.dt-cols > .field { flex: 1 1 100%; min-width: 0; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
Semi 仅剩的用途:工作经历的「年月选择」(<input type="month"> 的升级)
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
⚠️ 日期/时间控件(.dt-input)v37 起已完全不用 Semi —— 上面那套自建下拉
|
|
|
|
|
|
就是因为它给的弹层交互不可控(选完年月卡住)。这里保留的是另一处。
|
|
|
|
|
|
============================================================================ */
|
2026-10-04 08:56:40 +08:00
|
|
|
|
.dt-semi.dt-semi-month { display: none; }
|
|
|
|
|
|
.dt-semi.dt-semi-month.is-live { display: block; width: 100%; }
|
|
|
|
|
|
body[class] {
|
|
|
|
|
|
--semi-color-primary: var(--brand, #A84A28);
|
|
|
|
|
|
--semi-color-primary-hover: var(--brand-2, #C05F38);
|
|
|
|
|
|
--semi-color-primary-active: var(--brand-ink, #8D3C20);
|
|
|
|
|
|
--semi-color-focus-border: var(--brand, #A84A28);
|
|
|
|
|
|
}
|
|
|
|
|
|
body[class] .dt-semi .semi-input-wrapper {
|
|
|
|
|
|
width: 100%; height: 40px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--surface); color: var(--ink);
|
2026-10-04 19:43:00 +08:00
|
|
|
|
display: flex; align-items: center;
|
2026-10-04 08:56:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
body[class] .dt-semi .semi-input-wrapper:hover { border-color: var(--brand-2); background: var(--surface); }
|
|
|
|
|
|
body[class] .dt-semi .semi-input { font: inherit; color: var(--ink); }
|
|
|
|
|
|
body[class] .dt-semi .semi-input::placeholder { color: var(--muted); }
|
2026-10-04 19:43:00 +08:00
|
|
|
|
body[class] .dt-semi .semi-datepicker-input,
|
|
|
|
|
|
body[class] .dt-semi .semi-datepicker {
|
2026-10-10 00:26:42 +08:00
|
|
|
|
background: transparent !important; height: auto !important;
|
|
|
|
|
|
min-height: 0 !important; border: 0; padding: 0;
|
2026-10-04 19:43:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
body[class] .dt-semi .semi-input-wrapper .semi-input {
|
|
|
|
|
|
height: 100%; line-height: 40px; padding: 0 11px; background: transparent;
|
|
|
|
|
|
}
|
2026-10-04 08:56:40 +08:00
|
|
|
|
body[class] .semi-popover .semi-datepicker { background: var(--surface, #fff); }
|
|
|
|
|
|
body[class] .semi-datepicker-day-selected { background-color: var(--brand, #A84A28); }
|
|
|
|
|
|
body[class] .semi-datepicker-day-hoverday,
|
|
|
|
|
|
body[class] .semi-datepicker-day-inhover { background-color: color-mix(in srgb, var(--brand, #A84A28) 12%, transparent); }
|
2026-10-09 20:23:09 +08:00
|
|
|
|
|
2026-09-30 09:44:55 +08:00
|
|
|
|
/* 「以哪个生日为准」的两块:被选中的那块描一圈,一眼看出填的是哪边 */
|
|
|
|
|
|
.bd-source { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
|
|
|
|
|
|
.bd-pane { border: 1px solid transparent; border-radius: var(--radius); padding: 10px 12px 2px; }
|
|
|
|
|
|
.bd-pane.is-primary { border-color: var(--brand-2); background: #FDF6F1; }
|
|
|
|
|
|
.bd-pane .bd-pane-k { font-size: 13px; font-weight: 600; margin: 0 0 8px; }
|
|
|
|
|
|
.bd-readonly {
|
|
|
|
|
|
display: inline-block; padding: 6px 10px; border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--line-2); color: var(--muted); font-size: 14px;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-30 08:13:07 +08:00
|
|
|
|
/* ---------------- 称谓标签 ---------------- */
|
|
|
|
|
|
.rel-label {
|
|
|
|
|
|
display: inline-block; padding: 1px 9px; border-radius: 999px;
|
|
|
|
|
|
background: #F6E3D7; color: var(--brand-ink);
|
|
|
|
|
|
font-size: 11px; font-weight: 500; line-height: 1.8;
|
|
|
|
|
|
margin-right: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-01 12:11:43 +08:00
|
|
|
|
/* ---------------- 家谱(以我为中心) ----------------
|
2026-10-02 20:09:28 +08:00
|
|
|
|
v22:按 family-chart **官方用法**接(容器 class="f3" + 引 family-chart.css),
|
|
|
|
|
|
库把 data[0].id 当 main_id,所以把「最高祖先」排第一位以画出尽可能多的血亲旁支;
|
2026-10-02 19:24:08 +08:00
|
|
|
|
加载后再把镜头平移回「我」,兼顾"看到全树"与"以自己为中心"。
|
2026-10-01 17:42:15 +08:00
|
|
|
|
|
2026-10-02 20:09:28 +08:00
|
|
|
|
⚠️ 免费版 family-chart 的算法只画「树根的祖先链 + 后代 + 树根的兄弟姐妹 + 各人配偶」,
|
|
|
|
|
|
**不会从配偶继续向上/向下 walk**。这一点已用**官方示例自己的数据**验证过:
|
|
|
|
|
|
官方 data.json 里 13 人(含配偶 Andrea 的父母 Zadro/Zadra,格式完全按官方),
|
|
|
|
|
|
库只画出 11 人 —— 配偶方那两位长辈一个都没画。
|
|
|
|
|
|
所以「把数据按格式全塞进去就能画全」在姻亲这一项上不成立,是库的算法边界。 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.kin-tools { display: flex; gap: 8px; justify-content: flex-end; margin: 0 0 10px; }
|
|
|
|
|
|
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.kin-chart {
|
|
|
|
|
|
position: relative;
|
2026-10-01 12:11:43 +08:00
|
|
|
|
width: 100%;
|
2026-10-01 19:35:48 +08:00
|
|
|
|
height: clamp(420px, 62vh, 720px);
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius);
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
overflow: hidden;
|
2026-10-02 10:26:14 +08:00
|
|
|
|
cursor: grab;
|
2026-10-02 19:24:08 +08:00
|
|
|
|
/* 拖拽/缩放由库接管,别让浏览器插手滚动 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
touch-action: none;
|
2026-10-01 12:11:43 +08:00
|
|
|
|
}
|
2026-10-02 10:26:14 +08:00
|
|
|
|
.kin-chart:active { cursor: grabbing; }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
2026-10-02 20:09:28 +08:00
|
|
|
|
/* 库的 `.f3` 会自带一套**深色主题**(--background-color: rgb(33,33,33) / --text-color: #fff)。
|
|
|
|
|
|
家书是宣纸浅色,必须在这里把库的主题变量改掉;否则卡片文字会变白、看不出内容。
|
|
|
|
|
|
只覆盖颜色变量,**不动**库的结构规则(那些是撑满/定位必需的)。 */
|
|
|
|
|
|
.kin-chart.f3 {
|
|
|
|
|
|
--male-color: #F1E7D6; /* 库的男卡底色,改成纸色(我们自己的 .kin-card 会再盖一层) */
|
|
|
|
|
|
--female-color: #F1E7D6;
|
|
|
|
|
|
--genderless-color: #F1E7D6;
|
|
|
|
|
|
--background-color: transparent;
|
|
|
|
|
|
--text-color: var(--ink);
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-02 19:24:08 +08:00
|
|
|
|
/* 隐藏 family-chart 自带的空导航栏(我们用自己的「看全部 / 回到我」按钮) */
|
|
|
|
|
|
.kin-chart .f3-nav-cont { display: none !important; }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
2026-10-02 20:09:28 +08:00
|
|
|
|
/* 官方 CSS 已经给了 `.f3 svg.main_svg { width:100%; height:100% }`(撑满画布),
|
|
|
|
|
|
这里只补一个 display:block,避免 svg 作为 inline 元素多出基线空隙。 */
|
|
|
|
|
|
.kin-chart svg.main_svg { display: block; z-index: 1; }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
2026-10-02 19:24:08 +08:00
|
|
|
|
/* family-chart 的 HTML 卡片层 #htmlSvg 与 SVG 连线层由库的 onZoom 同步 transform。
|
|
|
|
|
|
卡片容器 .card_cont 已经 absolute + translate(x,y);里面再放我们的 .kin-card。 */
|
|
|
|
|
|
.kin-chart #htmlSvg { z-index: 2; }
|
|
|
|
|
|
.kin-chart .card_cont { pointer-events: none; }
|
|
|
|
|
|
|
2026-10-02 20:09:28 +08:00
|
|
|
|
/* ⚠️ 库的性别底色规则是 `.f3 div.card-male .card-inner`(3 段),
|
|
|
|
|
|
比 `.kin-chart .card_cont .card-inner`(3 段)**同级**,靠先后顺序定胜负 ——
|
|
|
|
|
|
所以这份覆盖必须写在**引库 CSS 之后**(app.css 在 layout 里就是这么排的)。
|
|
|
|
|
|
把外层中转容器全部归零,只留我们自己的 .kin-card。 */
|
2026-10-02 19:24:08 +08:00
|
|
|
|
.kin-chart .card_cont > .card,
|
2026-10-02 20:09:28 +08:00
|
|
|
|
.kin-chart .card_cont .card-inner,
|
|
|
|
|
|
.kin-chart.f3 .card_cont .card-inner {
|
2026-10-02 19:24:08 +08:00
|
|
|
|
background: transparent;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
|
min-height: 0;
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
height: auto;
|
2026-10-02 20:09:28 +08:00
|
|
|
|
outline: none;
|
2026-10-02 19:24:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
.kin-chart .card_cont .card-inner { display: block; }
|
|
|
|
|
|
|
|
|
|
|
|
/* v21:卡片尺寸与 setCardDim({w:140, h:120}) 对齐 */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
/* 用户 2026-10-03 第 1 条:
|
|
|
|
|
|
· 头像外框改**长方形**(宽 96 × 高 72),宽度基本就是头像显示宽度;
|
|
|
|
|
|
img 用 object-fit: contain —— 既不裁切,也不会把外框撑变形。
|
|
|
|
|
|
· 信息(姓名/称呼)在头像**下方**。
|
|
|
|
|
|
· 卡片不再整张是链接:只有 .kin-nm 是 <a>,右下角是独立的 <button>,
|
|
|
|
|
|
两者分开,避免"点按钮却进了成员页"的误触。
|
|
|
|
|
|
卡片尺寸与 JS 的 setCardDim({w,h}) 必须一致(库按它算间距与连线落点)。 */
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* 卡片尺寸:**框宽 = 头像宽**(用户 2026-10-03:「外面那个框,宽度和头像图片一致,
|
2026-10-03 17:49:10 +08:00
|
|
|
|
下面显示名字就行了」)。
|
2026-10-03 19:27:14 +08:00
|
|
|
|
🔴 头像槽位是 **1:1(正方形)**(见 App\ImageSlot::SLOTS['avatar'])
|
|
|
|
|
|
—— 所以"框宽 = 头像宽"其实要求框里的头像区**也是正方形**:
|
|
|
|
|
|
之前写成 96×72 的长方形 + `object-fit: contain`,正方形照片被**缩到 72 宽**
|
|
|
|
|
|
左右各留 ~12px 空白 → 看起来"框比头像宽很多"(用户第 8 条「还是比头像宽很多」)。
|
|
|
|
|
|
现在头像区取正方形,照片 `object-fit: cover` 铺满 —— 框就是头像本身那么大。
|
|
|
|
|
|
⚠️ 这个 90/128 必须与 JS 里 setCardDim({w,h}) **保持一致**:
|
2026-10-03 17:49:10 +08:00
|
|
|
|
库按它算卡片间距与连线落点,两边不一致连线就会歪。 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.kin-card {
|
2026-10-03 19:27:14 +08:00
|
|
|
|
--kin-w: 90px;
|
|
|
|
|
|
--kin-h: 128px;
|
|
|
|
|
|
--kin-ph: 88px; /* 头像区(正方形):卡宽 − 左右各 1px 边框 */
|
2026-10-02 10:26:14 +08:00
|
|
|
|
position: absolute;
|
2026-10-02 13:26:11 +08:00
|
|
|
|
display: flex; flex-direction: column; align-items: center;
|
|
|
|
|
|
gap: 0;
|
2026-10-03 17:49:10 +08:00
|
|
|
|
width: var(--kin-w);
|
|
|
|
|
|
height: var(--kin-h);
|
|
|
|
|
|
box-sizing: border-box; padding: 5px 0 4px;
|
2026-10-01 19:35:48 +08:00
|
|
|
|
text-align: center;
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line);
|
2026-10-02 13:26:11 +08:00
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
box-shadow: 0 1px 3px rgba(43,38,32,.10);
|
2026-10-01 19:35:48 +08:00
|
|
|
|
color: var(--ink);
|
2026-10-02 10:26:14 +08:00
|
|
|
|
transition: border-color .15s ease, box-shadow .15s ease;
|
2026-10-02 13:26:11 +08:00
|
|
|
|
overflow: hidden;
|
2026-10-02 19:24:08 +08:00
|
|
|
|
pointer-events: auto; /* 父 .card_cont 是 none,这里恢复 */
|
2026-10-01 17:42:15 +08:00
|
|
|
|
}
|
2026-10-03 17:49:10 +08:00
|
|
|
|
/* ⚠️⚠️ 居中**绝不能**用 transform、也不能用 `inset:0 + margin:auto`。
|
|
|
|
|
|
两次踩坑记录(都是用户先发现的:一次"鼠标移上去框会动",一次"线又错位了"):
|
|
|
|
|
|
· 用 `transform: translate(-50%,-50%)`:库自带
|
|
|
|
|
|
`.f3 div.card:hover > div { transform: translate(0,-2px) }` 会把居中 transform
|
|
|
|
|
|
**整份覆盖** → 鼠标一进卡片整张卡跳 53×58px(半张卡)。
|
|
|
|
|
|
· 用 `inset: 0` + `margin: auto`:**在这里不成立** —— 含块是库的 `div.card`,
|
|
|
|
|
|
在 Cartesian 模式下它只有 **1.8px 宽**(宽度由内部一个空 div 撑出来),
|
|
|
|
|
|
auto 外边距在一个比卡片还窄的盒子里根本分不出空间,结果卡片整体**右移了 53.1px**
|
|
|
|
|
|
(实测每张卡的中心都偏在节点右边 53.1px)→ 连线与卡片错位。
|
|
|
|
|
|
正解:`left/top: 50%` + **半个自身尺寸的负外边距** —— 位置完全由布局决定,
|
|
|
|
|
|
不经过 transform,库那条 :hover 规则怎么覆盖都影响不到。
|
|
|
|
|
|
⚠️ 负外边距必须写 `calc(var(--kin-*) / -2)`,与上面的尺寸共用同一个变量;
|
|
|
|
|
|
写成死数字(-59/-66)迟早会和尺寸脱节。 */
|
2026-10-03 15:57:56 +08:00
|
|
|
|
.kin-card {
|
2026-10-03 17:49:10 +08:00
|
|
|
|
left: 50%; top: 50%;
|
|
|
|
|
|
margin-left: calc(var(--kin-w) / -2);
|
|
|
|
|
|
margin-top: calc(var(--kin-h) / -2);
|
2026-10-03 15:57:56 +08:00
|
|
|
|
}
|
2026-10-03 17:49:10 +08:00
|
|
|
|
/* ⚠️ 还要把库那条 `:hover` 位移**归零**(用户反馈「鼠标放上去框会动」的另一半)。
|
2026-10-03 15:57:56 +08:00
|
|
|
|
库的 family-chart.css:517 有:
|
|
|
|
|
|
`.f3 div.card:hover > div { transform: translate(0, -2px); }`
|
2026-10-03 17:49:10 +08:00
|
|
|
|
它除了覆盖居中,还会给卡片一个纯视觉的"上浮 2px"(实测 dy = -1.8px)。
|
|
|
|
|
|
我们自绘的宣纸卡不需要库那套悬停装饰,直接归零。
|
|
|
|
|
|
⚠️ 不去改 vendor 里那份文件(升级库会整份覆盖、改动静默消失):
|
|
|
|
|
|
在 app.css 覆盖即可 —— 它加载在 family-chart.css **之后**,
|
|
|
|
|
|
同特异性下后写的赢,**不需要 !important**。 */
|
2026-10-03 15:57:56 +08:00
|
|
|
|
.kin-chart.f3 div.card:hover > div { transform: none; }
|
|
|
|
|
|
.kin-chart.f3 div.card > div { transition: none; }
|
2026-10-02 10:26:14 +08:00
|
|
|
|
.kin-card:hover {
|
2026-10-03 11:30:48 +08:00
|
|
|
|
box-shadow: var(--shadow-l); border-color: var(--brand-2);
|
2026-10-03 08:18:05 +08:00
|
|
|
|
}
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* 头像区:**正方形、铺满**(见上面 --kin-ph 的说明)。
|
|
|
|
|
|
用户 2026-10-03 第 8 条:「宽度和头像图片一致,下面显示名字就行了」。 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.kin-card .kin-ph {
|
2026-10-03 19:27:14 +08:00
|
|
|
|
width: var(--kin-ph); height: var(--kin-ph);
|
|
|
|
|
|
border-radius: 8px; overflow: hidden;
|
2026-10-01 19:35:48 +08:00
|
|
|
|
background: #F1E7D6; flex: 0 0 auto;
|
2026-10-03 11:30:48 +08:00
|
|
|
|
display: block;
|
2026-09-30 08:13:07 +08:00
|
|
|
|
}
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* 头像槽位是 1:1,所以这里的容器也是 1:1 —— cover 不会裁掉任何内容
|
|
|
|
|
|
(照片本来就是按 1:1 裁好的)。⚠️ 别改成 contain:那会在框里留出空白,
|
|
|
|
|
|
看起来就是"框比头像宽"。 */
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.kin-card .kin-ph img {
|
2026-10-03 19:27:14 +08:00
|
|
|
|
width: 100%; height: 100%; object-fit: cover; display: block;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
}
|
2026-10-03 17:49:10 +08:00
|
|
|
|
.kin-card .kin-ph:hover { box-shadow: inset 0 0 0 2px var(--brand-2); }
|
|
|
|
|
|
/* 姓名:用户 2026-10-03 第 7 条起,点姓名 = **以他为中心**重画家谱
|
|
|
|
|
|
(点头像才是进资料页)。
|
|
|
|
|
|
⚠️ 第 8 条明确要求**不要再显示"资料 / 以他为中心"那两行悬停提示**(没必要)——
|
|
|
|
|
|
所以 .kin-hint 这套已整个删掉,卡片上头像下面只有名字。 */
|
2026-10-02 13:26:11 +08:00
|
|
|
|
.kin-card .kin-nm {
|
2026-10-03 11:30:48 +08:00
|
|
|
|
display: block;
|
2026-10-02 13:26:11 +08:00
|
|
|
|
font-size: 12.5px; font-weight: 600; line-height: 1.25; max-width: 100%;
|
|
|
|
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
2026-10-03 11:30:48 +08:00
|
|
|
|
margin-top: 5px; color: var(--ink); text-decoration: none;
|
2026-10-02 13:26:11 +08:00
|
|
|
|
}
|
2026-10-03 11:30:48 +08:00
|
|
|
|
.kin-card .kin-nm:hover { color: var(--brand); text-decoration: underline; }
|
2026-10-02 13:26:11 +08:00
|
|
|
|
/* 称呼在姓名下面一行,用品牌色的浅字(参考实现是「(称呼)」) */
|
|
|
|
|
|
.kin-card .kin-lb {
|
|
|
|
|
|
font-size: 10.5px; color: var(--brand); line-height: 1.2; max-width: 100%;
|
|
|
|
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
|
|
|
|
}
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.kin-card .kin-mark { font-size: 10px; color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
/* 「我」:品牌色描边 + 光圈 */
|
|
|
|
|
|
.kin-card.is-me {
|
2026-09-30 08:13:07 +08:00
|
|
|
|
border-color: var(--brand);
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(168, 74, 40, .12), var(--shadow);
|
|
|
|
|
|
}
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.kin-card.is-me .kin-lb { color: var(--brand-ink); font-weight: 600; }
|
|
|
|
|
|
/* 「待确认」(只填了称呼、没对应到真人):虚线 */
|
|
|
|
|
|
.kin-card.is-ph { border-style: dashed; background: #FCFAF6; }
|
|
|
|
|
|
|
2026-10-02 19:24:08 +08:00
|
|
|
|
/* family-chart 默认连线颜色改淡,与之前自研版一致。
|
|
|
|
|
|
库在 path 上写了 inline stroke="#fff",必须用 !important 覆盖。 */
|
|
|
|
|
|
.kin-chart svg.main_svg .links_view path.link {
|
|
|
|
|
|
fill: none;
|
|
|
|
|
|
stroke: #C9BDA9 !important;
|
|
|
|
|
|
stroke-width: 1.6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-01 19:35:48 +08:00
|
|
|
|
.tree-legend { font-size: 12px; color: var(--muted); margin: 14px 2px 0; }
|
2026-10-02 10:26:14 +08:00
|
|
|
|
|
2026-09-30 08:13:07 +08:00
|
|
|
|
/* 详情页里的迷你家谱 */
|
|
|
|
|
|
.mini-tree { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.mini-gen { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
.mini-node {
|
|
|
|
|
|
display: flex; align-items: center; gap: 7px;
|
|
|
|
|
|
padding: 5px 12px 5px 5px; border-radius: 999px;
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line);
|
|
|
|
|
|
color: var(--ink); font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mini-node:hover { text-decoration: none; border-color: var(--brand); }
|
|
|
|
|
|
.mini-node img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; }
|
|
|
|
|
|
.mini-node .mn-label { font-size: 11px; color: var(--brand); }
|
|
|
|
|
|
.mini-node.is-me { border-color: var(--brand); background: #F6E3D7; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 亲属关系编辑 ---------------- */
|
|
|
|
|
|
.rel-summary {
|
|
|
|
|
|
display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
|
|
|
gap: 12px; margin-bottom: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rel-sum-item {
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
border-radius: var(--radius-s); padding: 10px 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rel-sum-k { display: block; font-size: 12px; color: var(--muted); margin-bottom: 3px; }
|
|
|
|
|
|
.rel-sum-v { font-size: 14px; }
|
|
|
|
|
|
.rel-sum-v a { margin-right: 6px; }
|
|
|
|
|
|
|
|
|
|
|
|
.rel-add { border-top: 1px solid var(--line-2); padding-top: 16px; }
|
|
|
|
|
|
.rel-add-title { font-size: 14px; font-weight: 600; margin: 0 0 12px; }
|
|
|
|
|
|
.rel-form {
|
|
|
|
|
|
display: grid; grid-template-columns: 1fr 1fr 1.4fr auto;
|
|
|
|
|
|
gap: 12px; align-items: end;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rel-list { margin-top: 16px; font-size: 13px; }
|
|
|
|
|
|
.rel-list summary { cursor: pointer; color: var(--muted); }
|
|
|
|
|
|
.rel-list ul { margin: 10px 0 0; padding-left: 18px; }
|
|
|
|
|
|
.rel-list li { margin-bottom: 6px; }
|
|
|
|
|
|
.rel-list .btn { margin-left: 6px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 三角色 / 存储设置 ---------------- */
|
|
|
|
|
|
.role-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
|
|
|
|
|
|
.role-card { background: #FAF7F1; border: 1px solid var(--line-2); border-radius: var(--radius-s); padding: 14px 16px; }
|
|
|
|
|
|
.rc-name { font-weight: 600; margin-bottom: 5px; }
|
|
|
|
|
|
.rc-desc { margin: 0; font-size: 13px; color: var(--muted); line-height: 1.65; }
|
|
|
|
|
|
|
|
|
|
|
|
.radio-row { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.radio-item {
|
|
|
|
|
|
display: flex; gap: 10px; align-items: flex-start;
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
border-radius: var(--radius-s); padding: 12px 14px; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.radio-item input { margin-top: 3px; }
|
|
|
|
|
|
.check-item { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; cursor: pointer; }
|
|
|
|
|
|
.check-item input { margin-top: 3px; }
|
|
|
|
|
|
|
|
|
|
|
|
.oss-box {
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
padding: 12px 16px; background: #FCFAF6;
|
|
|
|
|
|
}
|
|
|
|
|
|
.oss-box summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted); }
|
|
|
|
|
|
|
|
|
|
|
|
.plain-list { margin: 0; padding-left: 18px; font-size: 14px; }
|
|
|
|
|
|
.plain-list li { margin-bottom: 7px; }
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.rel-form { grid-template-columns: 1fr; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-30 00:49:53 +08:00
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
/* 390px 宽度放不下整套顶栏:只留 图标 + 导航 + 头像 + 退出 */
|
2026-09-30 08:13:07 +08:00
|
|
|
|
.topbar-inner { gap: 6px; padding: 0 10px; height: 54px; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.brand img { width: 26px; height: 26px; }
|
|
|
|
|
|
.nav { gap: 0; }
|
2026-09-30 08:13:07 +08:00
|
|
|
|
.nav a { padding: 6px 8px; font-size: 13px; }
|
|
|
|
|
|
.topbar-right { gap: 6px; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.who-name, .who-pwd { display: none; } /* 名字与「改密码」收起,设置页里都有 */
|
|
|
|
|
|
.who img { width: 26px; height: 26px; }
|
|
|
|
|
|
.container, .container-narrow { padding: 20px 16px 48px; }
|
|
|
|
|
|
.form-grid { grid-template-columns: 1fr; }
|
|
|
|
|
|
.detail { grid-template-columns: 1fr; }
|
|
|
|
|
|
.hero { padding: 20px; gap: 14px; }
|
|
|
|
|
|
.hero h1 { font-size: 20px; }
|
|
|
|
|
|
.hero-stats { margin-left: 0; gap: 20px; }
|
|
|
|
|
|
.page-head { flex-wrap: wrap; align-items: center; }
|
|
|
|
|
|
.page-head .actions { margin-left: 0; width: 100%; }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* ⚠️ 窄屏下动作区**必须允许换行**:
|
|
|
|
|
|
一行里可能有 6 个按钮(月/周/天 + 上一周/今天/下一周 + 新建 + ☰),
|
|
|
|
|
|
360px 根本放不下。不换行的后果不只是横向溢出(整页被拖走),
|
|
|
|
|
|
还会把按钮**挤扁**成高低不一(实测 91/68/44 三种高度,同排按钮参差不齐)——
|
|
|
|
|
|
而"页头按钮同高"是用户提过三次的明确要求。
|
|
|
|
|
|
换行之后每个按钮保持自己的尺寸,高度自然一致。 */
|
|
|
|
|
|
.page-head .actions { flex-wrap: wrap; }
|
|
|
|
|
|
.page-head .actions > .movie-set { margin-left: 0; }
|
2026-09-30 00:49:53 +08:00
|
|
|
|
.kv-row { grid-template-columns: 84px 1fr; }
|
|
|
|
|
|
.search { flex-wrap: wrap; }
|
|
|
|
|
|
.search .input { max-width: none; flex: 1 1 auto; }
|
|
|
|
|
|
}
|
2026-09-30 09:44:55 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---------------- 「我怎么称呼家人」(视角属性,见 app/Nickname.php) ---------------- */
|
|
|
|
|
|
.nick-list { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.nick-row {
|
|
|
|
|
|
display: grid; grid-template-columns: minmax(120px, auto) 1fr auto;
|
|
|
|
|
|
gap: 10px; align-items: center;
|
|
|
|
|
|
padding: 8px 10px; border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.nick-who { display: flex; align-items: center; gap: 8px; font-size: 14px; min-width: 0; }
|
|
|
|
|
|
.nick-who img { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
|
|
|
|
|
.nick-who span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
/* 详情页上的单个"我叫他什么"输入行 */
|
|
|
|
|
|
.nick-inline { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
|
|
|
|
|
|
.nick-inline .input { flex: 1 1 220px; max-width: 340px; }
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.nick-row { grid-template-columns: 1fr; }
|
|
|
|
|
|
.nick-inline .input { max-width: none; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 连通性测试与诊断(设置页) ---------------- */
|
|
|
|
|
|
.test-actions { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.test-actions form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
|
|
|
|
|
|
|
|
|
|
|
|
.oss-diag {
|
|
|
|
|
|
margin-top: 16px; border-radius: var(--radius-s); overflow: hidden;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.oss-diag-head {
|
|
|
|
|
|
display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
|
|
|
|
|
|
padding: 10px 14px; font-size: 13px;
|
|
|
|
|
|
background: var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.oss-diag.is-ok .oss-diag-head { background: #E6F0DC; color: #3F6021; }
|
|
|
|
|
|
.oss-diag.is-bad .oss-diag-head { background: #F6E3D7; color: var(--brand-ink); }
|
|
|
|
|
|
.oss-diag-table { width: 100%; border-collapse: collapse; font-size: 13px; background: var(--surface); }
|
|
|
|
|
|
.oss-diag-table th,
|
|
|
|
|
|
.oss-diag-table td { padding: 8px 12px; text-align: left; vertical-align: top; border-top: 1px solid var(--line-2); }
|
|
|
|
|
|
.oss-diag-table th { font-weight: 500; color: var(--muted); font-size: 12px; }
|
|
|
|
|
|
.oss-diag-table td:nth-child(1) { white-space: nowrap; }
|
|
|
|
|
|
.oss-diag-table td:nth-child(3) { white-space: nowrap; }
|
|
|
|
|
|
.oss-diag-table tr.row-ok td:nth-child(2) { color: #4A7226; }
|
|
|
|
|
|
.oss-diag-table tr.row-bad td:nth-child(2) { color: var(--red); }
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.oss-diag-table th:nth-child(3),
|
|
|
|
|
|
.oss-diag-table td:nth-child(3) { display: none; }
|
|
|
|
|
|
}
|
2026-09-30 11:06:22 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
以下都是 2026-09-30 那一批反馈加的东西
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
2026-10-08 10:54:43 +08:00
|
|
|
|
/* 只给读屏用的标签:视觉上不占地,但无障碍名还在(别用 display:none,那会一起藏掉)
|
|
|
|
|
|
🔴 v29 用户第 2 条:「任务完成复选框的提示文字还在」——
|
|
|
|
|
|
真根因:`_task_check.php` 与任务看板用的是 `class="visually-hidden"`,
|
|
|
|
|
|
而**本文件里从来没有这个类**(项目一直只定义 `.sr-only`)。
|
|
|
|
|
|
CSS 里查不到的类 = 没有任何样式 → 那段文字是**普通 inline span,直接显示出来**,
|
|
|
|
|
|
就贴在复选框旁边(用户看到的就是「标记完成:待办」)。
|
|
|
|
|
|
⇒ 修法:把两个名字指向同一条规则(两种写法都认)。
|
|
|
|
|
|
为什么不是"把模板改成 sr-only 了事":这个类名在下游(别的模板、以后新写的)
|
|
|
|
|
|
同样可能被用到,名字不再是隐患;而只改调用点的话,下次谁再写
|
|
|
|
|
|
`visually-hidden` 就又漏了。这里是"给能力补上定义",不是"给某一处打补丁"。*/
|
|
|
|
|
|
.sr-only,
|
|
|
|
|
|
.visually-hidden {
|
2026-09-30 11:06:22 +08:00
|
|
|
|
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 区块之间的小间隔(比写 style="margin-top:20px" 好读) */
|
|
|
|
|
|
.stack-gap { height: 20px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 名册:按关系分组分栏 ---------------- */
|
|
|
|
|
|
.group-block { margin-top: 24px; }
|
|
|
|
|
|
.group-head {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 8px;
|
|
|
|
|
|
margin: 0 0 10px; padding-bottom: 8px;
|
|
|
|
|
|
border-bottom: 1px solid var(--line);
|
|
|
|
|
|
font-size: 15px; font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
.group-head .group-title { color: var(--ink); }
|
|
|
|
|
|
/* 分组名前面那道砖红短线,让分栏在长页面上更容易一眼定位 */
|
|
|
|
|
|
.group-head .group-title::before {
|
|
|
|
|
|
content: ''; display: inline-block; vertical-align: middle;
|
|
|
|
|
|
width: 3px; height: 13px; margin-right: 8px; border-radius: 2px;
|
|
|
|
|
|
background: var(--brand);
|
|
|
|
|
|
}
|
|
|
|
|
|
.group-head .group-n { margin-left: auto; font-weight: 400; font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
/* 卡片改成 div > a + details:表单不能套在链接里(非法 HTML,浏览器会把 DOM 拆开) */
|
|
|
|
|
|
.person-main { display: block; color: var(--ink); }
|
|
|
|
|
|
.person-main:hover { text-decoration: none; }
|
2026-10-04 08:56:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 行右侧的动作区(分组 / 编辑 / ⋯)----
|
|
|
|
|
|
⚠️ 2026-10-04 之前这里有一条 `.person-more { display: none; }`,
|
|
|
|
|
|
而 `<details>` 默认 display 是 block,被它一压**整个 ⋯ 按钮都不见了**
|
|
|
|
|
|
—— 用户报的「名册没有地方可以更改分组了」就是这条(它把唯一的入口藏了)。
|
|
|
|
|
|
现在的做法是:动作区本身是 flex,三个按钮自然排开,谁都不用写死偏移。 */
|
|
|
|
|
|
.person-actions {
|
|
|
|
|
|
display: flex; align-items: center; gap: 6px;
|
|
|
|
|
|
padding: 8px 10px 8px 0; flex: 0 0 auto;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
2026-10-03 19:27:14 +08:00
|
|
|
|
.person-edit {
|
2026-10-04 08:56:40 +08:00
|
|
|
|
padding: 3px 10px; font-size: 13px; white-space: nowrap;
|
2026-10-03 19:27:14 +08:00
|
|
|
|
}
|
2026-10-04 10:46:50 +08:00
|
|
|
|
.person-more-btn {
|
|
|
|
|
|
padding: 3px 9px; font-size: 15px; line-height: 1.3;
|
|
|
|
|
|
color: var(--muted); white-space: nowrap;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
2026-10-04 10:46:50 +08:00
|
|
|
|
.person-more-btn:hover { color: var(--brand); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 名册卡片动作的**共享浮层**(v24 第 10 批 #6)----------------
|
|
|
|
|
|
「分组」「移出名册」两份表单全页只渲染一份(原来每卡各一份,1184 人 =
|
|
|
|
|
|
2369 个 form / 27234 个 input,密码管理器逐个扫描把页面拖死)。
|
|
|
|
|
|
这里给共享浮层一个定位容器,面板由 JS 贴合触发按钮摆放。 */
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- v24 第 11 批 #2:名册卡片的动作**居中模态框** ----
|
|
|
|
|
|
(第 10 批是"贴按钮的浮层",用户反馈分组"点第二次失效"且要求"像选观影人一样弹框",
|
|
|
|
|
|
于是改成遮罩 + 居中面板,与 _person_picker 同一形态。) */
|
|
|
|
|
|
.rm-modal { position: fixed; inset: 0; z-index: 60; display: flex;
|
|
|
|
|
|
align-items: center; justify-content: center; }
|
|
|
|
|
|
.rm-modal[hidden] { display: none; }
|
|
|
|
|
|
.rm-mask { position: absolute; inset: 0; background: rgba(47, 36, 30, .34); }
|
|
|
|
|
|
.rm-panel {
|
|
|
|
|
|
position: relative; z-index: 1;
|
2026-10-03 11:30:48 +08:00
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
2026-10-04 17:42:21 +08:00
|
|
|
|
border-radius: 14px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
width: min(360px, 92vw); max-height: min(78vh, 620px);
|
|
|
|
|
|
display: flex; flex-direction: column;
|
2026-10-03 11:30:48 +08:00
|
|
|
|
}
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.rm-panel[hidden] { display: none; }
|
|
|
|
|
|
.rm-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 14px 10px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.rm-head b { font-size: 14.5px; font-weight: 600; }
|
|
|
|
|
|
.rm-x {
|
|
|
|
|
|
margin-left: auto; border: 0; background: transparent; cursor: pointer;
|
|
|
|
|
|
font-size: 15px; line-height: 1; color: var(--muted); padding: 4px 6px; border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rm-x:hover { background: var(--line-2); color: var(--ink); }
|
|
|
|
|
|
.rm-body { padding: 8px 6px; overflow-y: auto; }
|
|
|
|
|
|
.rm-foot {
|
|
|
|
|
|
display: flex; gap: 8px; justify-content: flex-end;
|
|
|
|
|
|
padding: 10px 14px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.rm-warn {
|
|
|
|
|
|
margin: 0; padding: 10px 12px; font-size: 13px; line-height: 1.7;
|
|
|
|
|
|
background: #FDF2F0; border: 1px solid #F0D6D1; border-radius: 8px; color: #7A2A20;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rm-modal .pg-menu { display: contents; }
|
|
|
|
|
|
.rm-modal .pd-form { display: contents; }
|
|
|
|
|
|
.rm-modal .person-move { display: block; padding: 6px 14px 10px; }
|
|
|
|
|
|
.rm-modal .person-move.is-kin { padding: 6px 14px 10px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v24 第 11 批 #2:详情页底部「删除」= 大按钮(与「开通账号」同规格,红色底)---- */
|
|
|
|
|
|
.del-big { display: flex; flex-direction: column; gap: 12px; max-width: 420px; }
|
|
|
|
|
|
.del-big-tip { margin: 0; font-size: 13px; line-height: 1.75; color: var(--muted); }
|
|
|
|
|
|
.btn-block-lg {
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
width: 100%; padding: 12px 16px; font-size: 14.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.del-big-confirm {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 10px 12px; background: #FDF2F0;
|
|
|
|
|
|
border: 1px solid #F0D6D1; border-radius: 8px; font-size: 13px; color: #7A2A20;
|
|
|
|
|
|
}
|
|
|
|
|
|
.del-big-confirm[hidden] { display: none; }
|
2026-10-04 19:43:00 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- v24 第 12 批 #1:删除按钮紧挨「开通账号」放在同一列 ----
|
|
|
|
|
|
用户原话:「删除按钮,就放在开通账号按钮下面,紧挨着,长度大小,
|
|
|
|
|
|
和开通账号一样,就是颜色改成红色。」
|
|
|
|
|
|
所以这里只做两件事:① 与账号区的按钮**左对齐同宽**(都以账号卡片内容宽为准);
|
|
|
|
|
|
② 上方留一条细分隔线,让人一眼看出"这是同一个区块里的第二件事"。
|
|
|
|
|
|
⚠️ 尺寸一致性靠 .btn-block-lg(100% 宽 + 同 padding),不在这里写死宽度,
|
|
|
|
|
|
否则窄屏下会与「开通账号」对不齐。 */
|
|
|
|
|
|
.del-inline {
|
|
|
|
|
|
margin-top: 14px;
|
|
|
|
|
|
padding-top: 14px;
|
|
|
|
|
|
border-top: 1px dashed var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.del-inline-tip {
|
|
|
|
|
|
margin: 0 0 10px;
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
line-height: 1.7;
|
|
|
|
|
|
color: var(--muted);
|
|
|
|
|
|
}
|
2026-10-03 11:30:48 +08:00
|
|
|
|
.person-move { display: flex; gap: 6px; padding: 8px 12px; flex-wrap: wrap; }
|
2026-09-30 11:06:22 +08:00
|
|
|
|
.person-move .select { flex: 1 1 auto; min-width: 0; padding: 6px 8px; font-size: 13px; }
|
|
|
|
|
|
.person-move .btn { flex: 0 0 auto; }
|
|
|
|
|
|
|
2026-10-04 08:56:40 +08:00
|
|
|
|
/* ---- 「分组」按钮(用户 2026-10-04 第 1 条)----
|
|
|
|
|
|
按钮上**直接写着当前分组**,点开就是一张分组列表。
|
|
|
|
|
|
没分过组时写「分组」两个字并压暗(is-none),跟"已经归了组"区分开。 */
|
|
|
|
|
|
.person-group-btn {
|
|
|
|
|
|
white-space: nowrap; max-width: 130px; overflow: hidden; text-overflow: ellipsis;
|
|
|
|
|
|
list-style: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.person-group-btn::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.person-group-btn.is-none { color: var(--faint); }
|
|
|
|
|
|
.person-group[open] {
|
|
|
|
|
|
position: absolute; right: 8px; top: 8px; z-index: 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pg-menu {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 10px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
min-width: 200px; max-height: 60vh; overflow: auto;
|
|
|
|
|
|
padding: 8px 0; margin-top: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pg-title {
|
|
|
|
|
|
margin: 0 0 6px; padding: 0 12px; font-size: 12px; color: var(--faint);
|
|
|
|
|
|
}
|
|
|
|
|
|
.pg-item {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; cursor: pointer;
|
|
|
|
|
|
padding: 7px 12px; font-size: 13.5px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.pg-item:hover { background: var(--line-2); }
|
|
|
|
|
|
.pg-item input { flex: 0 0 auto; }
|
|
|
|
|
|
.pg-menu .pg-save { margin: 6px 12px 0; }
|
|
|
|
|
|
|
2026-09-30 13:24:26 +08:00
|
|
|
|
/* ---------------- 名册:拖动排序 / 拖到别栏改分组 ----------------
|
2026-10-04 08:56:40 +08:00
|
|
|
|
⚠️ 2026-10-04 起这一段是 **Pointer Events**(不再用 HTML5 拖放)——
|
|
|
|
|
|
原因写在 app.js 那段注释里(Chrome 下"只有第一组能拖"就是 HTML5 DnD 的锅)。
|
|
|
|
|
|
没有它,行上的「分组」按钮照样能改分组,功能不缺。 */
|
2026-09-30 13:24:26 +08:00
|
|
|
|
.roster.is-droppable .person { cursor: grab; }
|
2026-10-04 08:56:40 +08:00
|
|
|
|
/* ⚠️ 拖动中被拖的那张卡必须 pointer-events:none:落点是用 elementFromPoint
|
|
|
|
|
|
现算的,卡自己压在指针底下就只能算到自己,永远插不进别人中间。 */
|
|
|
|
|
|
.roster.is-droppable .person.is-dragged { opacity: .55; cursor: grabbing; pointer-events: none; }
|
2026-09-30 13:24:26 +08:00
|
|
|
|
.drag-handle {
|
2026-10-03 11:30:48 +08:00
|
|
|
|
position: absolute; left: 3px; top: 50%; transform: translateY(-50%); z-index: 2;
|
2026-09-30 13:24:26 +08:00
|
|
|
|
width: 22px; height: 22px; line-height: 22px; text-align: center;
|
|
|
|
|
|
border-radius: 6px; font-size: 14px;
|
|
|
|
|
|
color: var(--muted); background: rgba(255, 255, 255, .82);
|
|
|
|
|
|
border: 1px solid var(--line-2);
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* 🔴 v24 第 25 批 用户第 5 条:手柄是**拖动名册的唯一入口**。
|
|
|
|
|
|
用户原话:「点击列表中的人,是直接查看这个人的信息,拖动的时候才是调整数序。」
|
|
|
|
|
|
→ 整行不再参与拖动,**只有按在这个 ⠿ 上才算**(鼠标与触摸同一判据)。
|
|
|
|
|
|
所以它必须一眼看得出来"这里是能抓的":
|
|
|
|
|
|
· `cursor: grab`(抓着时 JS 加 .is-dragged 的卡片会变 grabbing,见下)
|
|
|
|
|
|
· `touch-action: none` —— 不写它,手指在柄上一划会被浏览器当成滚页面,永远拖不起来
|
|
|
|
|
|
· 悬停加一点底色,别让它看着像一个装饰性的字符 */
|
2026-10-04 08:56:40 +08:00
|
|
|
|
touch-action: none; cursor: grab;
|
2026-09-30 13:24:26 +08:00
|
|
|
|
}
|
2026-10-07 11:35:31 +08:00
|
|
|
|
.drag-handle:hover { background: var(--brand-soft, rgba(168,74,40,.10)); color: var(--brand); }
|
2026-09-30 13:24:26 +08:00
|
|
|
|
.drag-handle-inline { color: var(--muted); }
|
2026-10-03 11:30:48 +08:00
|
|
|
|
/* 列表里每行要留出左侧拖柄的位置(否则⠿会压在头像上) */
|
|
|
|
|
|
.roster.is-droppable .person { padding-left: 18px; }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* 正被拖的那张卡:手柄变抓握态(与 cursor:grab 配成一对) */
|
|
|
|
|
|
.person.is-dragged .drag-handle { cursor: grabbing; }
|
2026-09-30 13:24:26 +08:00
|
|
|
|
|
|
|
|
|
|
/* 空栏平时收起来(七个预置分组可能只用到三个,摊开会显得名册破破烂烂)——
|
|
|
|
|
|
但**拖动时必须露出来**,否则"想拖到一个现在没人的分组里"就没地方放。 */
|
|
|
|
|
|
.group-block.is-empty { display: none; }
|
|
|
|
|
|
.roster.is-dragging .group-block.is-empty {
|
|
|
|
|
|
display: block; opacity: .9;
|
|
|
|
|
|
border: 1px dashed var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 10px; margin-top: 18px;
|
|
|
|
|
|
background: rgba(250, 247, 241, .6);
|
|
|
|
|
|
}
|
|
|
|
|
|
.group-drop-hint { display: none; margin-left: auto; font-weight: 400; font-size: 12px; color: var(--brand); }
|
|
|
|
|
|
.roster.is-dragging .group-block .group-drop-hint { display: inline; }
|
|
|
|
|
|
/* 拖动时把"有多少人"让出位置给落点提示,两者都挤在右上角会很乱 */
|
|
|
|
|
|
.roster.is-dragging .group-block .group-n { display: none; }
|
|
|
|
|
|
.roster.is-dragging .people-grid { min-height: 24px; }
|
|
|
|
|
|
|
2026-10-04 08:56:40 +08:00
|
|
|
|
/* 窄屏:一行上「分组 + 编辑 + ⋯」三个按钮,分组名会吃掉姓名的空间 ——
|
|
|
|
|
|
把分组名的上限压一压,先保住姓名能读(分组点开照样看得到全名)。 */
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
.person-group-btn { max-width: 76px; }
|
|
|
|
|
|
.person-actions { gap: 4px; padding-right: 6px; }
|
|
|
|
|
|
.person-edit { padding: 3px 7px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-30 13:24:26 +08:00
|
|
|
|
/* 拖完/没拖成的轻提示(2 秒自己消失,不打断操作) */
|
|
|
|
|
|
.roster-note {
|
|
|
|
|
|
position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 12px);
|
|
|
|
|
|
z-index: 200; padding: 8px 16px; border-radius: 999px;
|
|
|
|
|
|
background: rgba(44, 35, 29, .88); color: #fff; font-size: 13px;
|
|
|
|
|
|
opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.roster-note.is-show { opacity: 1; transform: translate(-50%, 0); }
|
|
|
|
|
|
.roster-note.is-err { background: rgba(178, 45, 45, .92); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 分享名片(成员详情页) ---------------- */
|
|
|
|
|
|
.share-wrap { display: inline-block; }
|
|
|
|
|
|
.share-wrap > summary { list-style: none; cursor: pointer; display: inline-block; }
|
|
|
|
|
|
.share-wrap > summary::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.share-wrap .inline-form { margin-top: 10px; }
|
2026-10-03 21:19:34 +08:00
|
|
|
|
/* 分享改用弹窗选人组件后,里面的 chips + 按钮要能在这个窄条里排开;
|
|
|
|
|
|
组件默认按"整页宽"设计(.pp-chips 自带 flex-wrap),这里给它一个合理上限,
|
|
|
|
|
|
免得点开"分享他的名片给…"时弹窗按钮被挤成半行。 */
|
|
|
|
|
|
.share-wrap .share-to { flex: 1 1 220px; min-width: 0; }
|
2026-09-30 13:24:26 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---------------- 「从家里已有的人里挑」 ---------------- */
|
|
|
|
|
|
.pick-list { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 8px; }
|
|
|
|
|
|
.pick-row { margin: 0; }
|
|
|
|
|
|
.pick-item {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; cursor: pointer;
|
|
|
|
|
|
padding: 8px 12px; border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.pick-item:hover { border-color: var(--brand); }
|
|
|
|
|
|
.pick-item input[type="checkbox"] { width: 16px; height: 16px; flex: 0 0 auto; accent-color: var(--brand); }
|
|
|
|
|
|
.pick-ph { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; background: #F1E7D6; }
|
|
|
|
|
|
.pick-name { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
|
|
|
|
|
2026-09-30 11:06:22 +08:00
|
|
|
|
/* ---------------- 个人设置:分组顺序 ---------------- */
|
|
|
|
|
|
.order-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.order-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 8px 12px; border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.order-no {
|
|
|
|
|
|
flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
|
|
|
|
|
|
background: var(--brand); color: #fff;
|
|
|
|
|
|
font-size: 12px; line-height: 22px; text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.order-name { flex: 1 1 auto; min-width: 0; font-size: 14px; }
|
|
|
|
|
|
.order-count { flex: 0 0 auto; font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
.order-move { flex: 0 0 auto; display: flex; gap: 4px; }
|
|
|
|
|
|
.order-move .btn { padding: 2px 8px; line-height: 1.4; }
|
|
|
|
|
|
.order-move .btn[disabled] { opacity: .35; cursor: default; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------------- 个人设置:关系分类管理 ---------------- */
|
|
|
|
|
|
.inline-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
|
|
|
|
.inline-form .input { flex: 1 1 200px; max-width: 320px; }
|
|
|
|
|
|
.group-manage { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.group-manage-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 8px 12px; border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FAF7F1; border: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.group-rename { display: flex; gap: 8px; align-items: center; flex: 1 1 240px; min-width: 0; }
|
|
|
|
|
|
.group-rename .input { flex: 1 1 auto; min-width: 0; max-width: 220px; padding: 6px 10px; font-size: 13px; }
|
|
|
|
|
|
.group-manage-row .group-count { flex: 0 0 auto; }
|
|
|
|
|
|
.del-wrap > summary { list-style: none; cursor: pointer; }
|
|
|
|
|
|
.del-wrap[open] { flex: 1 1 100%; }
|
|
|
|
|
|
.del-confirm { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 8px 0 2px; }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
/* ---- 页头动作区:统一尺寸 + 除设置外都要「有颜色」 ----
|
|
|
|
|
|
⚠️ 本节刻意放在**文件靠后**:.btn / .btn-ghost / .btn-danger / .btn-icon
|
|
|
|
|
|
的定义都在前面,CSS 同特异性时「后写的赢」——放前面会被它们覆盖
|
|
|
|
|
|
(实测过:放前面时 .btn-icon 白底被 .btn 的品牌底盖掉、.btn-ghost 也还是白的)。
|
|
|
|
|
|
用户明确提过三次:
|
|
|
|
|
|
·「设置按钮和记一场电影按钮高度要一致」
|
|
|
|
|
|
·「返回等按钮和记一场电影等按钮的大小高度的统一问题」
|
|
|
|
|
|
·「设置按钮…只保留图标,图标换成三条横线;除设置,其他按钮都要有颜色」 */
|
|
|
|
|
|
.page-head .actions > .btn,
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn,
|
|
|
|
|
|
.page-head .actions > form > .btn,
|
|
|
|
|
|
.page-head .actions > form > button.btn {
|
|
|
|
|
|
padding: var(--act-pad-y) var(--act-pad-x); font-size: var(--act-font);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 层 1:主按钮(裸 .btn,无修饰类)—— 品牌实心。
|
|
|
|
|
|
⚠️ `.btn` 同时出现在 `<a class="btn">` 和 `<form><button class="btn">`,
|
|
|
|
|
|
两条路径的选择器都要写出来,且**特异性必须相等**,否则后面层 2/3
|
|
|
|
|
|
按类名匹配的规则压不住它(下层靠"同特异性 + 后写"取胜)。 */
|
|
|
|
|
|
.page-head .actions > .btn:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > .btn:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn:not(.btn-icon) {
|
|
|
|
|
|
background: var(--brand); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .btn:not(.btn-icon):hover,
|
2026-10-06 03:14:18 +08:00
|
|
|
|
/* 底色交给文末统一段(同色系加深) */
|
|
|
|
|
|
.page-head .actions > form > button.btn:not(.btn-icon):hover { }
|
2026-10-01 19:35:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* 层 2:次要按钮(.btn-ghost)—— 品牌描边 + 极浅品牌底,比主按钮轻一档。
|
|
|
|
|
|
a / button 两种形态各写一条、特异性对齐(见层 1 的警告)。 */
|
|
|
|
|
|
.page-head .actions > .btn-ghost:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > a.btn-ghost:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > .btn-ghost:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-ghost:not(.btn-icon) {
|
|
|
|
|
|
background: #FDF7F2; color: var(--brand); border-color: rgba(168, 74, 40, .45);
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > a.btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > .btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > button.btn-ghost:not(.btn-icon):hover {
|
2026-10-06 03:14:18 +08:00
|
|
|
|
background: var(--hov-veil, rgba(44,35,29,.05)); border-color: var(--brand);
|
2026-10-01 19:35:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 层 3:危险按钮(.btn-danger)—— 淡红底 + 红字,同样要有颜色、但不能看着像主按钮。
|
|
|
|
|
|
⚠️ 实测踩过:只写 `.actions > form > .btn-danger`(0,4,0)会被层 1 的
|
|
|
|
|
|
`.actions > form > button.btn`(0,4,1)压掉 —— 详情页的「删除」按钮
|
|
|
|
|
|
在浏览器里显示成品牌砖红实心,跟「编辑」几乎分不出来。补上 `button.`
|
|
|
|
|
|
形态后特异性升到 (0,4,2),才真正生效。 */
|
|
|
|
|
|
.page-head .actions > .btn-danger:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > a.btn-danger:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > .btn-danger:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-danger:not(.btn-icon) {
|
|
|
|
|
|
background: #FDF1EE; color: var(--red); border-color: rgba(192, 83, 63, .45);
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .btn-danger:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > a.btn-danger:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > .btn-danger:not(.btn-icon):hover,
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.page-head .actions > form > button.btn-danger:not(.btn-icon):hover { background: rgba(192, 83, 63, .09); }
|
2026-10-10 22:13:20 +08:00
|
|
|
|
|
|
|
|
|
|
/* 层 4:**实心**底色按钮(v40 用户要求)。
|
|
|
|
|
|
原话(2026-10-10):「删除按钮就用红色背景颜色…影院管理部分…编辑使用蓝色的背景,
|
|
|
|
|
|
删除使用红色的背景。」
|
|
|
|
|
|
⇒ 这两个要的是**实心色块**(一眼分得清),而不是层 3 那种淡色描边。
|
|
|
|
|
|
⚠️ 为什么不直接改 `.btn-danger`:全站十来处「删除」都在用它,改成实心会到处变样;
|
|
|
|
|
|
而且**页头动作区的层 1**(`.actions > form > button.btn`,特异性 0,4,1)
|
|
|
|
|
|
会盖过基类 `.btn-del`(0,1,0)—— 必须在同一层里再写一条才生效(与层 3 同一个坑)。 */
|
|
|
|
|
|
.page-head .actions > .btn-del:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > a.btn-del:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > .btn-del:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-del:not(.btn-icon) {
|
|
|
|
|
|
background: var(--red); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .btn-edit:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > a.btn-edit:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > .btn-edit:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-edit:not(.btn-icon) {
|
|
|
|
|
|
background: var(--blue); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
2026-10-01 19:35:48 +08:00
|
|
|
|
/* 「设置」图标按钮:**唯一无色的**(白底描边、方形),与上面所有彩色按钮区分。
|
|
|
|
|
|
padding 归零、做成正方形,但高度必须仍是 --act-h(= 文字按钮的 43.8px)——
|
|
|
|
|
|
写死过 40px,比旁边按钮矮 3.8px,是用户反复反馈的那个问题。 */
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn-icon,
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn {
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
width: var(--act-h); height: var(--act-h); min-width: var(--act-h); line-height: 1;
|
|
|
|
|
|
background: #fff; color: var(--ink); border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn-icon:hover,
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn:hover {
|
2026-10-06 03:14:18 +08:00
|
|
|
|
border-color: var(--brand); color: var(--brand);
|
|
|
|
|
|
/* 底色交给文末统一段(中性薄雾),别在这里另糊一个 #FAF7F1 */
|
2026-10-01 19:35:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
.movie-set[open] > summary.btn-icon,
|
|
|
|
|
|
.movie-set[open] > summary.btn { border-color: var(--brand); color: var(--brand); }
|
2026-09-30 11:06:22 +08:00
|
|
|
|
.btn.danger { color: var(--red); border-color: rgba(192, 83, 63, .35); }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.btn.danger:hover { } /* 统一段处理 */
|
2026-09-30 11:06:22 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---------------- 图片裁剪浮层 ---------------- */
|
|
|
|
|
|
/* 覆盖层默认不占空间;打开时铺满整屏,把底下的页面锁住(裁剪时不该能点到别处) */
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- 图片裁剪(v24 第 11 批 #5:改用 Cropper.js)----
|
|
|
|
|
|
用户的四条硬要求(原话见 assets/js/app.js 那段注释)在这里逐条落地:
|
|
|
|
|
|
① 弹框**不要有任何滚动条** → 面板 overflow:hidden;画布尺寸固定,由 Cropper 缩放图片去适应。
|
|
|
|
|
|
② 图片无论多大都要缩放到框内 → 交给 Cropper 的 viewMode:1(container 自适应)。
|
|
|
|
|
|
③ **不要缩放条** → 原来那根 .crop-zoom-row 整块删掉了,改滚轮缩放。
|
|
|
|
|
|
④ 裁剪框要比弹框小、**所有触点都露出来** → 画布四周留出 22px 内边距,
|
|
|
|
|
|
Cropper 的四个角手柄画成实心白点,永远落在面板可见区内。 */
|
2026-09-30 11:06:22 +08:00
|
|
|
|
.crop-overlay { display: none; }
|
|
|
|
|
|
.crop-overlay.is-open {
|
2026-10-12 00:24:20 +08:00
|
|
|
|
/* 🔴🔴 v43(用户 2026-10-11 第 3 条):「新建行程的时候,如果把地图拖进去,
|
|
|
|
|
|
它不是开始裁剪吗?但是这个弹出的框把裁剪那个框又盖住了,裁剪的框应该放到前面来。」
|
|
|
|
|
|
真根因:裁剪层是 **100**,而行程/观影那些弹框用的 `.cal-modal` 是 **200**
|
|
|
|
|
|
⇒ 从弹框里拖图触发的裁剪层被整块盖在下面 —— 看不见、也点不到。
|
|
|
|
|
|
(与 v41 那个「新建影院弹框被记一场电影盖住」是**同一个坑**,当时把 .cn-modal
|
|
|
|
|
|
提到了 260;这里漏了。)
|
|
|
|
|
|
⇒ 提到 **260**:高于所有自建弹框(.cal-modal 200 / .pp-modal 等),
|
|
|
|
|
|
与 .cn-modal 同层;低于灯箱(300)、预览层(320) —— 那两者是"看大图"的顶级层。 */
|
|
|
|
|
|
display: flex; position: fixed; inset: 0; z-index: 260;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
align-items: center; justify-content: center;
|
|
|
|
|
|
padding: 20px; background: rgba(44, 35, 29, .55);
|
|
|
|
|
|
}
|
|
|
|
|
|
.crop-panel {
|
2026-10-04 17:42:21 +08:00
|
|
|
|
background: var(--surface); border-radius: 14px;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
box-shadow: var(--shadow-l); padding: 16px;
|
2026-10-04 17:42:21 +08:00
|
|
|
|
max-width: calc(100vw - 24px); max-height: calc(100vh - 24px);
|
|
|
|
|
|
/* ① 不许出滚动条:面板自己 overflow:hidden,画布尺寸按视口算死在下面 */
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
display: flex; flex-direction: column;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
.crop-head {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 8px;
|
2026-10-04 17:42:21 +08:00
|
|
|
|
font-size: 15px; font-weight: 600; margin-bottom: 12px; flex: 0 0 auto;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
.crop-head .crop-shape { font-size: 12px; font-weight: 400; color: var(--muted); }
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.crop-x {
|
|
|
|
|
|
margin-left: auto; align-self: center; border: 0; background: transparent;
|
|
|
|
|
|
font-size: 15px; line-height: 1; color: var(--muted);
|
|
|
|
|
|
cursor: pointer; padding: 4px 6px; border-radius: 6px;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.crop-x:hover { background: var(--line-2); color: var(--ink); }
|
|
|
|
|
|
/* 画布:**固定尺寸**(不是 max-height),这样 Cropper 一定会把图片缩进来,
|
|
|
|
|
|
而不会让容器去滚动。宽高都换算成"视口内还能放下的最大方块"。
|
|
|
|
|
|
⚠️ 留 22px 内边距是给裁剪框四个角的手柄留位(要求④)。 */
|
|
|
|
|
|
.crop-canvas {
|
|
|
|
|
|
flex: 0 0 auto; position: relative;
|
|
|
|
|
|
width: min(560px, calc(100vw - 88px));
|
|
|
|
|
|
height: min(66vh, 460px);
|
|
|
|
|
|
border-radius: var(--radius-s); overflow: hidden;
|
|
|
|
|
|
background: #2C231D;
|
2026-09-30 13:24:26 +08:00
|
|
|
|
}
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.crop-canvas img { display: block; max-width: 100%; }
|
|
|
|
|
|
.crop-tip { color: var(--muted); font-size: 12px; margin: 12px 0 0; flex: 0 0 auto; }
|
|
|
|
|
|
.crop-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; flex: 0 0 auto; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ④ 触点全露出:Cropper 默认的手柄太细、颜色偏灰,在深色画布上不好抓。
|
|
|
|
|
|
这里加粗、改成白底品牌边,并**保证它们不被画布裁掉**(Cropper 自己会留 margin)。 */
|
|
|
|
|
|
.cropper-view-box,
|
|
|
|
|
|
.cropper-face { border-radius: 2px; }
|
|
|
|
|
|
.cropper-line { background-color: rgba(255, 255, 255, .9); }
|
|
|
|
|
|
.cropper-point {
|
|
|
|
|
|
width: 12px; height: 12px; opacity: 1;
|
|
|
|
|
|
background-color: #fff; border: 2px solid var(--brand);
|
|
|
|
|
|
border-radius: 50%;
|
2026-09-30 11:06:22 +08:00
|
|
|
|
}
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.cropper-point.point-se { width: 14px; height: 14px; }
|
|
|
|
|
|
.cropper-bg { background-image: none; background-color: #2C231D; }
|
|
|
|
|
|
.cropper-modal { background-color: rgba(20, 14, 10, .55); }
|
|
|
|
|
|
|
2026-09-30 11:06:22 +08:00
|
|
|
|
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.order-move .btn { padding: 4px 10px; }
|
|
|
|
|
|
.group-manage-row { align-items: flex-start; }
|
|
|
|
|
|
.crop-panel { padding: 12px; }
|
|
|
|
|
|
}
|
2026-09-30 15:02:27 +08:00
|
|
|
|
|
|
|
|
|
|
/* ===== 补充联系方式(可多条):标注 + 内容 一行两组,窄屏摞起来 ===== */
|
|
|
|
|
|
.ct-row { display: flex; gap: 8px; margin-bottom: 8px; }
|
|
|
|
|
|
.ct-row .ct-label { flex: 0 0 140px; }
|
|
|
|
|
|
.ct-row .input { flex: 1; }
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.ct-row { flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.ct-row .ct-label { flex: none; }
|
|
|
|
|
|
}
|
2026-09-30 20:22:46 +08:00
|
|
|
|
|
2026-10-01 00:12:04 +08:00
|
|
|
|
/* ===== 观影 v9:瀑布流海报墙 + MovieLog 式详情/评价/影院 ===== */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 搜索栏 ---- */
|
|
|
|
|
|
.search-bar {
|
|
|
|
|
|
display: flex; gap: 10px; align-items: center;
|
|
|
|
|
|
background: var(--surface); padding: 8px 16px;
|
|
|
|
|
|
border-radius: 12px; box-shadow: var(--shadow);
|
|
|
|
|
|
border: 1px solid var(--line); max-width: 500px; margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.search-bar input[type="text"] {
|
|
|
|
|
|
flex: 1; border: none; outline: none; padding: 8px 10px;
|
|
|
|
|
|
font-size: 15px; background: transparent; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.search-bar button {
|
|
|
|
|
|
background: var(--brand); color: #fff; border: none;
|
|
|
|
|
|
padding: 8px 20px; border-radius: 8px; font-weight: 600;
|
|
|
|
|
|
cursor: pointer; white-space: nowrap;
|
|
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.search-bar button:hover { } /* 统一段处理(同色系加深,不换成 brand-2) */
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.search-clear { color: var(--muted); font-size: 14px; padding: 8px 4px; white-space: nowrap; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 瀑布流海报墙 ---- */
|
|
|
|
|
|
.waterfall {
|
|
|
|
|
|
display: grid; gap: 20px; padding: 4px 0;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
|
|
|
|
}
|
2026-09-30 20:22:46 +08:00
|
|
|
|
.movie-card {
|
2026-10-01 00:12:04 +08:00
|
|
|
|
background: var(--surface); border-radius: var(--radius);
|
|
|
|
|
|
overflow: hidden; box-shadow: var(--shadow); cursor: pointer;
|
|
|
|
|
|
border: 1px solid var(--line); display: flex; flex-direction: column;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
text-decoration: none; color: var(--ink);
|
|
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.movie-card:hover {
|
|
|
|
|
|
transform: translateY(-6px); box-shadow: var(--shadow-l);
|
|
|
|
|
|
border-color: var(--brand-2); text-decoration: none;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.card-image {
|
|
|
|
|
|
width: 100%; aspect-ratio: 2 / 3; background: var(--line-2);
|
|
|
|
|
|
overflow: hidden; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
position: relative; flex-shrink: 0;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.card-image img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
|
|
|
|
|
|
.movie-card:hover .card-image img { transform: scale(1.03); }
|
|
|
|
|
|
.placeholder-poster {
|
|
|
|
|
|
width: 100%; height: 100%; display: flex; flex-direction: column;
|
|
|
|
|
|
align-items: center; justify-content: center; gap: 6px;
|
|
|
|
|
|
background: linear-gradient(135deg, #4a3a30, #2C231D);
|
|
|
|
|
|
color: rgba(255, 255, 255, .55); font-size: 42px; font-weight: 600;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.placeholder-poster .placeholder-title {
|
|
|
|
|
|
font-size: 14px; text-align: center; padding: 0 12px;
|
|
|
|
|
|
color: rgba(255, 255, 255, .75); font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-body { padding: 14px 16px 16px; flex: 1; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.card-title {
|
|
|
|
|
|
font-size: 16px; font-weight: 600; color: var(--ink);
|
|
|
|
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-meta {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 6px 12px;
|
|
|
|
|
|
font-size: 13px; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.card-meta span { display: inline-flex; align-items: center; gap: 3px; }
|
|
|
|
|
|
.meta-rating { color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.meta-rating-max { color: var(--muted); font-weight: 400; }
|
|
|
|
|
|
.card-viewers { display: flex; flex-wrap: wrap; gap: 4px 8px; margin-top: auto; }
|
|
|
|
|
|
.viewer-tag {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 4px; font-size: 12px;
|
|
|
|
|
|
padding: 2px 8px; border-radius: 12px; background: var(--line-2);
|
|
|
|
|
|
color: var(--ink); text-decoration: none;
|
2026-10-02 09:28:07 +08:00
|
|
|
|
/* 底色/字色/边线由 person_chip() 写成行内样式(每人一个颜色,来自他的头像主色);
|
|
|
|
|
|
这里只给**没有行内样式时的兜底**(旧的灰底标签):1px 透明边,
|
|
|
|
|
|
这样有边线和没边线的两种标签高度完全一致,不会一行高一行矮。 */
|
|
|
|
|
|
border: 1px solid transparent;
|
2026-10-01 00:12:04 +08:00
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.viewer-tag:hover { text-decoration: none; filter: brightness(.96); }
|
|
|
|
|
|
.viewer-tag .chip-av { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
|
|
|
|
|
.viewer-tag .chip-av-text {
|
|
|
|
|
|
background: var(--faint); color: #fff;
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
font-size: 10px; line-height: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.viewer-tag .chip-name { white-space: nowrap; }
|
2026-09-30 20:22:46 +08:00
|
|
|
|
|
2026-10-01 00:12:04 +08:00
|
|
|
|
/* ---- 详情页 ---- */
|
|
|
|
|
|
.detail-hero {
|
|
|
|
|
|
display: grid; grid-template-columns: 300px 1fr; gap: 32px;
|
|
|
|
|
|
background: var(--surface); border-radius: var(--radius);
|
|
|
|
|
|
padding: 28px; box-shadow: var(--shadow); margin-bottom: 20px;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-poster {
|
|
|
|
|
|
border-radius: 12px; overflow: hidden; background: var(--line-2);
|
|
|
|
|
|
aspect-ratio: 2 / 3; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-poster img { width: 100%; height: 100%; object-fit: cover; }
|
|
|
|
|
|
.detail-poster .placeholder-poster { font-size: 48px; }
|
|
|
|
|
|
.detail-poster .placeholder-poster .placeholder-title { font-size: 16px; }
|
|
|
|
|
|
.detail-info { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
|
|
|
|
|
|
.detail-info h1 { font-size: 26px; font-weight: 700; margin: 0 0 4px; color: var(--ink); }
|
|
|
|
|
|
.detail-info .meta-row { display: flex; flex-wrap: wrap; gap: 8px 16px; font-size: 14px; color: var(--muted); }
|
|
|
|
|
|
.detail-info .meta-row span { display: inline-flex; align-items: center; gap: 4px; }
|
|
|
|
|
|
.info-text { color: var(--ink); line-height: 1.7; font-size: 15px; }
|
|
|
|
|
|
.remark-text {
|
|
|
|
|
|
background: var(--line-2); padding: 12px 16px; border-radius: 8px;
|
|
|
|
|
|
color: var(--ink); border-left: 4px solid var(--brand); font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-section {
|
|
|
|
|
|
background: var(--surface); border-radius: var(--radius);
|
|
|
|
|
|
padding: 24px 28px; box-shadow: var(--shadow); margin-bottom: 20px;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-section h3 {
|
|
|
|
|
|
font-size: 17px; font-weight: 600; margin: 0 0 16px; color: var(--ink);
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.detail-section h3 .badge {
|
|
|
|
|
|
font-size: 13px; font-weight: 400; background: var(--line-2);
|
|
|
|
|
|
padding: 2px 12px; border-radius: 20px; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.empty-hint { color: var(--muted); font-size: 14px; margin: 0; }
|
|
|
|
|
|
.viewers-list { display: flex; flex-wrap: wrap; gap: 12px; }
|
|
|
|
|
|
.viewers-list .viewer-tag { padding: 4px 12px 4px 6px; font-size: 14px; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.viewers-list .viewer-tag .chip-av { width: 28px; height: 28px; }
|
|
|
|
|
|
.viewers-list .viewer-tag .chip-av-text { font-size: 13px; }
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.cinema-info {
|
|
|
|
|
|
display: grid; grid-template-columns: 1fr 1fr; gap: 8px 24px; font-size: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cinema-info .label { color: var(--muted); }
|
|
|
|
|
|
.cinema-info .value { color: var(--ink); font-weight: 500; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 影像记录 ---- */
|
|
|
|
|
|
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; }
|
|
|
|
|
|
.gallery-item {
|
|
|
|
|
|
border-radius: 10px; overflow: hidden; background: var(--line-2);
|
|
|
|
|
|
aspect-ratio: 4 / 3; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
cursor: pointer; transition: transform .2s; position: relative;
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.gallery-item:hover { transform: scale(1.02); }
|
|
|
|
|
|
.gallery-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
|
|
|
|
.gallery-item .label-badge {
|
|
|
|
|
|
position: absolute; bottom: 8px; left: 8px;
|
|
|
|
|
|
background: rgba(0, 0, 0, .7); color: #fff; font-size: 11px;
|
|
|
|
|
|
padding: 2px 12px; border-radius: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 图片灯箱 ---- */
|
|
|
|
|
|
.lb-openable { cursor: zoom-in; }
|
|
|
|
|
|
.lb-openable:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
|
|
|
|
|
|
.lightbox {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 300; display: none;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
align-items: center; justify-content: center;
|
2026-10-01 00:12:04 +08:00
|
|
|
|
background: rgba(0, 0, 0, .88); overscroll-behavior: contain;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.lightbox.open { display: flex; }
|
|
|
|
|
|
.lb-stage { display: flex; align-items: center; justify-content: center; max-width: 92vw; max-height: 82vh; }
|
|
|
|
|
|
.lb-img {
|
|
|
|
|
|
max-width: 92vw; max-height: 78vh; width: auto; height: auto;
|
|
|
|
|
|
object-fit: contain; border-radius: 8px; box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
|
|
|
|
|
|
user-select: none; -webkit-user-drag: none;
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.lb-btn {
|
|
|
|
|
|
position: absolute; border: none; cursor: pointer; color: #fff;
|
|
|
|
|
|
background: rgba(255, 255, 255, .12); display: flex;
|
|
|
|
|
|
align-items: center; justify-content: center;
|
2026-10-11 10:12:11 +08:00
|
|
|
|
transition: background-color .2s ease, filter .2s ease;
|
|
|
|
|
|
font-family: inherit;
|
2026-10-01 00:12:04 +08:00
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.lb-btn:hover { } /* 深底上不能用薄雾:走文末统一段的 brightness 提亮 */
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.lb-btn[hidden] { display: none; }
|
|
|
|
|
|
.lb-close { top: 14px; right: 16px; width: 40px; height: 40px; border-radius: 50%; font-size: 18px; }
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* 下载按钮在关闭按钮左边,同高、同一套视觉(v24 第 3 条:预览层右上角要有下载) */
|
|
|
|
|
|
.lb-dl {
|
|
|
|
|
|
top: 14px; right: 66px; height: 40px; padding: 0 16px; border-radius: 20px;
|
|
|
|
|
|
display: inline-flex; align-items: center; font-size: 13px; font-weight: 600;
|
|
|
|
|
|
background: #fff; color: #1a1a1a; text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.lb-dl:hover { background: #eee; }
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.lb-nav { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; border-radius: 50%; font-size: 28px; padding-bottom: 4px; }
|
2026-10-11 10:12:11 +08:00
|
|
|
|
/* 🔴🔴 v41(用户 2026-10-10):「观影照片的左右按钮,鼠标悬停之后位置会变一下,
|
|
|
|
|
|
一不小心就会点错。」
|
|
|
|
|
|
真根因:文末「全站悬停统一」段给 `.lb-btn:hover` 加了
|
|
|
|
|
|
`transform: translateY(var(--hov-lift))`(= 上移 1px 的"轻抬升"手感)——
|
|
|
|
|
|
而 `.lb-nav` 是靠 `transform: translateY(-50%)` 做**垂直居中**的,
|
|
|
|
|
|
hover 那条**把居中的 transform 整个覆盖掉** ⇒ 鼠标一碰,按钮从"居中"跳到
|
|
|
|
|
|
"距顶 50%",**位移接近半个按钮高度**(48px 的一半),确实会点错。
|
|
|
|
|
|
⚠️ 与 v21 家谱那次 `.f3 div.card:hover > div` 覆盖库的居中 transform 是**同一个坑**。
|
|
|
|
|
|
⇒ 修:`.lb-nav:hover` 显式把它自己的居中 transform 写回去(只保留提亮,
|
|
|
|
|
|
不再抬升)。位置在 hover 前后**一字不动**,鼠标停在哪就点在哪。
|
|
|
|
|
|
⚠️ 必须写在统一 hover 段**之后**(同特异性下后者胜)—— 见文末那段里的同名规则。 */
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.lb-prev { left: 14px; }
|
|
|
|
|
|
.lb-next { right: 14px; }
|
|
|
|
|
|
.lb-bar {
|
|
|
|
|
|
position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 20px;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
|
|
|
|
|
color: #fff; font-size: 14px;
|
|
|
|
|
|
background: linear-gradient(to top, rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
|
|
|
|
|
|
}
|
|
|
|
|
|
.lb-caption { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.lb-counter { flex: 0 0 auto; opacity: .75; font-variant-numeric: tabular-nums; }
|
2026-09-30 20:22:46 +08:00
|
|
|
|
|
2026-10-01 00:12:04 +08:00
|
|
|
|
/* ---- 评价与评论 ---- */
|
|
|
|
|
|
.rv-composer > summary { list-style: none; cursor: pointer; }
|
|
|
|
|
|
.rv-composer > summary::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.rv-open-btn {
|
|
|
|
|
|
display: inline-block; padding: 8px 18px; border-radius: 10px;
|
|
|
|
|
|
background: linear-gradient(135deg, var(--brand), var(--brand-2));
|
|
|
|
|
|
color: #fff; font-size: 14px; font-weight: 600; user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rv-open-btn:hover { text-decoration: none; box-shadow: var(--shadow-l); }
|
|
|
|
|
|
.rv-composer[open] > .rv-open-btn { background: var(--line-2); color: var(--muted); }
|
|
|
|
|
|
.rv-act-btn {
|
|
|
|
|
|
display: inline-block; padding: 4px 12px; border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 20px; background: var(--surface); color: var(--muted);
|
|
|
|
|
|
font-size: 12.5px; user-select: none; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rv-act-btn:hover { border-color: var(--brand); color: var(--brand); text-decoration: none; }
|
|
|
|
|
|
.rv-composer[open] > .rv-act-btn { border-color: var(--brand); background: rgba(168, 74, 40, .08); color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.rv-form { background: var(--line-2); border-radius: 12px; padding: 16px 18px; margin-top: 10px; }
|
|
|
|
|
|
.rv-composer > .rv-form { margin-bottom: 0; }
|
|
|
|
|
|
.rv-form-inline { padding: 12px 14px; }
|
|
|
|
|
|
.rv-rating-row { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; margin-bottom: 12px; }
|
|
|
|
|
|
.rv-rating-label { font-size: 14px; font-weight: 600; color: var(--ink); }
|
2026-10-01 10:21:45 +08:00
|
|
|
|
/* ---- 10 星评分(v10):空心 ☆ 灰、点亮 ★ 金黄。
|
|
|
|
|
|
DOM 按 10..1 倒序渲染 + row-reverse,视觉即 1..10 从左到右;
|
|
|
|
|
|
「点亮的星星」由 JS 加 .lit(含悬停预览),.no-js 兜底用 :has() 只亮已选中那一档。 ---- */
|
|
|
|
|
|
.rv-scale { display: flex; gap: 2px; }
|
|
|
|
|
|
.rv-stars { flex-direction: row-reverse; justify-content: flex-end; }
|
|
|
|
|
|
.rv-star { position: relative; cursor: pointer; line-height: 1; }
|
|
|
|
|
|
.rv-star input { position: absolute; width: 1px; height: 1px; opacity: 0; }
|
|
|
|
|
|
.rv-star .st-glyph { font-size: 28px; line-height: 1; }
|
|
|
|
|
|
.rv-star .st-off { color: #c9cdd4; }
|
|
|
|
|
|
.rv-star .st-on { display: none; color: #f5b301; }
|
|
|
|
|
|
.rv-star.lit .st-on { display: inline; }
|
|
|
|
|
|
.rv-star.lit .st-off { display: none; }
|
|
|
|
|
|
.rv-star:hover .st-off { color: #aeb4be; }
|
|
|
|
|
|
.rv-star:focus-within { outline: 2px solid var(--brand); outline-offset: 1px; border-radius: 4px; }
|
|
|
|
|
|
/* 无 JS 兜底:至少选中的那一档及其左边(视觉)会亮 */
|
|
|
|
|
|
.rv-stars.no-js .rv-star:has(input:checked) .st-on,
|
|
|
|
|
|
.rv-stars.no-js .rv-star:has(input:checked) ~ .rv-star .st-on { display: inline; }
|
|
|
|
|
|
.rv-stars.no-js .rv-star:has(input:checked) .st-off,
|
|
|
|
|
|
.rv-stars.no-js .rv-star:has(input:checked) ~ .rv-star .st-off { display: none; }
|
|
|
|
|
|
/* 评价列表里的静态星级展示 */
|
|
|
|
|
|
.stars-disp { display: inline-flex; gap: 1px; font-size: 17px; line-height: 1; vertical-align: -2px; }
|
|
|
|
|
|
.stars-disp .d-on { color: #f5b301; }
|
|
|
|
|
|
.stars-disp .d-off { color: #d3d7de; }
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* ---- 财务 / 账本(v24 第 15 条) ---- */
|
|
|
|
|
|
/* 金额列右对齐 + 等宽数字(表格里数字不齐会很难扫) */
|
|
|
|
|
|
.table .num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.table tfoot th { border-top: 2px solid var(--line); border-bottom: 0; color: var(--ink); }
|
|
|
|
|
|
.led-sum-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
|
|
|
|
|
|
.led-total { display: flex; flex-wrap: wrap; gap: 18px; margin: 12px 0 4px; }
|
|
|
|
|
|
.led-total-item { display: flex; flex-direction: column; gap: 2px; }
|
|
|
|
|
|
.led-total-lb { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.led-total-num {
|
|
|
|
|
|
font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums;
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-total-item.led-net .led-total-num { color: var(--brand); }
|
|
|
|
|
|
/* 数字颜色:**收入/资产用红、负债用绿**(与 A 股涨红跌绿同一套约定,不要反) */
|
|
|
|
|
|
.led-asset { color: #B0342C; }
|
|
|
|
|
|
.led-debt { color: #1F7A4D; }
|
|
|
|
|
|
.led-kinds { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
|
|
|
|
|
|
.led-kind-chip {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 5px;
|
|
|
|
|
|
padding: 3px 9px; border-radius: 999px; font-size: 12px;
|
|
|
|
|
|
background: var(--line-2); color: var(--ink); white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-kind-chip b { font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.led-kind-chip.is-debt { background: #E7F2EC; }
|
|
|
|
|
|
.led-shares { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
|
|
|
|
|
|
.led-share-chip {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
|
|
|
|
padding: 3px 8px; border: 1px solid var(--line); border-radius: 999px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-ops { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
|
|
|
|
|
|
.led-ops .inline-form { flex-wrap: wrap; align-items: center; }
|
|
|
|
|
|
.led-ops .input { min-width: 140px; }
|
|
|
|
|
|
.led-edit summary { cursor: pointer; }
|
|
|
|
|
|
.led-edit .node-form { min-width: min(520px, 86vw); }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 财务:变化折线图 + 设置下拉(v24 用户 2026-10-03 第 7、8 条)---- */
|
|
|
|
|
|
.led-charts { margin-bottom: 0; }
|
|
|
|
|
|
.ck-grid {
|
|
|
|
|
|
display: grid; gap: 14px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.ck-card {
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7; padding: 10px 12px;
|
|
|
|
|
|
color: var(--ink); /* SVG 用 currentColor 画基线与日期,靠这里继承 */
|
|
|
|
|
|
}
|
|
|
|
|
|
.ck-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
|
|
|
|
|
|
.ck-head b { font-size: 14px; }
|
|
|
|
|
|
.ck-svg { display: block; margin-top: 2px; }
|
2026-10-04 10:46:50 +08:00
|
|
|
|
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- v24 第 11 批 #7:账目行的两个弹框(全页各一份)----
|
|
|
|
|
|
原来每行内联一套(form + 选人组件),账目一多就是几千个 form
|
|
|
|
|
|
—— 用户报的"账目页也卡、还是 Bitwarden 冲突"就是这个。
|
|
|
|
|
|
现在行上只有按钮,表单集中到 #ledPanels。 */
|
|
|
|
|
|
.led-modal {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 75;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-modal[hidden] { display: none; }
|
|
|
|
|
|
.led-mask { position: absolute; inset: 0; background: rgba(47, 36, 30, .34); }
|
|
|
|
|
|
.led-panel-lg {
|
|
|
|
|
|
position: relative; z-index: 1;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 14px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
width: min(460px, 92vw); max-height: min(86vh, 660px);
|
|
|
|
|
|
display: flex; flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-panel-lg[hidden] { display: none; }
|
|
|
|
|
|
.led-ph {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 14px 10px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-ph b { font-size: 14.5px; }
|
|
|
|
|
|
.led-x {
|
|
|
|
|
|
margin-left: auto; border: 0; background: transparent; cursor: pointer;
|
|
|
|
|
|
font-size: 15px; color: var(--muted); padding: 4px 6px; border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-x:hover { background: var(--line-2); color: var(--ink); }
|
|
|
|
|
|
.led-pb { padding: 12px 14px; overflow-y: auto; }
|
|
|
|
|
|
.led-pb .field { margin-bottom: 12px; }
|
|
|
|
|
|
.led-pb .field > label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px; }
|
|
|
|
|
|
.led-pf {
|
|
|
|
|
|
display: flex; gap: 8px; justify-content: flex-end;
|
|
|
|
|
|
padding: 10px 14px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 弹框里的选人组件别撑破面板 */
|
|
|
|
|
|
.led-pb .pp { max-width: none; }
|
|
|
|
|
|
.led-panel-lg .led-hist { margin-top: 4px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v24 第 11 批 #7:图例(只显示"哪个颜色代表哪个账目")----
|
|
|
|
|
|
用户原话:「图下面的条目不用显示详情,只需要显示每个账目的颜色,
|
|
|
|
|
|
就是说哪个颜色代表哪个账目,就可以了。」
|
|
|
|
|
|
所以从"每账目一张小卡"改成一行色块图例。 */
|
|
|
|
|
|
.ck-legend {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 6px 16px;
|
|
|
|
|
|
margin: 10px 2px 0; font-size: 13px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.ck-lg-item { display: inline-flex; align-items: center; gap: 6px; }
|
|
|
|
|
|
.ck-lg-item[hidden] { display: none; }
|
|
|
|
|
|
.ck-lg-dot {
|
|
|
|
|
|
width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto;
|
|
|
|
|
|
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 多线图:比单条小图高一点,才看得出差异 */
|
|
|
|
|
|
.ck-multi { margin-top: 4px; }
|
|
|
|
|
|
|
2026-10-04 10:46:50 +08:00
|
|
|
|
/* ---- v24 第 10 批 #3:总金额图在最前(跨整行),下面才是逐条账目 ---- */
|
|
|
|
|
|
.ck-total { margin-bottom: 14px; }
|
|
|
|
|
|
.ck-total .ck-head b { font-size: 15px; }
|
|
|
|
|
|
/* 类别筛选条:图表一多就是一坨,把筛选权交给用户(而不是少画几条骗自己) */
|
|
|
|
|
|
.ck-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
|
|
|
|
|
|
.ck-chip {
|
|
|
|
|
|
padding: 4px 11px; border: 1px solid var(--line); border-radius: 999px;
|
|
|
|
|
|
background: var(--surface); color: var(--ink); font: inherit; font-size: 13px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ck-chip:hover { border-color: var(--brand-2); }
|
|
|
|
|
|
.ck-chip.is-on { background: var(--brand); border-color: var(--brand); color: #fff; }
|
|
|
|
|
|
.ck-chip.is-debt:not(.is-on) { color: #1F7A4D; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v24 第 10 批 #3:每行的「盘点 / 修改」两个按钮 + 就地展开的面板 ---- */
|
|
|
|
|
|
.led-acts { display: flex; gap: 6px; align-items: center; white-space: nowrap; }
|
|
|
|
|
|
.led-panel {
|
|
|
|
|
|
/* 作为 <tr> 的兄弟插进来(见模板里的 JS):表格列宽会把表单切碎,格子外才排得开 */
|
|
|
|
|
|
display: block; background: #FDFBF7;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
padding: 12px 14px; margin: 0 0 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-panel .field { margin-bottom: 10px; }
|
|
|
|
|
|
.led-panel .field > label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
|
|
|
|
|
|
.led-panel .input, .led-panel .select { width: 100%; max-width: 360px; }
|
|
|
|
|
|
.led-panel .btn-row { margin-top: 4px; }
|
|
|
|
|
|
.led-panel[hidden] { display: none; }
|
|
|
|
|
|
/* 「修改」面板里嵌了选人组件,给它一个不夸张的最大宽度 */
|
|
|
|
|
|
.led-panel .pp { max-width: 420px; }
|
|
|
|
|
|
/* 盘点面板与「修改」不再同处一个 details,分隔线也就不需要了 */
|
|
|
|
|
|
.led-recon { padding-bottom: 0; border-bottom: 0; margin-bottom: 0; }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
.led-form-h { font-size: 12.5px; color: var(--muted); font-weight: 500; margin: 0 0 8px; }
|
|
|
|
|
|
.led-hist { margin-top: 6px; }
|
|
|
|
|
|
.led-hist summary { cursor: pointer; }
|
|
|
|
|
|
.led-hist-list { list-style: none; margin: 6px 0 0; padding: 0; font-size: 13px; }
|
|
|
|
|
|
.led-hist-list li {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 5px 0; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-hist-list li b { font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 账本设置下拉:比观影那个内容多,给个上限 + 内部滚动 */
|
|
|
|
|
|
.led-set .menu-list { min-width: 280px; max-width: min(340px, 94vw); }
|
|
|
|
|
|
.led-set-list { padding: 10px; gap: 0; max-height: 70vh; overflow-y: auto; }
|
|
|
|
|
|
.led-set-block { padding: 8px 2px; }
|
|
|
|
|
|
.led-set-block + .led-set-block { border-top: 1px solid var(--line-2); margin-top: 4px; }
|
|
|
|
|
|
.led-set-shares { list-style: none; margin: 0 0 8px; padding: 0; }
|
|
|
|
|
|
.led-set-shares li {
|
|
|
|
|
|
display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-set-shares li .node-badge { flex: 0 0 auto; }
|
|
|
|
|
|
.led-set-form-in { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
|
|
|
|
.led-set-form-in .input { flex: 1 1 120px; min-width: 0; }
|
|
|
|
|
|
.led-set-form-in .pp { flex: 1 1 100%; }
|
|
|
|
|
|
.led-add { margin-bottom: 18px; }
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* ---- 纪念日(v24 第 13 条) ---- */
|
|
|
|
|
|
.ann-up { list-style: none; margin: 0; padding: 0; }
|
|
|
|
|
|
.ann-up-item {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
|
|
|
|
|
|
padding: 8px 2px; border-bottom: 1px solid var(--line-2); font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ann-up-item:last-child { border-bottom: 0; }
|
|
|
|
|
|
.ann-days {
|
|
|
|
|
|
flex: 0 0 auto; min-width: 62px; font-weight: 600; color: var(--brand);
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ann-date { flex: 0 0 auto; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.ann-title { flex: 1 1 auto; color: var(--ink); min-width: 0; }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* ---- 纪念日的「关联人」列(v24 第 25 批 用户第 2 条)----
|
|
|
|
|
|
用户原话:「再加一列,关联人。列表中,人的前面,都加头像。」
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 列里画的是全站统一的 person_chip(`.viewer-tag`,自带头像 + 底色),
|
|
|
|
|
|
所以这里只需要处理**排布**,不要另造一套人名样式(会与其它模块不一致)。
|
|
|
|
|
|
⚠️ 关联多个人时要能换行 —— `.viewer-tag` 是 `inline-flex`,
|
|
|
|
|
|
不写 flex-wrap 的话 5 个人会把表格撑宽(手机上直接横向溢出)。
|
|
|
|
|
|
⚠️ 「改/删」两个按钮要排成一行:`.res-inline` 那个 form 是 inline 的,
|
|
|
|
|
|
但两个按钮之间得靠 gap 分开,否则会贴在一起、看着像一个双色按钮。 */
|
|
|
|
|
|
.ann-people { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; max-width: 260px; }
|
|
|
|
|
|
.ann-acts { display: flex; gap: 6px; align-items: center; }
|
|
|
|
|
|
.ann-acts .btn { flex: 0 0 auto; }
|
|
|
|
|
|
@media (max-width: 767px) {
|
|
|
|
|
|
/* 窄屏:关联人那一列不再限宽(表格本来就会横向滚动),
|
|
|
|
|
|
但两个按钮要保持不换行 —— 换行后「删除」会掉到「修改」下面,
|
|
|
|
|
|
在表格行里看着像两张卡片。 */
|
|
|
|
|
|
.ann-people { max-width: none; }
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.chk-inline { display: flex; align-items: center; gap: 6px; font-size: 14px; }
|
|
|
|
|
|
/* ---- 任务设置(v24 第 9、10 条):看板/分类的增删改列表 ---- */
|
|
|
|
|
|
.kb-boards { margin-bottom: 12px; }
|
|
|
|
|
|
.set-list { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 0; }
|
|
|
|
|
|
/* 一行 = 一个「改名」表单 + 一个「删除」表单,靠 flex 排成一条 */
|
|
|
|
|
|
.set-row { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; margin: 0; }
|
|
|
|
|
|
.set-row .input { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.set-tail { flex: 0 0 auto; }
|
|
|
|
|
|
/* 「已完成」归档列表 */
|
|
|
|
|
|
.done-list { list-style: none; margin: 0; padding: 0; }
|
|
|
|
|
|
.done-item {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
|
|
|
|
|
|
padding: 9px 2px; border-bottom: 1px solid var(--line-2); font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.done-item:last-child { border-bottom: 0; }
|
|
|
|
|
|
.done-title { color: var(--ink); text-decoration: none; }
|
|
|
|
|
|
.done-title:hover { color: var(--brand); text-decoration: underline; }
|
|
|
|
|
|
/* ---- 附件缩略图墙 + 全局预览(v24 第 3 条) ----
|
|
|
|
|
|
规则:图片/视频给缩略图,PDF/Word/Excel 给**同尺寸**图标;
|
|
|
|
|
|
可预览的点开在本页这一层里看,不可预览的点了直接下载。 */
|
|
|
|
|
|
.att-wall {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 12px; margin: 8px 0 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.att-cell { width: 132px; }
|
|
|
|
|
|
/* ⚠️ 缩略图与文档图标**必须是同一个盒子**:用户要的是"图标跟预览图一样大小",
|
|
|
|
|
|
所以尺寸只在这里写一次,图标靠 flex 撑满,不另给一套尺寸。 */
|
|
|
|
|
|
.att-thumb {
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
width: 132px; height: 96px; border-radius: 8px; overflow: hidden;
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--line-2); position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.att-thumb:hover { border-color: var(--brand); }
|
|
|
|
|
|
.att-thumb img, .att-thumb video {
|
|
|
|
|
|
width: 100%; height: 100%; object-fit: cover; display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.att-thumb video { object-fit: cover; pointer-events: none; }
|
|
|
|
|
|
.att-play {
|
|
|
|
|
|
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
color: #fff; font-size: 22px; text-shadow: 0 2px 8px rgba(0, 0, 0, .6); pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.att-doc {
|
|
|
|
|
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
2026-10-05 22:56:49 +08:00
|
|
|
|
gap: 4px; width: 100%; height: 100%; padding: 6px;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
font-size: 12px; font-weight: 700; letter-spacing: .5px; color: #fff;
|
2026-10-05 22:56:49 +08:00
|
|
|
|
text-align: center; box-sizing: border-box;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
.att-doc::before {
|
|
|
|
|
|
content: ""; width: 34px; height: 34px; border-radius: 6px; background: rgba(255, 255, 255, .22);
|
2026-10-05 22:56:49 +08:00
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* v24 第 19 批 用户第 6 条「如果是文件,则在图标上显示文件名」:
|
|
|
|
|
|
文件名压着色块显示 —— 文件就是**读名字**的,名字才是最该看清的东西。
|
|
|
|
|
|
⚠️ 两行封顶 + 省略号:文件名可以很长(「学位学历证书_博士学位证书_2022-07-08-17-05-53.jpeg」),
|
|
|
|
|
|
不截就会把图标撑变形、把相邻的格子挤歪。完整名字仍能从悬停 title / 下载看到。 */
|
|
|
|
|
|
.att-doc-name {
|
|
|
|
|
|
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
|
|
|
|
overflow: hidden; word-break: break-all; line-height: 1.35;
|
|
|
|
|
|
max-width: 100%; font-size: 11px; font-weight: 600; letter-spacing: 0;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
.att-doc-pdf { background: #B0342C; }
|
|
|
|
|
|
.att-doc-doc { background: #2C5AA0; }
|
|
|
|
|
|
.att-doc-xls { background: #1F7A4D; }
|
|
|
|
|
|
.att-doc-ppt { background: #B4622A; }
|
|
|
|
|
|
.att-doc-text { background: #5F6672; }
|
|
|
|
|
|
.att-doc-file { background: #5F6672; }
|
|
|
|
|
|
.att-meta {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
|
|
|
|
|
|
margin-top: 4px; font-size: 12px; color: var(--muted);
|
|
|
|
|
|
}
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* v24 第 19 批 用户第 6 条:缩略图下面**不再放文件名**(那串是上传时的原始名,
|
|
|
|
|
|
图片/视频是"看"的,一串哈希既认不出内容也不比缩略图本身多信息)。
|
|
|
|
|
|
`.att-fname` 的规则保留 —— 万一将来又要在某处显示一行名字,样式不用重写。 */
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.att-fname {
|
|
|
|
|
|
flex: 1 1 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
|
|
|
|
color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.att-fsize { flex: 0 0 auto; }
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* ---- 拖动上传(v24 第 19 批 用户第 1 条)----
|
|
|
|
|
|
用户原话:「为所有的图片视频附件上传处,提供拖动上传的功能,就是允许用户,
|
|
|
|
|
|
通过把文件拖动到那里进行上传。」
|
|
|
|
|
|
⚠️ 类名 `.dropzone` 由 app.js **自动给页面上每个 file 控件挂上**,
|
|
|
|
|
|
并且给「`data-pick-input` 指向该控件的预览图」也挂一份 —— 题图/头像那类
|
|
|
|
|
|
控件的 input 是 sr-only(看不见),往旁边那张图上拖才是最自然的动作。
|
|
|
|
|
|
全站十几处上传点一次性都获得这个能力(不改任何模板)。
|
|
|
|
|
|
⚠️ 落在哪儿由 `.is-over` 高亮体现;真正的落文件逻辑在 app.js 里
|
|
|
|
|
|
(DataTransfer → input.files → 手动派发 change)。
|
|
|
|
|
|
⚠️ 曾经想过再加一句常驻的「也可以把文件拖到这里」小字,**去掉了**:
|
|
|
|
|
|
十几个上传点各多一行灰字,页面会明显变吵,而"拖动"本身不是必须被教导的能力。 */
|
|
|
|
|
|
.dropzone { position: relative; }
|
|
|
|
|
|
.dropzone.is-over {
|
|
|
|
|
|
outline: 2px dashed var(--brand); outline-offset: 3px;
|
|
|
|
|
|
background: #FDF3EC; border-radius: var(--radius-s);
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.att-meta form { display: inline; margin: 0; }
|
|
|
|
|
|
/* ---- 全局预览层 ---- */
|
|
|
|
|
|
.pv {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 320; display: flex; flex-direction: column;
|
|
|
|
|
|
background: rgba(0, 0, 0, .9); overscroll-behavior: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ .pv 自己声明了 display:flex,必须补这条,否则 preview.js 里的
|
|
|
|
|
|
box.hidden = true 藏不住它(与 .pp-item 同一个坑)。 */
|
|
|
|
|
|
.pv[hidden] { display: none; }
|
|
|
|
|
|
.pv-head {
|
|
|
|
|
|
flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 16px; color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-name {
|
|
|
|
|
|
min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-meta { flex: 0 0 auto; font-size: 12px; opacity: .7; }
|
|
|
|
|
|
/* 下载按钮恒在右上角(用户第 3 条点名要求) */
|
|
|
|
|
|
.pv-dl {
|
|
|
|
|
|
margin-left: auto; flex: 0 0 auto; padding: 6px 14px; border-radius: 8px;
|
|
|
|
|
|
background: #fff; color: #1a1a1a; font-size: 13px; font-weight: 600; text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-dl:hover { background: #eee; }
|
|
|
|
|
|
.pv-close {
|
|
|
|
|
|
flex: 0 0 auto; border: 0; background: rgba(255, 255, 255, .16); color: #fff;
|
|
|
|
|
|
width: 34px; height: 34px; border-radius: 50%; font-size: 16px; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-close:hover { background: rgba(255, 255, 255, .28); }
|
|
|
|
|
|
.pv-stage {
|
|
|
|
|
|
flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
padding: 0 16px 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-img {
|
|
|
|
|
|
max-width: 92vw; max-height: 100%; width: auto; height: auto;
|
|
|
|
|
|
object-fit: contain; border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-video { max-width: 92vw; max-height: 100%; width: auto; height: auto; background: #000; }
|
|
|
|
|
|
.pv-pdf {
|
|
|
|
|
|
width: 92vw; height: 100%; border: 0; border-radius: 8px; background: #fff;
|
|
|
|
|
|
}
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* ---- 左右翻页箭头(v24 第 19 批 用户第 6 条)----
|
|
|
|
|
|
用户原话:「预览的时候,左右有箭头,可以直接查看下一张。」
|
|
|
|
|
|
⚠️ 左右各一个圆形按钮,垂直居中、压在内容两侧。禁用态(第一张/最后一张)
|
|
|
|
|
|
要**看得出来**(半透明 + 禁止光标),否则用户会以为"点了没反应"。 */
|
|
|
|
|
|
.pv-nav {
|
|
|
|
|
|
position: fixed; top: 50%; transform: translateY(-50%); z-index: 5;
|
|
|
|
|
|
width: 46px; height: 46px; border-radius: 50%; border: 0; cursor: pointer;
|
|
|
|
|
|
background: rgba(255, 255, 255, .2); color: #fff; font-size: 30px; line-height: 1;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center; padding: 0 0 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.pv-nav:hover:not(:disabled) { background: rgba(255, 255, 255, .34); }
|
|
|
|
|
|
.pv-nav:disabled { opacity: .28; cursor: default; }
|
|
|
|
|
|
/* ⚠️ 与 .pv 同一个老坑:这里自己声明了 display:flex,不补 [hidden] 就藏不住 ——
|
|
|
|
|
|
只有一个可预览项时箭头必须消失,靠的就是这条。 */
|
|
|
|
|
|
.pv-nav[hidden] { display: none; }
|
|
|
|
|
|
.pv-prev { left: 14px; }
|
|
|
|
|
|
.pv-next { right: 14px; }
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.pv-nav { width: 40px; height: 40px; font-size: 26px; }
|
|
|
|
|
|
.pv-prev { left: 6px; }
|
|
|
|
|
|
.pv-next { right: 6px; }
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.att-cell, .att-thumb { width: 108px; }
|
|
|
|
|
|
.att-thumb { height: 80px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ---- 全局人员选择器(v24 第 11 条):chips + 弹窗 + 拼音首字母联想 ----
|
|
|
|
|
|
⚠️ .att-* 是这套组件早年在观影页的版本,已由 .pp-* 取代;
|
|
|
|
|
|
保留只为历史样式,新页面一律用 _person_picker.php。 */
|
|
|
|
|
|
.pp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
|
|
|
|
|
|
.pp-chip {
|
2026-10-01 12:11:43 +08:00
|
|
|
|
display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 4px;
|
2026-10-01 10:21:45 +08:00
|
|
|
|
border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
|
|
|
|
|
|
font-size: 13px;
|
2026-10-01 00:12:04 +08:00
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-chip img {
|
2026-10-01 12:11:43 +08:00
|
|
|
|
width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: 0 0 auto;
|
|
|
|
|
|
background: #F1E7D6;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-chip .pp-x {
|
2026-10-01 10:21:45 +08:00
|
|
|
|
border: 0; background: none; color: var(--muted); font-size: 15px;
|
|
|
|
|
|
line-height: 1; padding: 0 2px; cursor: pointer;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-chip .pp-x:hover { color: #c0392b; }
|
|
|
|
|
|
.pp-chip-empty { color: var(--muted); border-style: dashed; padding: 3px 10px; }
|
|
|
|
|
|
.pp-modal {
|
2026-10-01 10:21:45 +08:00
|
|
|
|
position: fixed; inset: 0; z-index: 60; display: flex; align-items: center;
|
|
|
|
|
|
justify-content: center; background: rgba(0, 0, 0, .35); padding: 16px;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-modal[hidden] { display: none; }
|
|
|
|
|
|
.pp-modal-box {
|
2026-10-01 10:21:45 +08:00
|
|
|
|
background: var(--surface); border-radius: 12px; box-shadow: 0 12px 40px rgba(0, 0, 0, .2);
|
|
|
|
|
|
width: min(420px, 100%); max-height: 70vh; display: flex; flex-direction: column;
|
|
|
|
|
|
padding: 14px 16px; box-sizing: border-box;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
|
|
|
|
|
|
.pp-close {
|
2026-10-01 10:21:45 +08:00
|
|
|
|
border: 0; background: none; font-size: 20px; line-height: 1;
|
|
|
|
|
|
color: var(--muted); cursor: pointer; padding: 2px 6px;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-modal-box .input { margin-bottom: 8px; }
|
|
|
|
|
|
.pp-list { overflow-y: auto; border: 1px solid var(--line); border-radius: 8px; }
|
|
|
|
|
|
.pp-item {
|
2026-10-01 10:21:45 +08:00
|
|
|
|
display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer;
|
|
|
|
|
|
border-bottom: 1px solid var(--line-2); font-size: 14px;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* ⚠️ 这条不能省:.pp-item 自己写了 display:flex,作者样式压过浏览器
|
|
|
|
|
|
[hidden] { display:none },缺了它「过滤」就成了摆设 —— 名字和拼音都搜不动。
|
|
|
|
|
|
弹窗 .pp-modal 同理(上面已有),凡是**自己声明了 display** 的元素要藏都得补一条。 */
|
|
|
|
|
|
.pp-item[hidden] { display: none; }
|
|
|
|
|
|
.pp-item:last-child { border-bottom: 0; }
|
|
|
|
|
|
.pp-item:hover { background: var(--line-2); }
|
|
|
|
|
|
.pp-item input { accent-color: var(--brand); flex: 0 0 auto; }
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* v24 第 19 批 用户第 8 条:「前面的复选框就没用了吧,去掉吧。」
|
|
|
|
|
|
⚠️ 多选时复选框**确实没用**了 —— 第 18 批起"选谁"靠点头像/名字(点击整行),
|
|
|
|
|
|
勾选与否只由暂存区的 chip 表达,一个小小的方框反而是干扰。
|
|
|
|
|
|
JS 给多选组件加 `.pp-compact` 才隐藏;**单选不隐藏**(单选的圆点是他唯一
|
|
|
|
|
|
能看见"现在选的是谁"的地方)。
|
|
|
|
|
|
⚠️ 只是 `display:none`,input **仍在 DOM 里** —— 表单提交全靠它。
|
|
|
|
|
|
千万别改成 remove()(那就变成"选了保存后没人")。 */
|
|
|
|
|
|
.pp-compact .pp-item input { display: none; }
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-item .pp-av {
|
2026-10-01 12:11:43 +08:00
|
|
|
|
width: 30px; height: 30px; border-radius: 50%; object-fit: cover; flex: 0 0 auto;
|
|
|
|
|
|
background: #F1E7D6;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.pp-item .pp-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.pp-item .pp-initials { margin-left: auto; color: var(--muted); font-size: 12px; }
|
|
|
|
|
|
.pp-item-none .pp-name { color: var(--muted); }
|
|
|
|
|
|
.pp-empty { padding: 10px 12px; color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
.pp-empty[hidden] { display: none; }
|
2026-10-01 10:21:45 +08:00
|
|
|
|
/* ---- 豆瓣自动补充(v10):片名行 + 下拉候选 + 海报预览 ---- */
|
|
|
|
|
|
.db-title-row { display: flex; gap: 8px; align-items: center; }
|
|
|
|
|
|
.db-title-row .input { flex: 1 1 auto; }
|
|
|
|
|
|
.db-title-row .btn { flex: 0 0 auto; white-space: nowrap; }
|
|
|
|
|
|
.db-suggest {
|
|
|
|
|
|
margin-top: 6px; border: 1px solid var(--line); border-radius: 10px;
|
|
|
|
|
|
background: var(--surface); overflow: hidden; max-height: 300px; overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.db-suggest[hidden] { display: none; }
|
|
|
|
|
|
.db-item {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 12px;
|
|
|
|
|
|
border: 0; border-bottom: 1px solid var(--line-2); background: none;
|
|
|
|
|
|
text-align: left; cursor: pointer; font: inherit; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.db-item:last-child { border-bottom: 0; }
|
|
|
|
|
|
.db-item:hover { background: var(--line-2); }
|
|
|
|
|
|
.db-item img { width: 32px; height: 45px; object-fit: cover; border-radius: 4px; background: var(--line-2); flex: 0 0 auto; }
|
|
|
|
|
|
.db-item-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
|
|
|
|
.db-item-tx b { font-size: 14px; }
|
|
|
|
|
|
.db-item-tx small { color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.db-poster-preview { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
|
|
|
|
|
|
.db-poster-preview[hidden] { display: none; }
|
|
|
|
|
|
.db-poster-preview img {
|
|
|
|
|
|
width: 60px; height: 90px; object-fit: cover; border-radius: 6px;
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 详情页英雄区里的豆瓣信息块 */
|
|
|
|
|
|
.db-meta {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
|
|
|
|
|
|
margin: 8px 0 2px; padding: 8px 12px; border-radius: 10px;
|
|
|
|
|
|
background: var(--line-2); font-size: 13px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.db-meta .db-rating { color: #f5b301; font-weight: 600; }
|
|
|
|
|
|
.db-meta .db-rating b { font-size: 16px; }
|
|
|
|
|
|
.db-meta .db-line { display: inline-flex; gap: 6px; align-items: baseline; min-width: 0; }
|
|
|
|
|
|
.db-meta .db-label { color: var(--muted); flex: 0 0 auto; }
|
|
|
|
|
|
.db-meta .db-link { margin-left: auto; color: var(--brand); text-decoration: none; white-space: nowrap; }
|
|
|
|
|
|
.db-meta .db-link:hover { text-decoration: underline; }
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.rv-word { font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.rv-word.is-set { color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.rv-textarea {
|
|
|
|
|
|
width: 100%; min-height: 92px; resize: vertical; padding: 12px 14px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 10px; font-size: 15px;
|
|
|
|
|
|
font-family: inherit; line-height: 1.7; background: var(--surface);
|
|
|
|
|
|
color: var(--ink); box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rv-textarea:focus { outline: none; border-color: var(--brand); }
|
|
|
|
|
|
.rv-textarea-sm { min-height: 56px; font-size: 14px; }
|
|
|
|
|
|
.rv-form-foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
|
|
|
|
|
|
.rv-form-foot .rv-hint { margin-right: auto; }
|
|
|
|
|
|
.rv-hint { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.rv-pick-label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
|
|
|
|
|
|
.rv-empty { color: var(--muted); font-size: 14px; }
|
|
|
|
|
|
.rv-list { display: flex; flex-direction: column; gap: 18px; }
|
|
|
|
|
|
.rv-item { border-top: 1px solid var(--line-2); padding-top: 16px; }
|
|
|
|
|
|
.rv-item:first-child { border-top: none; padding-top: 0; }
|
|
|
|
|
|
.rv-head { display: flex; align-items: center; gap: 10px; }
|
|
|
|
|
|
.rv-avatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
|
|
|
|
|
.rv-avatar-sm { width: 26px; height: 26px; }
|
|
|
|
|
|
.rv-avatar-text {
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
background: var(--line-2); color: var(--muted); font-weight: 600; font-size: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rv-who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
|
|
|
|
.rv-name { font-size: 14px; font-weight: 600; color: var(--ink); }
|
2026-10-01 12:11:43 +08:00
|
|
|
|
/* ⚠️ 写着「我」的那个徽标(类名是「评价」区块 + 「我的」后缀)v11 删掉了:
|
|
|
|
|
|
它在 .rv-who(flex column)里被 align-items:stretch 拉成整行宽的色带,
|
|
|
|
|
|
星星旁边显出一条丑长的品牌色条。删除按钮已经表达了「这是我写的」,
|
|
|
|
|
|
不需要徽标。别再把它加回来。 */
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.rv-time { display: block; font-size: 12px; color: var(--muted); }
|
2026-10-01 10:21:45 +08:00
|
|
|
|
.rv-score { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px; }
|
|
|
|
|
|
.rv-score .stars-disp { font-size: 16px; }
|
|
|
|
|
|
.rv-score-max { font-size: 12px; font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.rv-del { margin-left: auto; }
|
|
|
|
|
|
.rv-del-btn {
|
|
|
|
|
|
background: none; border: none; cursor: pointer; color: var(--muted);
|
|
|
|
|
|
font-size: 14px; line-height: 1; padding: 4px 6px; border-radius: 6px;
|
|
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.rv-del-btn:hover { color: var(--red); } /* 底色交给统一段 */
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.rv-content {
|
|
|
|
|
|
margin: 8px 0 2px 44px; font-size: 15px; line-height: 1.75;
|
|
|
|
|
|
color: var(--ink); word-break: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rv-updated { margin-left: 44px; font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.rv-comments { margin: 10px 0 10px 44px; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.rv-comment { display: flex; gap: 8px; background: var(--line-2); border-radius: 10px; padding: 8px 12px; }
|
|
|
|
|
|
.rv-c-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
|
|
|
|
.rv-c-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.rv-c-head .rv-name { font-size: 13px; }
|
|
|
|
|
|
.rv-c-text { font-size: 14px; line-height: 1.7; color: var(--ink); word-break: break-word; }
|
|
|
|
|
|
.rv-c-acts { margin-top: 6px; }
|
|
|
|
|
|
.rv-thread { display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.rv-comment-reply { margin-left: 22px; }
|
|
|
|
|
|
.rv-at { font-size: 12.5px; color: var(--muted); margin-bottom: 2px; }
|
|
|
|
|
|
.rv-at span { color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.rv-actions { display: flex; align-items: flex-start; gap: 8px 10px; flex-wrap: wrap; margin: 12px 0 0 44px; }
|
|
|
|
|
|
.rv-feelings { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 2px; }
|
|
|
|
|
|
.rv-item > .rv-feelings { margin-left: 44px; }
|
|
|
|
|
|
.rv-feeling-pick { margin-top: 8px; }
|
|
|
|
|
|
.feel-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
|
|
|
|
.feel-chip { display: inline-flex; }
|
|
|
|
|
|
.feel-pick { position: relative; }
|
|
|
|
|
|
.feel-pick input { position: absolute; width: 1px; height: 1px; opacity: 0; }
|
|
|
|
|
|
.feel-inner {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 20px; background: var(--surface);
|
|
|
|
|
|
font-size: 13px; color: var(--muted); cursor: pointer; user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.feel-pick:hover .feel-inner { border-color: var(--brand); }
|
|
|
|
|
|
.feel-pick input:checked + .feel-inner { border-color: var(--brand); background: rgba(168, 74, 40, .10); color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.feel-pick:focus-within .feel-inner { outline: 2px solid var(--brand); outline-offset: 1px; }
|
|
|
|
|
|
.feel-emoji { font-size: 14px; }
|
|
|
|
|
|
.feel-chip.is-static {
|
|
|
|
|
|
align-items: center; gap: 4px; padding: 2px 10px; border-radius: 20px;
|
|
|
|
|
|
background: rgba(168, 74, 40, .10); color: var(--brand); font-size: 12px;
|
|
|
|
|
|
}
|
2026-09-30 20:22:46 +08:00
|
|
|
|
|
2026-10-01 00:12:04 +08:00
|
|
|
|
/* ---- 影院管理页 ---- */
|
|
|
|
|
|
.cinema-h2 { font-size: 17px; font-weight: 600; margin: 0 0 14px; }
|
|
|
|
|
|
.cinema-select-row { display: flex; gap: 10px; align-items: center; }
|
|
|
|
|
|
.cinema-select-row .select { flex: 1; }
|
|
|
|
|
|
.color-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
|
|
|
|
|
|
.color-picker { width: 60px; height: 40px; padding: 2px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); cursor: pointer; }
|
|
|
|
|
|
.color-hex { font-size: 14px; color: var(--muted); font-family: monospace; }
|
|
|
|
|
|
.preset-palette { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
|
|
|
|
.preset-color {
|
|
|
|
|
|
display: inline-block; width: 28px; height: 28px; border-radius: 50%;
|
|
|
|
|
|
cursor: pointer; border: 2px solid transparent; transition: transform .2s, border-color .2s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.preset-color:hover { transform: scale(1.1); }
|
|
|
|
|
|
.preset-color.active { border-color: var(--ink); }
|
|
|
|
|
|
.color-preview {
|
|
|
|
|
|
display: inline-block; width: 14px; height: 14px; border-radius: 3px;
|
|
|
|
|
|
margin-right: 6px; vertical-align: middle; border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.table-wrap { overflow-x: auto; }
|
|
|
|
|
|
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
|
|
|
|
|
.table th { text-align: left; padding: 10px 8px; border-bottom: 2px solid var(--line); color: var(--muted); font-weight: 600; }
|
|
|
|
|
|
.table td { padding: 10px 8px; border-bottom: 1px solid var(--line-2); }
|
|
|
|
|
|
.table tr:hover td { background: var(--line-2); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 观影响应式 ---- */
|
2026-09-30 20:22:46 +08:00
|
|
|
|
@media (max-width: 720px) {
|
2026-10-01 00:12:04 +08:00
|
|
|
|
.waterfall { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
|
|
|
|
|
|
.card-body { padding: 10px 12px 12px; }
|
|
|
|
|
|
.card-title { font-size: 14px; }
|
|
|
|
|
|
.card-meta { font-size: 11px; gap: 4px 10px; }
|
|
|
|
|
|
.detail-hero { grid-template-columns: 1fr; padding: 20px; }
|
|
|
|
|
|
.detail-poster { max-width: 240px; margin: 0 auto; }
|
|
|
|
|
|
.cinema-info { grid-template-columns: 1fr; }
|
|
|
|
|
|
.gallery-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
|
|
|
|
|
|
.detail-section { padding: 16px 18px; }
|
|
|
|
|
|
.detail-info h1 { font-size: 22px; }
|
|
|
|
|
|
.rv-content, .rv-updated, .rv-comments, .rv-actions, .rv-item > .rv-feelings { margin-left: 0; }
|
|
|
|
|
|
.rv-comment-reply { margin-left: 10px; }
|
|
|
|
|
|
.lb-nav { width: 40px; height: 40px; font-size: 24px; }
|
|
|
|
|
|
.lb-prev { left: 6px; }
|
|
|
|
|
|
.lb-next { right: 6px; }
|
|
|
|
|
|
.lb-img { max-width: 88vw; max-height: 70vh; }
|
2026-09-30 20:22:46 +08:00
|
|
|
|
}
|
2026-10-01 12:11:43 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v11:观影统计 / 高级搜索 / 年度报告(从 MovieLog 迁入)
|
|
|
|
|
|
版式沿用家书的暖纸配色;图表全用 CSS(不引 CDN 图表库)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 统计仪表板 ---- */
|
|
|
|
|
|
.stats-grid {
|
|
|
|
|
|
display: grid; gap: 14px; margin-bottom: 16px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.stat-card {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
|
|
|
|
|
|
padding: 16px 18px; text-align: center; box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.stat-card .number { font-size: 30px; font-weight: 700; color: var(--brand); line-height: 1.2; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.stat-card .label { font-size: 13px; color: var(--muted); margin-top: 2px; }
|
|
|
|
|
|
.stats-span {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 12px; margin-bottom: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stats-span .label { font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.stats-span .value { font-size: 16px; font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
.chart-card {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
|
|
|
|
|
|
padding: 18px 22px; box-shadow: var(--shadow); margin-bottom: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.chart-card h3 { font-size: 16px; font-weight: 600; margin: 0 0 14px; display: flex; align-items: baseline; gap: 8px; }
|
|
|
|
|
|
.chart-card h3 .hint { font-size: 12px; color: var(--faint); font-weight: 400; }
|
|
|
|
|
|
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
|
|
|
|
|
@media (max-width: 720px) { .two-col { grid-template-columns: 1fr; } }
|
|
|
|
|
|
|
|
|
|
|
|
.bar-chart { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.bar-item { display: flex; align-items: center; gap: 12px; }
|
|
|
|
|
|
.bar-item .bar-label {
|
|
|
|
|
|
width: 150px; flex: 0 0 auto; font-size: 13px; color: var(--ink);
|
|
|
|
|
|
display: flex; align-items: center; gap: 6px;
|
|
|
|
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bar-item .bar-label .bar-sub { color: var(--faint); font-size: 11px; }
|
|
|
|
|
|
.bar-item .bar-avatar { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
|
|
|
|
|
.bar-item .color-dot { display: inline-block; width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
|
|
|
|
|
|
.bar-item .bar-track {
|
|
|
|
|
|
flex: 1; height: 20px; background: var(--line-2); border-radius: 6px; overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bar-item .bar-fill {
|
|
|
|
|
|
display: block; height: 100%; border-radius: 6px; background: var(--brand);
|
|
|
|
|
|
}
|
|
|
|
|
|
.bar-item .bar-fill-alt { background: var(--brand-2); }
|
|
|
|
|
|
.bar-item .bar-fill-green { background: var(--green); }
|
|
|
|
|
|
.bar-item .bar-count {
|
|
|
|
|
|
width: 40px; flex: 0 0 auto; text-align: right; font-size: 13px; font-weight: 600;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
}
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.bar-item .bar-label { width: 92px; font-size: 12px; }
|
|
|
|
|
|
.bar-item .bar-count { width: 30px; }
|
|
|
|
|
|
.chart-card { padding: 14px 16px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 高级搜索 ---- */
|
|
|
|
|
|
.adv-form { margin-bottom: 18px; }
|
|
|
|
|
|
.date-range { display: flex; align-items: center; gap: 8px; }
|
|
|
|
|
|
.date-range .to { color: var(--muted); font-size: 13px; flex: 0 0 auto; }
|
|
|
|
|
|
/* ⚠️ 原生 <input type="date"> 的 min-width:auto 约 150px(带日历图标 + 占位数字)——
|
|
|
|
|
|
两个日期框 + 「至」在 360px 下会横向溢出(实测 scrollW 390 > clientW 360)。
|
|
|
|
|
|
给 0 并让它们等比收缩;这是继 .field(select)之后同一页的第二个溢出源。 */
|
|
|
|
|
|
.date-range .input { flex: 1 1 0; min-width: 0; }
|
|
|
|
|
|
.results-head {
|
|
|
|
|
|
display: flex; align-items: baseline; justify-content: space-between;
|
|
|
|
|
|
gap: 10px; margin: 0 2px 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.results-head h3 { margin: 0; font-size: 17px; }
|
|
|
|
|
|
.results-head .sub { color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 年度报告 ---- */
|
|
|
|
|
|
.year-pick { display: inline-block; }
|
|
|
|
|
|
.report-grid {
|
|
|
|
|
|
display: grid; gap: 14px; margin-bottom: 16px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.report-grid.two { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
|
|
|
|
|
|
.report-card {
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
|
|
|
|
|
|
padding: 18px 20px; box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.report-card .n { font-size: 32px; font-weight: 700; color: var(--brand); line-height: 1.15; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.report-card .l { font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.report-card .v { font-size: 19px; font-weight: 600; margin-top: 2px; }
|
|
|
|
|
|
.report-card .s { font-size: 12px; color: var(--faint); margin-top: 4px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 月份竖柱图(纯 CSS) */
|
|
|
|
|
|
.vgrid {
|
|
|
|
|
|
display: grid; grid-template-columns: repeat(12, 1fr); gap: 6px;
|
|
|
|
|
|
align-items: end; height: 160px; margin-top: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.vcol { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 3px; }
|
|
|
|
|
|
.vcol .vbar {
|
|
|
|
|
|
width: 68%; min-height: 2px; background: linear-gradient(var(--brand-2), var(--brand));
|
|
|
|
|
|
border-radius: 5px 5px 2px 2px; transition: height .4s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.vcol .vlab { font-size: 11px; color: var(--muted); }
|
|
|
|
|
|
.vcol .vnum { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
|
|
|
|
|
|
.kw-cloud { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
.kw-cloud .kw {
|
|
|
|
|
|
font-size: 14px; padding: 4px 12px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--brand-ink); border: 1px solid var(--line);
|
|
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
|
|
|
|
|
|
/* ==================== v12:旅程 / 日程 / 资源 / 任务 ==================== */
|
|
|
|
|
|
/* 四个新模块共用一套"卡片骨架"(.card + .card-pad + .cinema-h2 的小标题),
|
|
|
|
|
|
下面只写各模块**特有**的部件,避免又造一套并行的卡片。 */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 旅程 ---- */
|
|
|
|
|
|
.trip-list { display: flex; flex-direction: column; gap: 12px; }
|
|
|
|
|
|
.trip-card {
|
|
|
|
|
|
display: flex; gap: 16px; background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 14px; text-decoration: none; color: inherit;
|
|
|
|
|
|
transition: transform .18s ease, box-shadow .18s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.trip-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-l); text-decoration: none; }
|
|
|
|
|
|
.trip-cover {
|
|
|
|
|
|
width: 132px; height: 96px; flex: 0 0 auto; border-radius: var(--radius-s);
|
|
|
|
|
|
overflow: hidden; background: #F1E7D6; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.trip-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
|
|
|
|
.trip-cover-empty { font-size: 34px; opacity: .55; }
|
|
|
|
|
|
.trip-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.trip-title { font-size: 17px; font-weight: 600; margin: 0; }
|
|
|
|
|
|
.trip-meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.trip-sum { margin: 0; font-size: 14px; color: var(--muted); line-height: 1.6; }
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* 老数据(只有 events.note、还没搬成 summary)时的一句提示 ——
|
|
|
|
|
|
见 templates/trips/show.php 里第 19 批 第 4 条的说明。 */
|
|
|
|
|
|
.trip-sum-legacy {
|
|
|
|
|
|
margin: 0; font-size: 13px; color: var(--muted);
|
|
|
|
|
|
background: #FDF3EC; border: 1px dashed rgba(168, 74, 40, .3);
|
|
|
|
|
|
border-radius: var(--radius-s); padding: 8px 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.trip-sum-legacy a { font-weight: 600; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.trip-people { display: flex; flex-wrap: wrap; gap: 4px 8px; }
|
|
|
|
|
|
|
|
|
|
|
|
.trip-hero { display: flex; gap: 20px; flex-wrap: wrap; }
|
2026-10-05 13:26:49 +08:00
|
|
|
|
/* ⚠️ v24 第 16 批 用户第 1 条:「题图应该按照 16:9 显示,因为添加的时候,
|
|
|
|
|
|
是按照这个比例裁剪的,现在的显示比例不对」—— 原来是 4:3 把 16:9 的图裁掉了两边。
|
|
|
|
|
|
这个数字必须与 ImageSlot 的 'cover' 槽位比例**一致**(部署断言专门比对两处)。 */
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.trip-hero-cover {
|
2026-10-05 13:26:49 +08:00
|
|
|
|
width: 420px; max-width: 100%; aspect-ratio: 16 / 9; flex: 0 0 auto;
|
|
|
|
|
|
border-radius: var(--radius-s);
|
2026-10-02 09:28:07 +08:00
|
|
|
|
overflow: hidden; background: #F1E7D6; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.trip-hero-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
|
|
|
|
.trip-hero-body { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.trip-loc { margin: 0; font-size: 14px; color: var(--muted); }
|
|
|
|
|
|
.cover-now { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
|
|
|
|
|
|
.cover-now img { width: 96px; height: 64px; object-fit: cover; border-radius: 8px; display: block; }
|
|
|
|
|
|
|
|
|
|
|
|
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
|
|
|
|
|
|
.photo-cell { margin: 0; background: #F1E7D6; border-radius: var(--radius-s); overflow: hidden; }
|
|
|
|
|
|
.photo-cell a { display: block; }
|
|
|
|
|
|
.photo-cell img { width: 100%; height: 120px; object-fit: cover; display: block; }
|
|
|
|
|
|
.photo-del { padding: 6px; text-align: center; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 行程节点 ---- */
|
|
|
|
|
|
.node-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.node-row {
|
|
|
|
|
|
display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px;
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s); background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.node-row.status-cancelled { opacity: .62; }
|
|
|
|
|
|
.node-row.status-done .node-head b { color: var(--muted); }
|
|
|
|
|
|
.node-ico { font-size: 20px; flex: 0 0 auto; line-height: 1.4; }
|
|
|
|
|
|
.node-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
|
|
|
|
|
|
.node-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.node-head b { font-size: 15px; }
|
|
|
|
|
|
.node-badge {
|
|
|
|
|
|
font-size: 11px; padding: 1px 8px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--muted); white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.node-row.status-done .node-badge { background: #E6F0DC; color: #4A7226; }
|
|
|
|
|
|
.node-place, .node-time { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.node-detail { margin: 0; font-size: 14px; line-height: 1.65; }
|
2026-10-05 22:56:49 +08:00
|
|
|
|
/* v24 第 19 批 用户第 7 条:动作按钮**横着排列**、放在行程**右上角**。
|
|
|
|
|
|
「计划行程的三个按钮,修改、完成、未成行,横着排列,放在行程右上角」
|
|
|
|
|
|
「实际行程的编辑和删除按钮,也放在行程的右上角」
|
|
|
|
|
|
⚠️ 原来是 `flex-direction: column`(竖着一列、贴右下),用户要的是横排靠上。
|
|
|
|
|
|
改成 row + align-self:flex-start(贴着行的顶部对齐),窄屏再允许换行。 */
|
|
|
|
|
|
.node-ops {
|
|
|
|
|
|
flex: 0 0 auto; display: flex; flex-direction: row; flex-wrap: wrap;
|
|
|
|
|
|
gap: 6px; align-items: flex-start; justify-content: flex-end;
|
|
|
|
|
|
align-self: flex-start;
|
|
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.node-edit > summary { cursor: pointer; }
|
|
|
|
|
|
.node-add { margin-top: 14px; border-top: 1px solid var(--line-2); padding-top: 12px; }
|
|
|
|
|
|
.node-add > summary { cursor: pointer; font-size: 14px; }
|
|
|
|
|
|
.node-form { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
|
|
|
|
|
|
.nf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
|
|
|
|
|
.nf-grid .field.full { grid-column: 1 / -1; }
|
|
|
|
|
|
.nf-members { display: flex; flex-wrap: wrap; gap: 6px 16px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 附件行(旅程节点 / 资源 / 任务共用) ---- */
|
|
|
|
|
|
.attach-row { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
.attach-item {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 5px; font-size: 13px;
|
|
|
|
|
|
padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line);
|
|
|
|
|
|
background: var(--surface); color: var(--brand-ink); text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.attach-item:hover { border-color: var(--brand); text-decoration: none; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 日程(月视图,群晖 Calendar 的外观) ---- */
|
|
|
|
|
|
.cal-wrap { display: grid; grid-template-columns: 230px 1fr; gap: 18px; align-items: start; }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* 用户 2026-10-03 第 4 条:左侧「我的日历本」那一栏撤了,日历占满整宽。
|
|
|
|
|
|
⚠️ 用**单列**改写而不是删掉 .cal-wrap:`.cal-wrap` 还被别处(窄屏媒体查询)
|
|
|
|
|
|
引用着,删掉会连带把那条声明变空。单列 = 视觉上就是"充满整个宽度"。 */
|
|
|
|
|
|
.cal-wrap-full { grid-template-columns: 1fr; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.cal-side { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; }
|
|
|
|
|
|
.cal-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.cal-item { display: flex; flex-direction: column; gap: 4px; }
|
|
|
|
|
|
.cal-item > .node-badge { align-self: flex-start; }
|
|
|
|
|
|
.cal-toggle { display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; }
|
|
|
|
|
|
.cal-toggle input { accent-color: var(--brand); }
|
|
|
|
|
|
.cal-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.cal-note { font-size: 12px; color: var(--faint); line-height: 1.6; margin: 12px 0 0; }
|
|
|
|
|
|
.cal-main { min-width: 0; }
|
|
|
|
|
|
.cal-add { margin-bottom: 18px; }
|
|
|
|
|
|
.cal-grid-card { padding: 0; overflow: hidden; }
|
|
|
|
|
|
.cal-head { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--line); }
|
|
|
|
|
|
.cal-wd { padding: 8px 0; text-align: center; font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
|
|
|
|
|
|
.cal-cell {
|
|
|
|
|
|
min-height: 104px; padding: 6px 6px 8px; border-right: 1px solid var(--line-2);
|
|
|
|
|
|
border-bottom: 1px solid var(--line-2); display: flex; flex-direction: column; gap: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-cell:nth-child(7n) { border-right: 0; }
|
|
|
|
|
|
.cal-cell:nth-last-child(-n+7) { border-bottom: 0; }
|
|
|
|
|
|
.cal-cell.is-out { background: #FCFAF6; }
|
|
|
|
|
|
.cal-cell.is-out .cal-dnum { color: var(--faint); }
|
|
|
|
|
|
.cal-cell.is-today { background: #FDF6F1; }
|
|
|
|
|
|
.cal-dnum { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; padding-left: 2px; }
|
|
|
|
|
|
.cal-cell.is-today .cal-dnum {
|
|
|
|
|
|
color: #fff; background: var(--brand); border-radius: 999px;
|
|
|
|
|
|
width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-evs { display: flex; flex-direction: column; gap: 3px; }
|
|
|
|
|
|
.cal-ev {
|
|
|
|
|
|
display: block; font-size: 12px; line-height: 1.35; color: #fff;
|
|
|
|
|
|
padding: 2px 6px; border-radius: 5px; text-decoration: none;
|
|
|
|
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-ev:hover { text-decoration: none; filter: brightness(1.08); }
|
|
|
|
|
|
.cal-ev.is-allday { font-weight: 500; }
|
|
|
|
|
|
.cal-more { font-size: 11px; color: var(--faint); padding-left: 2px; }
|
|
|
|
|
|
.ev-del { margin-top: 16px; }
|
|
|
|
|
|
.cal-share-name { font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 860px) {
|
|
|
|
|
|
.cal-wrap { grid-template-columns: 1fr; }
|
|
|
|
|
|
.cal-cell { min-height: 78px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 资源 ---- */
|
|
|
|
|
|
.res-list { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.res-item { border: 1px solid var(--line-2); border-radius: var(--radius-s); background: #FDFBF7; }
|
|
|
|
|
|
.res-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 12px 14px; cursor: pointer; list-style: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-head::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.res-head:hover { background: #FAF7F1; }
|
|
|
|
|
|
.res-title { font-size: 15px; font-weight: 600; }
|
|
|
|
|
|
.res-n { font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
.res-body { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.res-inline { display: inline; margin: 0; }
|
|
|
|
|
|
.res-shares { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
|
|
|
|
.res-label { font-size: 12px; color: var(--muted); }
|
2026-10-06 20:41:04 +08:00
|
|
|
|
/* 🔴 v24 第 23 批:这条规则**必须改而不是在后面再覆盖一条**。
|
|
|
|
|
|
旧值是 `flex-direction: column` —— 那是给「展开区里四个内联表单竖着排」用的布局,
|
|
|
|
|
|
而第 23 批把四个动作搬进了弹框,`.res-ops` 变成了**标题行右端那一排按钮**。
|
|
|
|
|
|
本轮实测:只在文件末尾追加 `display/gap/margin-left`,**没写 `flex-direction`**,
|
|
|
|
|
|
于是四个按钮仍然**竖着排**,把标题行从 40px 撑到 **175px 高**
|
|
|
|
|
|
(真机几何实测 ops.top=382.9 / title.top=445.6 —— 差 63px,一眼就看出不在同一排)。
|
|
|
|
|
|
⚠️ 这也是"两处定义同一个东西"的经典代价:覆盖式修法天生容易漏子属性,
|
|
|
|
|
|
而下一次改的人只会看到其中一处。**改类名语义时,旧规则要删/改,不要叠。** */
|
|
|
|
|
|
.res-ops { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* ---- 资源列表:搜索在上(用户 2026-10-03 第 6 条)、排序与截断提示(第 10 条)---- */
|
|
|
|
|
|
.res-search-card { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.res-search { margin-bottom: 0; }
|
|
|
|
|
|
/* 搜索框给宽一点:资源标题长(「不动产证 / 学区房合同」),窄了看不全 */
|
|
|
|
|
|
.res-search .input { max-width: none; flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.res-sortbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
|
|
|
|
.res-sortbar .seg { margin: 0; }
|
|
|
|
|
|
.res-showall { margin-left: auto; }
|
|
|
|
|
|
.res-more {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* ---- 任务看板 ----
|
|
|
|
|
|
⚠️ 列数不再固定为 3:v24(用户 2026-10-03 第 7 条)起**一列 = 用户自己的一个看板**,
|
|
|
|
|
|
看板能加能删,写死 repeat(3, 1fr) 的话加第四个看板就直接掉到第二行去
|
|
|
|
|
|
(看起来像"加了个看板结果没显示")。
|
|
|
|
|
|
改成"横向自动排 + 可横向滚动":几列都放得下,列多了也不挤。 */
|
|
|
|
|
|
.kanban {
|
|
|
|
|
|
display: grid; grid-auto-flow: column;
|
|
|
|
|
|
grid-auto-columns: minmax(230px, 1fr);
|
|
|
|
|
|
gap: 14px; align-items: start; overflow-x: auto; padding-bottom: 2px;
|
|
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.kb-col { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
|
|
|
|
|
|
.kb-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; padding: 12px 16px;
|
|
|
|
|
|
border-bottom: 1px solid var(--line-2); font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.kb-head .kb-n { margin-left: auto; font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
.kb-body { padding: 12px; display: flex; flex-direction: column; gap: 10px; min-height: 90px; }
|
|
|
|
|
|
.kb-body.is-over { background: #FDF6F1; outline: 2px dashed var(--brand-2); outline-offset: -4px; }
|
|
|
|
|
|
.kb-card {
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s); background: #FDFBF7;
|
|
|
|
|
|
padding: 10px 12px; display: flex; flex-direction: column; gap: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.kb-card.is-dragging { opacity: .45; }
|
|
|
|
|
|
.kb-card.is-overdue { border-color: rgba(192, 83, 63, .4); }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* 🔴 v24 第 25 批 用户第 6 条:卡片加了「完成」复选框之后,它必须与标题**同一行**。
|
|
|
|
|
|
作者样式是 `flex-direction: column` —— 不处理的话复选框会独占一行、
|
|
|
|
|
|
标题被挤到第二行,一张卡凭空高一截(用户要的是"任务前面带一个复选框",
|
|
|
|
|
|
不是"任务上面带一个")。做法:把标题包成一行(.kb-top),
|
|
|
|
|
|
复选框 + 标题一起横排,剩下的 meta/foot 仍然竖着叠。 */
|
|
|
|
|
|
.kb-top { display: flex; align-items: flex-start; gap: 8px; }
|
|
|
|
|
|
.kb-top .kb-title { flex: 1 1 auto; min-width: 0; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.kb-title { font-size: 14px; font-weight: 500; color: var(--ink); }
|
|
|
|
|
|
.kb-title:hover { color: var(--brand); }
|
|
|
|
|
|
.kb-meta { display: flex; flex-wrap: wrap; gap: 4px 8px; font-size: 12px; color: var(--muted); }
|
2026-10-05 10:58:17 +08:00
|
|
|
|
/* ---- 状态徽标(v24 第 14 批 用户第 2 条:每张卡都有,点一下推进到下一档 ----
|
|
|
|
|
|
三档各有颜色:待办灰 / 进行中品牌色 / 已完成绿 —— 不靠位置也能一眼看出做到哪一步。
|
|
|
|
|
|
⚠️ .is-static(只读账号)长得一样但不可点:不给可点的错觉。 */
|
|
|
|
|
|
.kb-st {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 4px;
|
|
|
|
|
|
padding: 1px 8px; border-radius: 999px; border: 1px solid transparent;
|
|
|
|
|
|
font-size: 11px; line-height: 1.7; white-space: nowrap; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.kb-st.is-todo { background: var(--line-2); color: var(--muted); border-color: var(--line); }
|
|
|
|
|
|
.kb-st.is-doing { background: rgba(168, 74, 40, .12); color: var(--brand-ink); border-color: rgba(168, 74, 40, .3); }
|
|
|
|
|
|
.kb-st.is-done { background: rgba(111, 158, 92, .14); color: #4C7038; border-color: rgba(111, 158, 92, .35); }
|
|
|
|
|
|
.kb-st.is-static { cursor: default; }
|
|
|
|
|
|
.kb-st.is-doing:hover { border-color: var(--brand); }
|
|
|
|
|
|
/* .is-on = "当前就是这一档"(读书详情页的四个状态按钮用它标选中):
|
|
|
|
|
|
加一圈内描边而不是换底色 —— 底色已经表达"这一档是什么颜色",
|
|
|
|
|
|
再换一次就会分不清"选中"和"这一档"。 */
|
|
|
|
|
|
.kb-st.is-on { box-shadow: inset 0 0 0 1px currentColor; font-weight: 600; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.kb-due.is-late, .kb-late { color: var(--red); }
|
|
|
|
|
|
.kb-ico { white-space: nowrap; }
|
2026-10-07 15:31:26 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 看板色点(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; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.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); }
|
|
|
|
|
|
.kb-sub-n { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.kb-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.kb-move { margin-left: auto; display: flex; gap: 4px; }
|
|
|
|
|
|
.kb-empty { padding: 6px 2px; }
|
|
|
|
|
|
.hidden-form { display: none; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 任务详情 ---- */
|
|
|
|
|
|
.sub-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.sub-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; padding: 7px 10px;
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s); background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sub-row.is-done .sub-title { color: var(--muted); text-decoration: line-through; }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* ⚠️ `.sub-check`(旧的 ☐/☑ 字符按钮)已在 v24 第 25 批 用户第 6 条**删掉**:
|
|
|
|
|
|
子任务改用全站统一的 `.tk-check`(见上面那一段)。留一份没人用的样式
|
|
|
|
|
|
只会让下一个人以为还有第二条画法。 */
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.sub-title { flex: 1 1 auto; min-width: 0; font-size: 14px; }
|
|
|
|
|
|
.cmt-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.cmt-row { border-top: 1px solid var(--line-2); padding-top: 10px; }
|
|
|
|
|
|
.cmt-who { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.cmt-time { font-size: 11px; color: var(--faint); }
|
|
|
|
|
|
.cmt-body { font-size: 14px; line-height: 1.7; margin: 6px 0; }
|
|
|
|
|
|
.cmt-body .mention { color: var(--brand-ink); background: #F6E3D7; border-radius: 4px; padding: 0 3px; }
|
|
|
|
|
|
.cmt-form { margin-top: 6px; }
|
|
|
|
|
|
.task-danger { margin-top: 18px; display: flex; justify-content: flex-end; }
|
|
|
|
|
|
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* ---- 「危险操作区」(成员详情页的删除,用户 2026-10-03 第 2 条)----
|
|
|
|
|
|
刻意做成**页面最下方一块低调的折叠区**:破坏性操作不该一眼看到、更不该一键完成。
|
|
|
|
|
|
视觉上只用一条虚线分隔 + 灰色摘要,不抢上面正常内容的注意力。 */
|
|
|
|
|
|
.danger-zone {
|
|
|
|
|
|
margin-top: 28px; padding-top: 14px;
|
|
|
|
|
|
border-top: 1px dashed var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.danger-zone > details > summary { cursor: pointer; font-size: 13px; }
|
|
|
|
|
|
.danger-zone .del-confirm {
|
|
|
|
|
|
margin-top: 10px; padding: 12px 14px;
|
|
|
|
|
|
border: 1px solid rgba(178, 45, 45, .25); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDF6F4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 表单标签更醒目(用户 2026-10-03 第 6 条)----
|
|
|
|
|
|
「每一个输入的名字,都不够醒目,例如姓名、性别,这些字应该变大一点,加粗,
|
|
|
|
|
|
不能跟提示一样大小」—— 提醒(.tip)是 12px 的灰字,而标签原来是 13-14px,
|
|
|
|
|
|
两者太接近,扫一眼分不出"哪一行在哪"。这里把标签统一抬到 15px / 600 字重 /
|
|
|
|
|
|
深一点的墨色,与 .tip / .hint 明确拉开层级。 */
|
|
|
|
|
|
.form-grid > .field > label,
|
|
|
|
|
|
.form-grid > .field > .field-label {
|
|
|
|
|
|
font-weight: 600; font-size: 15px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 「我的资料 / 编辑成员」那张表里也有不在 form-grid 直接子级的 label(嵌套块),
|
|
|
|
|
|
一并覆盖;用 :not(.job-lb) 排除工作经历行里的那些小标签(见下)。 */
|
|
|
|
|
|
.card .field > label:not(.job-lb):not(.check-item):not(.chk-inline) {
|
|
|
|
|
|
font-weight: 600; font-size: 15px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ 但 .tip / .hint / .small 这些"说明文字"必须保持小灰字,别被上面那条带大 */
|
|
|
|
|
|
.card .field > label.tip,
|
|
|
|
|
|
.card .field > label.hint,
|
|
|
|
|
|
.card .field > label.small { font-weight: 400; font-size: 12.5px; color: var(--muted); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 头像选择器(用户第 6 条:头像放最前 + 去掉「选择文件」按钮)----
|
|
|
|
|
|
点那张(默认)头像就是选文件 —— 图本身就是按钮,不再另起一行控件。
|
|
|
|
|
|
默认头像用 .avatar-default 叠一个"+"角标,提示这里可点。 */
|
|
|
|
|
|
.avatar-field { margin-bottom: 4px; }
|
|
|
|
|
|
.avatar-picker { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
|
|
|
|
|
|
.avatar-picker #avatar-preview {
|
|
|
|
|
|
width: 96px; height: 96px; border-radius: 12px; object-fit: cover;
|
|
|
|
|
|
border: 1px solid var(--line); background: #F1E7D6; cursor: pointer;
|
|
|
|
|
|
transition: border-color .15s ease, box-shadow .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.avatar-picker #avatar-preview:hover { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(168,74,40,.12); }
|
|
|
|
|
|
.avatar-picker #avatar-preview[data-has-avatar="0"] { border-style: dashed; }
|
|
|
|
|
|
.avatar-hint { line-height: 1.7; }
|
|
|
|
|
|
|
2026-10-05 10:58:17 +08:00
|
|
|
|
/* ---- 旅程题图(v24 第 14 批 用户第 3 条):与头像同一套裁剪,比例 16:9 ----
|
|
|
|
|
|
预览块本身就是"选文件"的点击区(与头像一样,省掉一整行重复的文件控件)。
|
|
|
|
|
|
⚠️ 比例写死成 16/9 是**故意**的:CSS 不读 ImageSlot,而槽位里的比例就是 16:9,
|
|
|
|
|
|
两边各写一份会漂移 —— 部署脚本有一条断言比对 app.js 与 CSS 里的比例数字。 */
|
|
|
|
|
|
.cover-picker { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
|
|
|
|
|
|
.cover-picker #cover-preview {
|
|
|
|
|
|
width: 240px; max-width: 100%; aspect-ratio: 16 / 9;
|
|
|
|
|
|
object-fit: cover; border-radius: 12px;
|
|
|
|
|
|
border: 1px solid var(--line); background: #F1E7D6; cursor: pointer;
|
|
|
|
|
|
transition: border-color .15s ease, box-shadow .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cover-picker #cover-preview:hover { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(168,74,40,.12); }
|
|
|
|
|
|
.cover-picker #cover-preview[data-has-cover="0"] { border-style: dashed; }
|
|
|
|
|
|
.trip-people-block { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
|
|
|
|
|
|
|
2026-10-03 19:27:14 +08:00
|
|
|
|
/* ---- 工作经历(用户第 4 条:可以有多个)---- */
|
|
|
|
|
|
.job-list { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.job-row {
|
|
|
|
|
|
display: grid; gap: 8px; align-items: end;
|
|
|
|
|
|
/* 单位 / 职务 / 职称 各占一份,起止各一份窄的,最后是删除按钮 */
|
|
|
|
|
|
grid-template-columns: 1.4fr 1fr 1fr 130px 130px auto;
|
|
|
|
|
|
padding: 10px 12px; border: 1px solid var(--line-2);
|
|
|
|
|
|
border-radius: var(--radius-s); background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.job-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
|
|
|
|
|
|
.job-lb { font-size: 12px; color: var(--muted); font-weight: 500; }
|
|
|
|
|
|
.job-cell .input { padding: 7px 9px; font-size: 14px; }
|
|
|
|
|
|
.job-del { align-self: end; }
|
|
|
|
|
|
@media (max-width: 860px) {
|
|
|
|
|
|
/* 窄屏:一段经历折成两列,别硬塞六列(会挤成没法填) */
|
|
|
|
|
|
.job-row { grid-template-columns: 1fr 1fr; }
|
|
|
|
|
|
.job-row .job-cell:first-child { grid-column: 1 / -1; }
|
|
|
|
|
|
.job-del { grid-column: 1 / -1; justify-self: end; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
@media (max-width: 860px) {
|
|
|
|
|
|
.kanban { grid-template-columns: 1fr; }
|
|
|
|
|
|
.nf-grid { grid-template-columns: 1fr; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 个人设置里的「模块」两块 ---- */
|
|
|
|
|
|
.mod-order .mod-row { cursor: grab; }
|
|
|
|
|
|
.mod-order .mod-row.is-dragged { opacity: .45; cursor: grabbing; }
|
|
|
|
|
|
.mod-order .mod-row.is-drop-before { box-shadow: inset 0 3px 0 var(--brand); }
|
|
|
|
|
|
.mod-order .mod-row.is-drop-after { box-shadow: inset 0 -3px 0 var(--brand); }
|
|
|
|
|
|
.mod-pick { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
|
|
|
|
|
|
.mod-pick input { accent-color: var(--brand); }
|
|
|
|
|
|
.mod-swatches { display: flex; flex-wrap: wrap; gap: 8px 18px; }
|
|
|
|
|
|
.mod-swatch { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.mod-colors { display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.mod-color-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
|
|
|
|
.mod-color-name { flex: 0 0 76px; font-size: 14px; }
|
|
|
|
|
|
.mod-preset { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
|
|
|
|
.mod-preset .preset-color { cursor: pointer; }
|
|
|
|
|
|
|
2026-10-03 15:01:38 +08:00
|
|
|
|
/* ---- 纪念日设置下拉(v24 用户 2026-10-03 第 9 条)---- */
|
|
|
|
|
|
.ann-set .menu-list { min-width: 260px; max-width: min(320px, 92vw); }
|
|
|
|
|
|
.ann-set-list { padding: 10px; gap: 0; }
|
|
|
|
|
|
.ann-kind-list { list-style: none; margin: 0; padding: 0; max-height: 46vh; overflow-y: auto; }
|
|
|
|
|
|
.ann-kind-list li {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 5px 2px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.ann-kind-list li:last-child { border-bottom: 0; }
|
|
|
|
|
|
.ann-kind-name { font-size: 13.5px; font-weight: 500; }
|
|
|
|
|
|
.ann-kind-list li .small { margin-left: auto; }
|
|
|
|
|
|
|
2026-10-02 09:28:07 +08:00
|
|
|
|
/* ---- 首页 dashboard ---- */
|
|
|
|
|
|
.hero-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
|
|
|
|
|
.dash-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
|
|
|
|
.dash-row {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 10px; padding: 8px 2px;
|
|
|
|
|
|
border-top: 1px solid var(--line-2); flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dash-row:first-child { border-top: 0; }
|
|
|
|
|
|
.dash-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
|
|
|
|
|
|
.dash-when { flex: 0 0 96px; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.dash-what { flex: 1 1 auto; min-width: 0; font-size: 14px; }
|
|
|
|
|
|
.dash-tag { flex: 0 0 auto; font-size: 11px; color: var(--faint); }
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- v24 第 11 批 #4:影院下拉(带色点)+ 新建影院弹框 ----
|
|
|
|
|
|
原生 <option> 画不了色块,所以自己做一个"按钮 + 弹出列表":
|
|
|
|
|
|
值仍写进隐藏的 input[name=cinema_id],服务端与既有测试都不用改。 */
|
|
|
|
|
|
.cinema-select-row { display: flex; align-items: flex-start; gap: 8px; }
|
|
|
|
|
|
.cs { position: relative; flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.cs-btn {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; width: 100%;
|
|
|
|
|
|
padding: 10px 12px; font: inherit; font-size: 14px; color: var(--ink);
|
|
|
|
|
|
background: #fff; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
cursor: pointer; text-align: left;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cs-btn:hover { border-color: var(--brand-2); }
|
|
|
|
|
|
.cs-btn:focus { outline: none; border-color: var(--brand); }
|
|
|
|
|
|
.cs-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.cs-caret { flex: 0 0 auto; color: var(--muted); font-size: 11px; }
|
|
|
|
|
|
.cs-dot {
|
|
|
|
|
|
flex: 0 0 auto; width: 12px; height: 12px; border-radius: 3px;
|
|
|
|
|
|
background: var(--line-2); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cs-dot.is-none { background: transparent; box-shadow: inset 0 0 0 1px var(--line); }
|
|
|
|
|
|
.cs-menu {
|
|
|
|
|
|
position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 10px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
padding: 4px; max-height: 280px; overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cs-menu[hidden] { display: none; }
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* 🔴 v39(用户 2026-10-10):「影院那个地方应该有一个搜索的功能,下拉的地方上面
|
|
|
|
|
|
有一个搜索筛选的功能。」
|
|
|
|
|
|
⇒ 弹出列表顶部一条搜索框。⚠️ 它要**吸顶**(列表长时往下滚,它跟着走)——
|
|
|
|
|
|
不然滚两下搜索框就没了,"搜索筛选"等于白加。 */
|
|
|
|
|
|
.cs-search {
|
|
|
|
|
|
position: sticky; top: -4px; z-index: 2;
|
|
|
|
|
|
margin: -4px -4px 4px; padding: 6px 6px 6px;
|
|
|
|
|
|
background: var(--surface); border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cs-search-input {
|
|
|
|
|
|
width: 100%; box-sizing: border-box;
|
|
|
|
|
|
padding: 7px 10px; font: inherit; font-size: 13px; color: var(--ink);
|
|
|
|
|
|
background: var(--paper, #FDFBF7); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 7px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cs-search-input::placeholder { color: var(--muted); }
|
|
|
|
|
|
.cs-search-input:focus { outline: none; border-color: var(--brand); }
|
|
|
|
|
|
/* 没有匹配项时的提示(没搜过 / 有结果时都 hidden,不占高度) */
|
|
|
|
|
|
.cs-empty { padding: 10px 12px; font-size: 13px; color: var(--muted); text-align: center; }
|
|
|
|
|
|
.cs-empty[hidden] { display: none; }
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.cs-item {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; width: 100%;
|
|
|
|
|
|
padding: 8px 10px; border: 0; border-radius: 7px; background: transparent;
|
|
|
|
|
|
font: inherit; font-size: 13.5px; color: var(--ink); cursor: pointer; text-align: left;
|
|
|
|
|
|
}
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* ⚠️ 过滤用的 `hidden` 必须写出来:`.cs-item` 自己声明了 `display:flex`,
|
|
|
|
|
|
它会**盖过**浏览器默认的 `[hidden]{display:none}` ——
|
|
|
|
|
|
这正是第 11 批"选人过滤一直是坏的"的同一个坑,别再踩第二次。 */
|
|
|
|
|
|
.cs-item[hidden] { display: none; }
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.cs-item:hover, .cs-item:focus { background: var(--line-2); outline: none; }
|
2026-10-12 15:31:03 +08:00
|
|
|
|
.cs-item.is-disabled { opacity: .5; cursor: not-allowed; }
|
|
|
|
|
|
.cs-item.is-disabled:hover { background: transparent; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 🔴 v44:日程「日历本」下拉 ----
|
|
|
|
|
|
用户 2026-10-12 第 1 条:「把颜色放在下拉框里面,就跟电影的影院选择一样,
|
|
|
|
|
|
让日历本这三个字和下拉框在一条线上。」
|
|
|
|
|
|
⇒ 复用观影那套 `.cs`(按钮 + 色点 + 弹出列表 + 搜索),只补两点:
|
|
|
|
|
|
① 这个下拉在 `.mv-row` 里,宽度由 `> *:not(.mv-lb)` 那条 `flex:1` 接管,够用;
|
|
|
|
|
|
② **无 JS 兜底**:那个原生 `<select id="ce-cal">` 只做视觉收起 ——
|
|
|
|
|
|
用 `position:absolute; width:1px`(**不是 display:none**,保留可聚焦、可提交),
|
|
|
|
|
|
与 `_datetime.php` 的"隐藏 date 当值载体"同一套思路。
|
|
|
|
|
|
⚠️ 断言里按 `#ce-cal` 取 option / 值的写法必须继续成立 —— 它在 DOM 里。 */
|
|
|
|
|
|
.cal-book-cs { width: 100%; }
|
|
|
|
|
|
.cal-book-native {
|
|
|
|
|
|
position: absolute; width: 1px; height: 1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
|
|
|
|
|
|
border: 0; padding: 0; margin: -1px;
|
|
|
|
|
|
}
|
2026-10-04 17:42:21 +08:00
|
|
|
|
|
|
|
|
|
|
/* 新建影院:居中弹框(与名册的动作弹框同一形态,只是更宽) */
|
|
|
|
|
|
.cn-modal {
|
2026-10-11 10:12:11 +08:00
|
|
|
|
/* 🔴🔴 v41(用户 2026-10-10):「观影模块,第一场电影,新建影院这个弹窗不显示,
|
|
|
|
|
|
被记一场电影这个弹窗盖住了。」
|
|
|
|
|
|
真根因:`.cn-modal` 是 **70**,而「记一场电影」用的 `.cal-modal` 是 **200** ——
|
|
|
|
|
|
影院弹框是**从观影弹框里**打开的子层,层级却更低 ⇒ 被整块盖住、看不见也点不到。
|
|
|
|
|
|
⇒ 提到 260:必须**高于 .cal-modal(200)**,也高于 antd 的下拉面板
|
|
|
|
|
|
(`.ant-picker-dropdown` 走 popper,默认 1050 之外的那一层我们没碰;
|
|
|
|
|
|
这里只需保证"压过所有自建弹框"即可)。 */
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 260;
|
2026-10-04 17:42:21 +08:00
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-modal[hidden] { display: none; }
|
|
|
|
|
|
.cn-mask { position: absolute; inset: 0; background: rgba(47, 36, 30, .34); }
|
|
|
|
|
|
.cn-panel {
|
|
|
|
|
|
position: relative; z-index: 1;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 14px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
width: min(420px, 92vw); max-height: min(84vh, 620px);
|
|
|
|
|
|
display: flex; flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 14px 10px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-head b { font-size: 14.5px; }
|
|
|
|
|
|
.cn-x {
|
|
|
|
|
|
margin-left: auto; border: 0; background: transparent; cursor: pointer;
|
|
|
|
|
|
font-size: 15px; color: var(--muted); padding: 4px 6px; border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-x:hover { background: var(--line-2); color: var(--ink); }
|
|
|
|
|
|
.cn-body { padding: 12px 14px; overflow-y: auto; }
|
|
|
|
|
|
.cn-body .field { margin-bottom: 12px; }
|
|
|
|
|
|
.cn-body .field > label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px; }
|
|
|
|
|
|
.cn-foot {
|
|
|
|
|
|
display: flex; gap: 8px; justify-content: flex-end;
|
|
|
|
|
|
padding: 10px 14px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-presets { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; }
|
|
|
|
|
|
.cn-preset {
|
|
|
|
|
|
width: 20px; height: 20px; border-radius: 5px; border: 1px solid rgba(0, 0, 0, .12);
|
|
|
|
|
|
cursor: pointer; padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-preset:hover { transform: scale(1.08); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v24 第 11 批 #1:日历本改「实心色块」----
|
|
|
|
|
|
原来 .dash-tag 是 --faint 的 11px 灰字,压在宣纸底上几乎看不见(用户原话"看不清")。
|
|
|
|
|
|
现在:底色 = 该日历本的颜色(由模板内联),文字白色 —— 与左侧那个小圆点同一个颜色,
|
|
|
|
|
|
扫一眼就知道"这条是哪本日历的"。
|
|
|
|
|
|
⚠️ 颜色是用户自选的,浅色(如 #97A630)上白字会发虚 → 加一点文字阴影保底,
|
|
|
|
|
|
比"强制加深颜色"好:本子的颜色是用户定的,不该被我们改。 */
|
|
|
|
|
|
.dash-cal {
|
|
|
|
|
|
flex: 0 0 auto; align-self: center;
|
|
|
|
|
|
padding: 2px 9px; border-radius: 999px;
|
|
|
|
|
|
color: #fff; font-size: 11.5px; font-weight: 500; line-height: 1.7;
|
|
|
|
|
|
white-space: nowrap; max-width: 40%;
|
|
|
|
|
|
overflow: hidden; text-overflow: ellipsis;
|
|
|
|
|
|
text-shadow: 0 1px 1px rgba(0, 0, 0, .22);
|
|
|
|
|
|
}
|
2026-10-02 09:28:07 +08:00
|
|
|
|
@media (max-width: 620px) {
|
|
|
|
|
|
.dash-when { flex: 0 0 auto; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v14:导航条从 4 个模块变成最多 8 个,窄屏必须能横向滑动 ----
|
|
|
|
|
|
⚠️ 这是本轮**实测出来的回归**:模块从 4 个加到 8 个之后,
|
|
|
|
|
|
375px 视口下 scrollWidth=472 > clientWidth=375,**整页横向溢出**
|
|
|
|
|
|
(顶栏把 body 撑宽了)。以前 4 个模块刚好塞得下,所以从没有人给 .nav 写过窄屏规则。
|
|
|
|
|
|
修法用「导航自己横向滚动」而不是「换行」:
|
|
|
|
|
|
换行会把顶栏从 60px 撑成两行,sticky 顶栏一高一矮很难看,而且滚动时页面会跳。
|
|
|
|
|
|
⚠️ 断点必须是 **720px**(站点既有的"窄屏留白 16px"断点),不能用 860:
|
|
|
|
|
|
746px 宽时若只改顶栏留白,就会出现「顶栏 x=16、正文 x=24」错位 8px
|
|
|
|
|
|
(几何检查会直接报出来)。窄屏规则只在站点真正切到小留白的那一档生效。 */
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* ==================== 月 / 周 / 天 三选一的分段控件 ==================== */
|
|
|
|
|
|
/* 三个按钮连成一条(相邻边各留一半边框,拼起来才是一整条外框),
|
|
|
|
|
|
当前那个用模块主题色填底 —— 一眼看出自己在哪种看法上。 */
|
|
|
|
|
|
.seg { display: inline-flex; }
|
|
|
|
|
|
.seg-btn {
|
|
|
|
|
|
padding: 6px 14px; font-size: 13px; line-height: 1;
|
|
|
|
|
|
color: var(--muted); background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line); text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.seg-btn + .seg-btn { border-left: 0; }
|
|
|
|
|
|
.seg-btn:first-child { border-radius: var(--radius-s) 0 0 var(--radius-s); }
|
|
|
|
|
|
.seg-btn:last-child { border-radius: 0 var(--radius-s) var(--radius-s) 0; }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
.seg-btn:hover { text-decoration: none; } /* 原来那层 #FDFBF7 在米色底上像脏了一块 */
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.seg-btn.is-on {
|
|
|
|
|
|
background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-04 17:42:21 +08:00
|
|
|
|
/* ---- 日程页头的「跳到某一天」(v24 第 11 批 #6 重做)----
|
|
|
|
|
|
用户要求:「跳转日期那个地方,不要那么长,只需要和设置一样,一个按钮即可」,
|
|
|
|
|
|
且日期选择要用 Semi(与全站统一)。
|
|
|
|
|
|
所以现在是**一个方图标按钮**(与 ☰ 的 .btn-icon 同规格):
|
|
|
|
|
|
点开弹一个只含 Semi 日期选择器的轻浮层,选中即跳。 */
|
2026-10-04 10:46:50 +08:00
|
|
|
|
.cal-jump { display: inline-flex; margin: 0; }
|
2026-10-04 17:42:21 +08:00
|
|
|
|
.cal-jump-btn { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
|
2026-10-04 19:43:00 +08:00
|
|
|
|
/* ---- v24 第 12 批 #3:跳转日期改成**按钮下方的下拉日历** ----
|
|
|
|
|
|
用户原话:「选择这个日期,不用弹窗,直接把日历选择,弹出在这个按钮下面就可以了。」
|
|
|
|
|
|
所以把原来"全屏遮罩 + 居中弹窗"(.cal-jump-host/.cal-jump-pop)换成
|
|
|
|
|
|
贴着按钮下方展开的下拉面板(.cal-jump-drop)。 */
|
|
|
|
|
|
.cal-jump { position: relative; }
|
|
|
|
|
|
.cal-jump-drop {
|
|
|
|
|
|
position: absolute; z-index: 70;
|
|
|
|
|
|
top: calc(100% + 8px); left: auto; right: 0; /* 贴右:与按钮同一列,不会跑出屏外 */
|
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
|
border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
box-shadow: var(--shadow-l);
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
/* 下拉里放的是 Semi 的**内联**日历面板,去掉它自己的浮层阴影/描边避免双层框 */
|
2026-10-04 10:46:50 +08:00
|
|
|
|
}
|
2026-10-04 19:43:00 +08:00
|
|
|
|
.cal-jump-drop[hidden] { display: none; }
|
2026-10-05 10:58:17 +08:00
|
|
|
|
/* ---- v24 第 14 批 #1:下拉里是**自绘**的日历(不再挂 Semi 的浮层面板)----
|
|
|
|
|
|
「上一月/上一年」只重画面板、绝不提交(这正是不引第三方控件的原因:
|
|
|
|
|
|
它把"翻月"与"选中"混在同一个 onChange 里,于是翻月也会跳走)。 */
|
|
|
|
|
|
.cjd-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 4px; margin-bottom: 6px;
|
2026-10-04 10:46:50 +08:00
|
|
|
|
}
|
2026-10-05 10:58:17 +08:00
|
|
|
|
.cjd-title { flex: 1; text-align: center; font-weight: 600; font-size: 14px; }
|
|
|
|
|
|
.cjd-nav {
|
|
|
|
|
|
width: 28px; height: 28px; flex: 0 0 auto;
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 8px;
|
|
|
|
|
|
background: var(--surface); color: var(--ink); font-size: 14px; line-height: 1;
|
|
|
|
|
|
cursor: pointer;
|
2026-10-04 10:46:50 +08:00
|
|
|
|
}
|
2026-10-05 10:58:17 +08:00
|
|
|
|
.cjd-nav:hover { background: var(--line); }
|
|
|
|
|
|
.cjd-grid {
|
|
|
|
|
|
display: grid; grid-template-columns: repeat(7, 32px); gap: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cjd-wd {
|
|
|
|
|
|
text-align: center; font-size: 11px; color: var(--muted); padding: 2px 0 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cjd-day {
|
|
|
|
|
|
width: 32px; height: 30px; padding: 0;
|
|
|
|
|
|
border: 0; border-radius: 8px; background: transparent; color: var(--ink);
|
|
|
|
|
|
font-size: 13px; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cjd-day:hover { background: var(--line); }
|
|
|
|
|
|
.cjd-day.is-out { color: var(--muted); opacity: .55; }
|
|
|
|
|
|
.cjd-day.is-today { font-weight: 700; box-shadow: inset 0 0 0 1px var(--line); }
|
|
|
|
|
|
.cjd-day.is-on { background: var(--brand); color: #fff; }
|
|
|
|
|
|
.cjd-foot {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px;
|
|
|
|
|
|
margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cjd-foot .cjd-sel { flex: 1; }
|
2026-10-04 10:46:50 +08:00
|
|
|
|
|
2026-10-03 08:18:05 +08:00
|
|
|
|
/* ==================== 周 / 天:按小时铺的时间网格 ==================== */
|
|
|
|
|
|
/* 结构:左边一条"小时刻度"沟槽(tg-gutter),右边 N 个日期列(tg-col)。
|
|
|
|
|
|
列高固定 = 24 小时 × 每小时 44px,日程块按 top/height 百分比**绝对定位**,
|
|
|
|
|
|
所以"09:15 的 20 分钟"就是一小条,不会跟 9 点整的会挤成一样高。 */
|
|
|
|
|
|
.cal-tg-card { padding: 0; overflow: auto; }
|
|
|
|
|
|
.tg-head { display: flex; position: sticky; top: 0; z-index: 3;
|
|
|
|
|
|
background: var(--surface); border-bottom: 1px solid var(--line); }
|
|
|
|
|
|
.tg-gutter {
|
|
|
|
|
|
flex: 0 0 56px; width: 56px; border-right: 1px solid var(--line);
|
|
|
|
|
|
display: flex; flex-direction: column; align-items: flex-end;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-dayname {
|
|
|
|
|
|
flex: 1 1 0; min-width: 0; padding: 8px 6px; text-align: center;
|
|
|
|
|
|
border-left: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-dayname:first-of-type { border-left: 0; }
|
|
|
|
|
|
.tg-dayname.is-today { background: #FDF6F1; }
|
|
|
|
|
|
.tg-wd { display: block; font-size: 11px; color: var(--faint); }
|
|
|
|
|
|
.tg-dd { display: block; font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.tg-dayname.is-today .tg-dd { color: var(--brand); }
|
|
|
|
|
|
|
|
|
|
|
|
.tg-allday { display: flex; border-bottom: 1px solid var(--line); background: #FDFBF7; }
|
|
|
|
|
|
.tg-allday .tg-gutter { padding: 6px 6px; }
|
|
|
|
|
|
.tg-tag { font-size: 11px; color: var(--faint); }
|
|
|
|
|
|
.tg-adcell {
|
|
|
|
|
|
flex: 1 1 0; min-width: 0; padding: 4px 4px 6px; border-left: 1px solid var(--line-2);
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-adcell:first-of-type { border-left: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
.tg-body { display: flex; position: relative; }
|
|
|
|
|
|
.tg-hours { padding: 0; }
|
|
|
|
|
|
.tg-hr {
|
|
|
|
|
|
height: 44px; padding-right: 6px; padding-top: 2px;
|
|
|
|
|
|
font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums;
|
|
|
|
|
|
border-top: 1px solid var(--line-2); box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-hr:first-child { border-top: 0; }
|
|
|
|
|
|
.tg-col {
|
|
|
|
|
|
flex: 1 1 0; min-width: 0; position: relative;
|
|
|
|
|
|
height: 1056px; /* 24 × 44px,与 .tg-hr 的高度必须一致 */
|
|
|
|
|
|
border-left: 1px solid var(--line-2); box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-col:first-of-type { border-left: 0; }
|
|
|
|
|
|
.tg-col.is-today { background: #FDF6F1; }
|
|
|
|
|
|
.tg-line { display: block; height: 44px; border-top: 1px solid var(--line-2); box-sizing: border-box; }
|
|
|
|
|
|
.tg-line:first-child { border-top: 0; }
|
2026-10-08 17:41:30 +08:00
|
|
|
|
/* ⚠️ v30 第 4 条:`left` 与 `width` 现在由**内联样式**给出(冲突分列后每条不同),
|
|
|
|
|
|
所以这里**不能**再写 `left/right` —— 绝对定位下 left+right+width 三者同时存在是
|
|
|
|
|
|
"过约束",浏览器会丢掉 `right`(看着像是碰巧对)。留一个兜底 left:2px,
|
|
|
|
|
|
万一某条没带内联 left(老数据/兜底路径)也不至于跑到列外去。 */
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.tg-block {
|
2026-10-08 17:41:30 +08:00
|
|
|
|
position: absolute; left: 2px;
|
2026-10-03 08:18:05 +08:00
|
|
|
|
display: block; overflow: hidden; padding: 2px 5px;
|
|
|
|
|
|
border-radius: 4px; color: #fff; font-size: 11px; line-height: 1.35;
|
|
|
|
|
|
text-decoration: none; box-sizing: border-box;
|
|
|
|
|
|
border: 1px solid rgba(255,255,255,.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
.tg-block:hover { text-decoration: none; filter: brightness(1.1); z-index: 2; }
|
|
|
|
|
|
.tg-block b { font-weight: 600; margin-right: 3px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 天视图只有一列,把列拉宽好读;周视图 7 列时列宽由 flex 平分 */
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
/* 窄屏留不住 56px 的刻度沟槽 + 7 列,改成整体可横向滚动(.cal-tg-card 已 overflow:auto),
|
|
|
|
|
|
给每列一个最小宽度,滚动着看而不是把字挤成一团。 */
|
|
|
|
|
|
.tg-col, .tg-dayname, .tg-adcell { min-width: 92px; }
|
|
|
|
|
|
.cal-tg-card { -webkit-overflow-scrolling: touch; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ⚠️ v24:导航从 7 个模块加到 9 个(纪念日 / 财务)之后,**746px 就放不下了**,
|
|
|
|
|
|
而"放不下"的表现不是换行、是顶栏被撑宽 20.5px:
|
|
|
|
|
|
`.nav` 内部产生横向滚动条(哪怕已用 scrollbar-width:none 隐藏),
|
|
|
|
|
|
`.topbar-inner` 的可用宽度就比 `.container` 少一档,
|
|
|
|
|
|
几何检查直接报「顶栏右 742.5 / 正文右 722.0」。
|
|
|
|
|
|
所以**不能**只在 720px 断点里给 .nav 加快收缩 ——
|
|
|
|
|
|
那样 721~1080 这一段区间没人管,正是出问题的地方。
|
|
|
|
|
|
正确做法:把「导航可收缩 + 横向滚动」提到**无媒体查询的基态**,
|
|
|
|
|
|
只在真的窄到需要缩留白时才改 padding(下面 720px 那段)。 */
|
|
|
|
|
|
.nav {
|
|
|
|
|
|
/* flex:1 1 auto + min-width:0 才真的会"被压缩";只写 min-width 时它仍是 auto 宽度,
|
|
|
|
|
|
内容一多就把顶栏撑出去(这就是 746px 那 20.5px 的来源)。 */
|
|
|
|
|
|
flex: 1 1 auto; min-width: 0;
|
|
|
|
|
|
overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav::-webkit-scrollbar { display: none; }
|
|
|
|
|
|
.nav a { flex: 0 0 auto; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.topbar-inner { gap: 12px; padding: 0 16px; }
|
|
|
|
|
|
/* min-width:0 是关键:flex 子项默认 min-width:auto,会拒绝被压缩,
|
|
|
|
|
|
于是内部再 overflow-x 也撑不出滚动条,而是把父级一起顶宽。 */
|
|
|
|
|
|
.nav {
|
|
|
|
|
|
flex: 1 1 auto;
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
.nav a { padding: 6px 10px; }
|
2026-10-02 09:28:07 +08:00
|
|
|
|
.topbar-right { margin-left: 0; gap: 6px; }
|
|
|
|
|
|
/* 窄屏把「家书」两个字收起来,只留图标 —— 名字占的宽度正好够多放两个模块 */
|
|
|
|
|
|
.brand span { display: none; }
|
|
|
|
|
|
.who .who-name { display: none; }
|
|
|
|
|
|
}
|
2026-10-04 08:56:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 地址五级(国家 / 省 / 市 / 区 / 详细地址,用户 2026-10-04 第 4 条)----
|
|
|
|
|
|
一行排不下五个控件,用**自动换行的网格**:宽屏上「国家+省+市」一行、
|
|
|
|
|
|
「区+详细」一行;窄屏自动每组一个。每个控件头上一行小标签(addr-k),
|
|
|
|
|
|
比把「省 / 市」两个字塞进 placeholder 里好认 —— placeholder 一填字就没了。 */
|
|
|
|
|
|
.addr-grid {
|
|
|
|
|
|
display: grid; gap: 8px 10px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
|
|
|
|
margin-top: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.addr-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
|
|
|
|
|
|
.addr-cell-wide { grid-column: span 2; }
|
|
|
|
|
|
.addr-cell .addr-k { font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
.addr-cell .input,
|
|
|
|
|
|
.addr-cell .select { width: 100%; }
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.addr-cell-wide { grid-column: span 1; }
|
|
|
|
|
|
}
|
2026-10-04 20:57:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ==================== 旅程:行程状态机(v24 第 13 批)====================
|
|
|
|
|
|
分三组:计划 / 实际 / 未成行。未成行用灰调(它"不算数"但要看得到)。 */
|
|
|
|
|
|
.trip-stage-card { margin-bottom: 18px; }
|
|
|
|
|
|
.stage-hint { margin: -6px 0 12px; font-size: 12.5px; color: var(--muted); }
|
|
|
|
|
|
.stage-skipped { opacity: .82; }
|
|
|
|
|
|
.stage-skipped .node-row { background: var(--line-2); }
|
|
|
|
|
|
|
|
|
|
|
|
.node-badge.nb-plan { background: #EDE7DC; color: #6B5B45; }
|
|
|
|
|
|
.node-badge.nb-actual { background: #DCEFE2; color: #2C6B45; }
|
|
|
|
|
|
.node-badge.nb-skipped { background: #EFEDEA; color: #6B6560; }
|
|
|
|
|
|
.rev-badge {
|
|
|
|
|
|
display: inline-block; padding: 1px 7px; border-radius: 999px;
|
|
|
|
|
|
background: #F1E6F5; color: #6B3F7A; font-size: 11.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.actual-tag {
|
|
|
|
|
|
display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
|
|
|
|
|
|
background: #DCEFE2; color: #2C6B45; font-size: 11px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 修正面板(在行程行里就地展开) */
|
|
|
|
|
|
.rev-open > summary { cursor: pointer; list-style: none; }
|
|
|
|
|
|
.rev-open > summary::-webkit-details-marker { display: none; }
|
|
|
|
|
|
.rev-panel {
|
|
|
|
|
|
margin-top: 10px; padding: 12px 14px;
|
|
|
|
|
|
background: var(--surface-2, #FAF7F1);
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rev-tip { margin: 0 0 10px; font-size: 12.5px; line-height: 1.7; color: var(--muted); }
|
2026-10-10 00:26:42 +08:00
|
|
|
|
|
|
|
|
|
|
/* 🔴🔴 v37:修正面板必须**浮**在按钮列之外,否则它只有 ~22px 宽、完全没法填。
|
|
|
|
|
|
真机实测(1400px 视口、品心 1080px):
|
|
|
|
|
|
.dt-range 宽 **22px**、`.nf-grid` 宽 **22px** —— 整张修正表单被压成一条线。
|
|
|
|
|
|
根因:`.node-ops` 是"一排小按钮"的容器
|
|
|
|
|
|
`flex: 0 0 auto; justify-content: flex-end;`(见上面),
|
|
|
|
|
|
而「修正」是 `<details class="rev-open">`:**展开的内容也长在这个按钮列里**
|
|
|
|
|
|
⇒ 列宽只有"修正"两个字那么宽(22px),里面的表单跟着一起被压扁。
|
|
|
|
|
|
⚠️ 这不只是"不好看":日期控件在 22px 里根本点不到(用户报的就是这个)。
|
|
|
|
|
|
修法:面板 `position: absolute` 脱离按钮列的宽度约束,浮到卡片上。
|
|
|
|
|
|
· 宽度取 `min(720px, container 宽)` —— 720 刚好摆得下"两端各 304"(608+间距)。
|
|
|
|
|
|
· `right: 0` 让它从按钮列右缘向左展开,不会超出卡片右边。
|
|
|
|
|
|
· `z-index: 30` 盖在后面的行上面(它是临时展开的面板,本来就该在最上层)。
|
|
|
|
|
|
⚠️ 不动 templates/trips/show.php 的 DOM:
|
|
|
|
|
|
`.node-list`/`.node-row` 的 flex 结构一动就会牵动"节点列表"的排版
|
|
|
|
|
|
(那是清单页最核心的视觉),而这里只需要把它**浮出来**,纯 CSS 就够。 */
|
|
|
|
|
|
.rev-open { position: relative; }
|
|
|
|
|
|
.rev-panel {
|
|
|
|
|
|
position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
|
|
|
|
|
|
width: min(720px, calc(100vw - 48px));
|
|
|
|
|
|
max-height: min(76vh, 720px); overflow-y: auto;
|
|
|
|
|
|
box-shadow: var(--shadow-l, 0 12px 32px rgba(0, 0, 0, .16));
|
|
|
|
|
|
}
|
2026-10-04 20:57:40 +08:00
|
|
|
|
.rev-form .btn-row { margin-top: 10px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 修正历史对比表 */
|
|
|
|
|
|
.rev-hist { margin-top: 8px; }
|
|
|
|
|
|
.rev-hist > summary { cursor: pointer; font-size: 12.5px; }
|
|
|
|
|
|
.rev-table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 12.5px; }
|
|
|
|
|
|
.rev-table th, .rev-table td {
|
|
|
|
|
|
padding: 5px 8px; border-bottom: 1px solid var(--line-2); text-align: left;
|
|
|
|
|
|
}
|
|
|
|
|
|
.rev-table th { color: var(--muted); font-weight: 500; }
|
|
|
|
|
|
.rev-table tr:first-child td { color: var(--ink); } /* 原计划一行稍醒目 */
|
|
|
|
|
|
|
|
|
|
|
|
/* 行程表单里的"当前状态"只读展示 */
|
|
|
|
|
|
.node-stage-ro {
|
|
|
|
|
|
padding: 9px 11px; border: 1px dashed var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--line-2); font-size: 13px;
|
|
|
|
|
|
}
|
2026-10-05 10:58:17 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 14 批:读书模块(用户第 5 条)
|
|
|
|
|
|
卡片骨架 / 统计图表一律复用现成的(.card.card-pad / .stats-grid /
|
|
|
|
|
|
.stat-card / .chart-card / .bar-chart / .vgrid),这里只写读书**特有**的部件。
|
|
|
|
|
|
图表仍然是纯 CSS:不引图表库,服务端画出来、没 JS 也看得见。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 书架:状态筛选条 ---- */
|
|
|
|
|
|
.book-filter { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
|
|
|
|
|
|
.bf-btn {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 5px;
|
|
|
|
|
|
padding: 5px 14px; border-radius: 999px;
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--surface);
|
|
|
|
|
|
font-size: 13px; color: var(--ink); text-decoration: none;
|
|
|
|
|
|
transition: border-color .15s ease, background .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bf-btn:hover { border-color: var(--brand); text-decoration: none; }
|
|
|
|
|
|
.bf-btn.is-on { background: var(--brand); border-color: var(--brand); color: #fff; }
|
|
|
|
|
|
.bf-n { font-size: 11px; opacity: .72; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 书架:卡片网格 ----
|
|
|
|
|
|
封面按 2:3(书的形状),宽度自适应;窄屏自动减列。 */
|
|
|
|
|
|
.book-grid {
|
|
|
|
|
|
display: grid; gap: 14px;
|
|
|
|
|
|
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
.book-card {
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 8px;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 12px; box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ 封面是 <a>(整块可点):居中靠 flex,图自己铺满 —— 只写一次 display,
|
|
|
|
|
|
写两遍后者会把前者悄悄改掉(这类"重复声明"最容易在改版时留成陷阱)。 */
|
|
|
|
|
|
.book-cover {
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
aspect-ratio: 2 / 3; border-radius: var(--radius-s);
|
|
|
|
|
|
overflow: hidden; background: #F1E7D6;
|
|
|
|
|
|
}
|
|
|
|
|
|
.book-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
|
|
|
|
.book-cover-empty { font-size: 32px; opacity: .5; }
|
|
|
|
|
|
.book-body { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
|
|
|
|
|
|
.book-title {
|
|
|
|
|
|
font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.45;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.book-title:hover { color: var(--brand); }
|
|
|
|
|
|
.book-author { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.book-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
|
|
|
|
|
|
.book-rate { font-size: 11px; color: var(--brand-ink); }
|
|
|
|
|
|
.book-note-n { font-size: 11px; color: var(--muted); }
|
|
|
|
|
|
/* 读到第几章的细进度条 */
|
|
|
|
|
|
.bk-bar {
|
|
|
|
|
|
height: 4px; border-radius: 999px; background: var(--line-2); overflow: hidden; margin: 2px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bk-bar i { display: block; height: 100%; background: var(--brand); }
|
|
|
|
|
|
.book-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: auto; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 一本书 ---- */
|
|
|
|
|
|
.book-hero { display: flex; gap: 20px; flex-wrap: wrap; }
|
|
|
|
|
|
.book-hero-cover {
|
|
|
|
|
|
width: 150px; max-width: 46%; flex: 0 0 auto;
|
|
|
|
|
|
aspect-ratio: 2 / 3; border-radius: var(--radius-s);
|
|
|
|
|
|
overflow: hidden; background: #F1E7D6;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.book-hero-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
|
|
|
|
.book-hero-body { flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.book-sub { margin: 0; font-size: 14px; color: var(--muted); }
|
|
|
|
|
|
.book-states { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
|
|
|
|
.book-sum { margin-top: 4px; }
|
|
|
|
|
|
.book-toc-box { margin-top: 4px; }
|
|
|
|
|
|
.book-toc { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 3px; }
|
|
|
|
|
|
.book-toc li { font-size: 13.5px; display: flex; align-items: baseline; gap: 8px; }
|
|
|
|
|
|
.book-toc li.is-cur > a { color: var(--brand); font-weight: 600; }
|
|
|
|
|
|
.bk-file-now { margin: 0 0 6px; font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 笔记 ---- */
|
|
|
|
|
|
.book-note-form { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
|
|
|
|
|
|
.bn-row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.bn-row .select { flex: 0 0 auto; width: auto; min-width: 96px; }
|
|
|
|
|
|
.bn-row .input { flex: 1 1 160px; min-width: 0; }
|
|
|
|
|
|
.book-notes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.book-note {
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
padding: 9px 12px; background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.book-note.is-quote { border-left: 3px solid var(--brand-2); }
|
|
|
|
|
|
.book-note.is-review { border-left: 3px solid var(--green); }
|
|
|
|
|
|
.bn-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 5px; }
|
|
|
|
|
|
.bn-kind {
|
|
|
|
|
|
font-size: 11px; padding: 1px 7px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--brand-ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.bn-ch, .bn-src, .bn-who { font-size: 11.5px; color: var(--muted); }
|
|
|
|
|
|
.bn-del { margin-left: auto; }
|
|
|
|
|
|
.bn-body { font-size: 14px; line-height: 1.75; color: var(--ink); white-space: normal; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 阅读器 ----
|
|
|
|
|
|
目录在侧栏、正文在右边;窄屏侧栏折到上面(而不是横向挤成一条)。 */
|
|
|
|
|
|
.book-read { display: flex; gap: 18px; align-items: flex-start; }
|
|
|
|
|
|
.br-side {
|
|
|
|
|
|
flex: 0 0 210px; max-height: 72vh; overflow-y: auto;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 12px 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.br-side-h { font-size: 13px; font-weight: 600; color: var(--muted); margin-bottom: 8px; }
|
|
|
|
|
|
.br-toc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
|
|
|
|
.br-toc li { font-size: 13px; }
|
|
|
|
|
|
.br-toc li a {
|
|
|
|
|
|
display: block; padding: 4px 8px; border-radius: 6px; color: var(--ink); text-decoration: none;
|
|
|
|
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.br-toc li a:hover { background: var(--line-2); }
|
|
|
|
|
|
.br-toc li.is-cur a { background: rgba(168, 74, 40, .12); color: var(--brand-ink); font-weight: 600; }
|
|
|
|
|
|
.br-main {
|
|
|
|
|
|
flex: 1 1 auto; min-width: 0;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius); padding: 22px 26px; box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.br-ch-title { font-size: 19px; margin: 0 0 14px; }
|
|
|
|
|
|
.br-body { font-size: 16px; line-height: 1.95; color: var(--ink); }
|
|
|
|
|
|
.br-nav { display: flex; align-items: center; gap: 12px; margin-top: 22px; flex-wrap: wrap; }
|
|
|
|
|
|
.br-pos { margin-left: auto; }
|
|
|
|
|
|
.br-pdf object { width: 100%; height: 78vh; border: 0; display: block; }
|
|
|
|
|
|
@media (max-width: 860px) {
|
|
|
|
|
|
.book-read { flex-direction: column; }
|
|
|
|
|
|
.br-side { flex: 1 1 auto; width: 100%; max-height: 260px; }
|
|
|
|
|
|
.br-main { padding: 16px 18px; }
|
|
|
|
|
|
.br-body { font-size: 15.5px; line-height: 1.9; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 封面裁剪(书的封面是 2:3,与旅程题图的 16:9 不同)----
|
|
|
|
|
|
与 .cover-picker 同一套结构,只是预览框换成竖的。 */
|
|
|
|
|
|
.book-cover-picker #book-cover-preview {
|
|
|
|
|
|
width: 150px; aspect-ratio: 2 / 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 导入读书笔记 ---- */
|
|
|
|
|
|
.imp-how { margin: 0 0 10px; padding-left: 20px; display: flex; flex-direction: column; gap: 5px; }
|
|
|
|
|
|
.imp-how li { font-size: 13.5px; line-height: 1.7; }
|
|
|
|
|
|
.imp-list { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
|
|
|
|
.imp-book {
|
|
|
|
|
|
border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
padding: 10px 12px; background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.imp-bh { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
|
|
|
|
|
|
.imp-t { font-size: 14.5px; font-weight: 600; }
|
|
|
|
|
|
.imp-n { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.imp-notes { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
|
|
|
|
|
|
.imp-notes li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; font-size: 13px; }
|
|
|
|
|
|
.imp-notes li.is-quote .imp-txt { color: var(--muted); }
|
|
|
|
|
|
.imp-txt { flex: 1 1 240px; min-width: 0; line-height: 1.6; }
|
|
|
|
|
|
.imp-confirm { margin-top: 6px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 柱状图:列数不定的(每年的本数 / 评分档位)----
|
|
|
|
|
|
观影那套 .vgrid 是写死 12 列的(12 个月),这里列数随数据变。 */
|
|
|
|
|
|
.vgrid-auto { grid-template-columns: repeat(auto-fit, minmax(26px, 1fr)); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 15 批:活动(容器)/ 旅程(行程)两级语义
|
|
|
|
|
|
术语改了(用户第 1 条),活动表单砍到三项(用户第 4 条)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 活动表单里的"说明一句"(时间/城市从哪来)----
|
|
|
|
|
|
用左边一条竖线而不是整块底色:它是**解释**、不是输入项,
|
|
|
|
|
|
染成和输入区一样的底色会让人以为这里要填东西。 */
|
|
|
|
|
|
.form-note {
|
|
|
|
|
|
margin: 0 0 14px; padding: 8px 0 8px 12px;
|
|
|
|
|
|
border-left: 3px solid var(--line);
|
|
|
|
|
|
font-size: 13px; line-height: 1.75; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.form-note b { color: var(--ink); font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 「更多设置」折叠区:主流程只留三项,其余收在这里 ---- */
|
|
|
|
|
|
.more-set {
|
|
|
|
|
|
margin: 4px 0 14px; border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: var(--radius-s); background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.more-set > summary {
|
|
|
|
|
|
cursor: pointer; padding: 10px 14px;
|
|
|
|
|
|
font-size: 13.5px; color: var(--muted); font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
.more-set > summary:hover { color: var(--brand); }
|
|
|
|
|
|
.more-set[open] > summary { border-bottom: 1px solid var(--line-2); }
|
|
|
|
|
|
.more-set .form-grid { padding: 14px; margin: 0; }
|
|
|
|
|
|
/* 折叠区里的字段少一点内边距,看起来是"附带的"而不是主流程 */
|
|
|
|
|
|
.more-set .field { margin-bottom: 0; }
|
2026-10-05 13:26:49 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 16 批:旅程(容器)/ 行程(单元)两级
|
|
|
|
|
|
术语固定:旅程包含行程(用户第 9 条)。
|
|
|
|
|
|
新增:题图 16:9、五项统计、行程独立页、设置三页、花销。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 题图右侧的信息区:时间 + 城市 ---- */
|
|
|
|
|
|
.trip-when {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px;
|
|
|
|
|
|
font-size: 14px; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.trip-when-date { font-weight: 600; color: var(--ink); }
|
|
|
|
|
|
.trip-when-cities { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 5px; }
|
|
|
|
|
|
.city-chip {
|
|
|
|
|
|
padding: 1px 9px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--brand-ink); font-size: 12.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.city-sep { color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 五项统计(用户第 2 条)---- */
|
|
|
|
|
|
.trip-stats {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 10px 26px;
|
|
|
|
|
|
padding: 10px 0; border-top: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.ts-item { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; }
|
|
|
|
|
|
.ts-n {
|
|
|
|
|
|
font-size: 19px; font-weight: 700; color: var(--brand);
|
|
|
|
|
|
font-variant-numeric: tabular-nums; line-height: 1.2;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ts-l { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.trip-sum { margin: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 行程行上的新元素:出行方式 / 交通细节 / 起终点 / 花销 / 角色 ---- */
|
|
|
|
|
|
.node-mode { font-size: 12px; color: var(--muted); white-space: nowrap; }
|
|
|
|
|
|
.node-traffic { display: flex; flex-wrap: wrap; gap: 5px; }
|
|
|
|
|
|
.node-traffic .ntag {
|
|
|
|
|
|
font-size: 11.5px; padding: 1px 8px; border-radius: 5px;
|
|
|
|
|
|
background: var(--line-2); color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
.node-route-line { font-size: 12.5px; color: var(--muted); }
|
|
|
|
|
|
.node-route-line .arrow { color: var(--faint); margin: 0 3px; }
|
|
|
|
|
|
.node-spent { font-size: 12.5px; color: var(--brand-ink); }
|
|
|
|
|
|
.node-member { display: inline-flex; align-items: center; gap: 4px; }
|
|
|
|
|
|
.node-role {
|
|
|
|
|
|
font-size: 11px; padding: 0 6px; border-radius: 999px;
|
|
|
|
|
|
background: rgba(168, 74, 40, .12); color: var(--brand-ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 行程表单:参与人角色 ---- */
|
|
|
|
|
|
.role-set { margin-top: 6px; }
|
|
|
|
|
|
.role-grid { display: grid; gap: 6px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); margin-top: 8px; }
|
|
|
|
|
|
.role-row { display: flex; align-items: center; gap: 8px; }
|
|
|
|
|
|
.role-who { flex: 0 0 72px; font-size: 13px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.role-row .input { flex: 1 1 auto; min-width: 0; padding: 6px 9px; font-size: 13px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 花销 ---- */
|
|
|
|
|
|
.exp-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.exp-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 7px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7; font-size: 13.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.exp-cat {
|
|
|
|
|
|
font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
|
|
|
|
|
|
background: var(--line-2); color: var(--brand-ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.exp-title { flex: 1 1 140px; min-width: 0; }
|
|
|
|
|
|
.exp-amt { font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.exp-total { margin: 0 0 12px; font-size: 14px; }
|
|
|
|
|
|
.exp-form-row { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
.exp-form-row .input { flex: 1 1 130px; min-width: 0; }
|
|
|
|
|
|
.exp-form-row .select { flex: 0 0 auto; width: auto; min-width: 96px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 设置三页:车辆 / 出行方式 / 节点类型 ---- */
|
|
|
|
|
|
.set-sub { font-size: 14px; font-weight: 600; margin: 16px 0 8px; }
|
|
|
|
|
|
.veh-list { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.veh-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 8px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.veh-ro { background: var(--line-2); }
|
|
|
|
|
|
.veh-ico { font-size: 17px; }
|
|
|
|
|
|
.veh-name { font-size: 14px; font-weight: 600; }
|
|
|
|
|
|
.veh-tag { font-size: 11.5px; padding: 1px 8px; border-radius: 999px; background: var(--surface); color: var(--muted); border: 1px solid var(--line); }
|
|
|
|
|
|
.veh-form { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-width: 0; }
|
|
|
|
|
|
.veh-form .input { flex: 1 1 110px; min-width: 0; padding: 6px 9px; font-size: 13px; }
|
|
|
|
|
|
.veh-form .select { flex: 0 0 auto; width: auto; padding: 6px 9px; font-size: 13px; }
|
|
|
|
|
|
.veh-def { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; color: var(--muted); white-space: nowrap; }
|
|
|
|
|
|
.veh-add { margin-top: 4px; }
|
|
|
|
|
|
|
|
|
|
|
|
.mode-grid { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.mode-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 8px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mode-ico { font-size: 17px; }
|
|
|
|
|
|
.mode-name { flex: 0 0 64px; font-size: 14px; }
|
|
|
|
|
|
.mode-row .input { flex: 1 1 220px; min-width: 0; padding: 6px 9px; font-size: 13px; }
|
|
|
|
|
|
.mode-none { flex: 1 1 auto; }
|
|
|
|
|
|
|
|
|
|
|
|
.type-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.type-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 8px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
.type-form { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-width: 0; }
|
|
|
|
|
|
.type-form .input { flex: 1 1 140px; min-width: 0; padding: 6px 9px; font-size: 13px; }
|
|
|
|
|
|
.type-ico { flex: 0 0 52px !important; text-align: center; font-size: 16px !important; }
|
|
|
|
|
|
.type-tag { font-size: 11.5px; padding: 1px 8px; border-radius: 999px; background: var(--surface); color: var(--muted); border: 1px solid var(--line); }
|
|
|
|
|
|
.type-tag-custom { background: rgba(168, 74, 40, .1); color: var(--brand-ink); border-color: rgba(168, 74, 40, .25); }
|
|
|
|
|
|
.type-used { flex: 0 0 auto; }
|
|
|
|
|
|
.type-add { margin-top: 4px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 窄屏 ---- */
|
|
|
|
|
|
@media (max-width: 860px) {
|
|
|
|
|
|
/* 题图在窄屏铺满一行(信息区折到下面)—— 16:9 的比例保持不变 */
|
|
|
|
|
|
.trip-hero-cover { width: 100%; }
|
|
|
|
|
|
.trip-stats { gap: 8px 18px; }
|
|
|
|
|
|
.ts-n { font-size: 17px; }
|
|
|
|
|
|
}
|
2026-10-05 16:45:10 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 17 批:城市的聚合 / 高德地址 / 表单精简
|
|
|
|
|
|
用户 10 条(城市聚合、类型照 TripLog、只有自驾选车、飞机铁路只记车次、
|
|
|
|
|
|
高德地址、弹框选人、去角色标注、图片右侧显示聚合城市、时间到时分秒)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 时间:精确到时分的那一行(比原来只到日期的那行略宽)---- */
|
|
|
|
|
|
.node-time { font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 出发地 → 到达地:带导航链接 ---- */
|
|
|
|
|
|
.node-route-line a {
|
|
|
|
|
|
color: var(--brand-ink); text-decoration: none;
|
|
|
|
|
|
border-bottom: 1px dashed rgba(168, 74, 40, .35);
|
|
|
|
|
|
}
|
|
|
|
|
|
.node-route-line a:hover { border-bottom-style: solid; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 地址输入(高德联想)----
|
|
|
|
|
|
可见文本框 + 隐藏的 addr/lng/lat/city;下面一行显示"详细地址"与导航链接。 */
|
|
|
|
|
|
.loc-field { display: flex; flex-direction: column; gap: 4px; }
|
|
|
|
|
|
.loc-label { font-size: 13px; color: var(--muted); display: inline-flex; align-items: center; gap: 5px; }
|
|
|
|
|
|
.loc-ico { font-size: 14px; }
|
|
|
|
|
|
.loc-input { width: 100%; }
|
|
|
|
|
|
.loc-extra { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; min-height: 18px; }
|
|
|
|
|
|
.loc-detail {
|
|
|
|
|
|
font-size: 12px; color: var(--muted); flex: 1 1 140px; min-width: 0;
|
|
|
|
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.loc-detail:empty { display: none; }
|
|
|
|
|
|
.loc-nav {
|
|
|
|
|
|
flex: 0 0 auto; font-size: 12px; color: var(--brand-ink);
|
|
|
|
|
|
text-decoration: none; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.loc-nav:hover { text-decoration: underline; }
|
|
|
|
|
|
.loc-nav[hidden] { display: none; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 修正表单:里面的字段少,用同一套 .field 网格 ---- */
|
|
|
|
|
|
.rev-form .field { margin-bottom: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 窄屏:地址那两行不换行挤成一团 ---- */
|
|
|
|
|
|
@media (max-width: 620px) {
|
|
|
|
|
|
.loc-detail { flex: 1 1 100%; }
|
|
|
|
|
|
}
|
2026-10-05 20:12:18 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 18 批:选人弹框改「暂存 + 确定」两段式(用户第 18 条)
|
|
|
|
|
|
上半部分是暂存区(点了头像/名字但还没确定的人),下面是候选清单,
|
|
|
|
|
|
最下面「取消 / 确定」。⚠️ 只有多选(.pp-mode=multi)才渲染这两块。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 暂存区:在搜索框**下面**、候选清单**上面** ----
|
|
|
|
|
|
⚠️ 用户说的是"选择框的上半部分"。搜索框在最顶(要一直能打字搜下一个人),
|
|
|
|
|
|
所以暂存区放在搜索框之下、清单之上 —— 视觉上仍然属于"上半部分",
|
2026-10-05 22:56:49 +08:00
|
|
|
|
而且不会因为暂存区变高把搜索框挤走(搜索是要反复用的)。
|
|
|
|
|
|
⚠️ v24 第 19 批 用户第 8 条:「暂存区太小了,高度太低,看不见人」——
|
|
|
|
|
|
原来只有 148px 且一行能塞很多 chip,看着像一条空横条。
|
|
|
|
|
|
现在:① 高度提到 min 132 / max 46vh(跟着弹框走,不再写死一个矮数);
|
|
|
|
|
|
② chip 改成**大一点**(头像 28px、字号 13.5),并允许每行少放几个,
|
|
|
|
|
|
让人**看得见是谁**;③ 有内容时才占位(没人暂存时不显示,见 JS)。 */
|
2026-10-05 20:12:18 +08:00
|
|
|
|
.pp-stage {
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 8px;
|
2026-10-05 22:56:49 +08:00
|
|
|
|
background: #FDFBF7; padding: 10px 12px; margin-bottom: 8px;
|
|
|
|
|
|
min-height: 132px; max-height: 46vh; overflow-y: auto;
|
|
|
|
|
|
display: flex; flex-direction: column;
|
2026-10-05 20:12:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
.pp-stage[hidden] { display: none; }
|
|
|
|
|
|
.pp-stage-label {
|
2026-10-05 22:56:49 +08:00
|
|
|
|
display: block; font-size: 12px; color: var(--muted); margin-bottom: 8px;
|
|
|
|
|
|
flex: 0 0 auto;
|
2026-10-05 20:12:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
.pp-stage-label b { color: var(--brand); font-variant-numeric: tabular-nums; }
|
2026-10-05 22:56:49 +08:00
|
|
|
|
.pp-stage-chips {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 8px; align-content: flex-start;
|
|
|
|
|
|
flex: 1 1 auto;
|
|
|
|
|
|
}
|
2026-10-05 20:12:18 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 底部按钮:取消在左、确定在右(主操作靠右,与全站一致)---- */
|
|
|
|
|
|
.pp-actions {
|
|
|
|
|
|
display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px;
|
|
|
|
|
|
padding-top: 10px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 暂存区里的 chip 比外面的紧凑一点(弹窗里空间有限)---- */
|
2026-10-05 22:56:49 +08:00
|
|
|
|
.pp-stage-chips .pp-chip { font-size: 13px; padding: 3px 8px 3px 4px; }
|
|
|
|
|
|
.pp-stage-chips .pp-chip img { width: 28px; height: 28px; }
|
2026-10-05 20:12:18 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 窄屏:弹窗几乎占满,暂存区别太高(把清单挤没了就没法选了)---- */
|
|
|
|
|
|
@media (max-width: 480px) {
|
2026-10-05 22:56:49 +08:00
|
|
|
|
.pp-modal-box { max-height: 88vh; }
|
|
|
|
|
|
.pp-stage { min-height: 108px; max-height: 38vh; }
|
2026-10-05 20:12:18 +08:00
|
|
|
|
}
|
2026-10-06 03:14:18 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 20 批 用户第 9 条:**全站按钮悬停统一**
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「很多按钮的悬停效果,非常奇怪,感觉纯粹是换了一个背景色,
|
|
|
|
|
|
这个背景色,跟这个模块完全不协调,应该调整所有按钮的悬停效果,
|
|
|
|
|
|
保持统一,但是不要单纯的换一个不协调的背景色。」
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
⚠️ 改之前的问题(复现探针量出来 **15 种**互不相干的 hover 背景色):
|
|
|
|
|
|
#944022 / #FAF7F1 / #FBF7F1 / #F7EDE4 / #FDF1EE / #F7E4DF / #D79230 /
|
|
|
|
|
|
#518B43 / #AC4835 / var(--line-2) / var(--surface-2,#FDFBF7) / rgba(192,83,63,.08)
|
|
|
|
|
|
—— 同一行里「取消」和「保存」悬停变的是**两套不相干的色**;
|
|
|
|
|
|
`.seg-btn` 那种更是直接糊一层 `#FDFBF7`,在米色底上看着像"脏了一块"。
|
|
|
|
|
|
而且全是"只换背景"这一种表达 —— 这正是用户说的"纯粹是换了一个背景色"。
|
|
|
|
|
|
|
|
|
|
|
|
统一后的**一套手法**(所有按钮共用同一套手感,底色只跟着自己的色系走):
|
|
|
|
|
|
① **同色系加深**:有底色的一律 `filter: brightness(.92)` ——
|
|
|
|
|
|
深色按钮(品牌红 / 黄 / 绿 / 红)自然变深一点,**不再跳到另一个色**;
|
|
|
|
|
|
② **描边留白按钮**(.btn-ghost / .btn-danger / .btn-icon 及各处白底按钮):
|
|
|
|
|
|
统一用**中性薄雾** `rgba(44,35,29,.05)` —— 落在宣纸米底上只是"轻轻按了一下",
|
|
|
|
|
|
不会再出现 #F7EDE4 那种偏色的脏块;
|
|
|
|
|
|
③ **边框微显 + 极轻抬升**:`border-color: rgba(44,35,29,.16)` + `translateY(-1px)`
|
|
|
|
|
|
+ 一层很浅的投影 —— 给的是"这个能按"的触感,而不是换色;
|
|
|
|
|
|
④ 统一 `transition`(背景 / 边框 / 颜色 / 投影 / 位移一起过渡),避免"啪一下变色"。
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 实现上放在**文件最靠后**并带 `!important` 收口:
|
|
|
|
|
|
历史上有十几处散落的 hover(.btn:hover、.page-head 里那几层、.seg-btn:hover…)
|
|
|
|
|
|
优先级各不相同,逐个改既容易漏、又会被后加的规则盖掉。
|
|
|
|
|
|
收口之后**新加的按钮自动继承同一套手感**,作者不必再记一次。
|
|
|
|
|
|
⚠️ 深色浮层上的按钮(.lb-btn 在黑色遮罩上)不适用中性薄雾(深底上看不见),
|
|
|
|
|
|
由浮层自己的规则覆盖;.pv-nav / .pv-dl 同理,见各自定义处。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
:root {
|
|
|
|
|
|
/* 悬停手感三件套(改这里 = 全站按钮悬停一起变) */
|
|
|
|
|
|
--hov-lift: -1px;
|
|
|
|
|
|
--hov-ring: rgba(44, 35, 29, .16);
|
|
|
|
|
|
--hov-veil: rgba(44, 35, 29, .05);
|
|
|
|
|
|
--hov-dim: brightness(.92);
|
|
|
|
|
|
--hov-t: background-color .15s ease, border-color .15s ease,
|
|
|
|
|
|
color .15s ease, box-shadow .15s ease, transform .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn, .btn-ghost, .btn-danger, .btn-warn, .btn-ok, .btn-del, .btn-sm, .btn-icon,
|
|
|
|
|
|
button.btn, a.btn, summary.btn, .seg-btn, .icon-btn, .rv-act-btn, .cs-btn, .bf-btn {
|
|
|
|
|
|
transition: var(--hov-t);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ① 有底色的按钮:同色系加深(不换色)+ 轻抬升
|
|
|
|
|
|
⚠️ 这里**只加 filter,绝不能写 `background-color: inherit`** ——
|
|
|
|
|
|
`inherit` 取的是**父元素**的背景(多半是透明),会把实心按钮变透明
|
|
|
|
|
|
(实测:黄/绿按钮悬停后变成 alpha 0.008 的鬼影)。
|
|
|
|
|
|
不改底色就"不写底色",让按钮自己的 background 留着。 */
|
|
|
|
|
|
.btn:not(.btn-ghost):not(.btn-danger):not(.btn-icon):not(.btn-warn):not(.btn-ok):not(.btn-del):hover,
|
|
|
|
|
|
.btn-warn:hover, .btn-ok:hover, .btn-del:hover,
|
|
|
|
|
|
.search-bar button:hover {
|
|
|
|
|
|
filter: var(--hov-dim);
|
|
|
|
|
|
transform: translateY(var(--hov-lift));
|
|
|
|
|
|
box-shadow: var(--shadow-l);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ② 描边留白按钮:中性薄雾 + 边框微显 + 轻抬升(不再各自糊一个偏色底) */
|
|
|
|
|
|
.btn-ghost:hover, .btn-icon:hover, .seg-btn:hover, .icon-btn:hover,
|
|
|
|
|
|
.who-menu > summary:hover,
|
|
|
|
|
|
.page-head .actions > .btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > a.btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > .btn-ghost:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > button.btn-ghost:not(.btn-icon):hover {
|
|
|
|
|
|
background: var(--hov-veil) !important;
|
|
|
|
|
|
border-color: var(--hov-ring) !important;
|
|
|
|
|
|
transform: translateY(var(--hov-lift));
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn-icon:hover,
|
|
|
|
|
|
.page-head .actions > .movie-set > summary.btn:hover {
|
|
|
|
|
|
background: var(--hov-veil) !important;
|
|
|
|
|
|
border-color: var(--hov-ring) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ③ 危险 / 删除类:同一套手法,薄雾里带一点红(语义不丢,但不刺眼) */
|
|
|
|
|
|
.btn-danger:hover, .rv-del-btn:hover, .btn.danger:hover,
|
|
|
|
|
|
.page-head .actions > .btn-danger:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > a.btn-danger:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > .btn-danger:not(.btn-icon):hover,
|
|
|
|
|
|
.page-head .actions > form > button.btn-danger:not(.btn-icon):hover {
|
|
|
|
|
|
background: rgba(192, 83, 63, .09) !important;
|
|
|
|
|
|
border-color: rgba(192, 83, 63, .30) !important;
|
|
|
|
|
|
color: var(--red) !important;
|
|
|
|
|
|
transform: translateY(var(--hov-lift));
|
|
|
|
|
|
box-shadow: var(--shadow);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ .btn-del 是**实心红**(第 19 批 行程行那种)—— 上面那条 ③ 会把它拉成淡红,
|
|
|
|
|
|
所以实心那一类要单独拉回来:不改底色(保住 #C0533F),只走"同色系加深"。 */
|
|
|
|
|
|
.btn-del:hover {
|
|
|
|
|
|
background: #C0533F !important;
|
|
|
|
|
|
color: #fff !important;
|
|
|
|
|
|
border-color: transparent !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ④ 纯图标 / 文字小按钮:不占背景,只做"轻抬升 + 轻微加深" */
|
|
|
|
|
|
.person-more-btn:hover, .rv-act-btn:hover, .bf-btn:hover, .cs-btn:hover,
|
|
|
|
|
|
.more-set > summary:hover, .rv-open-btn:hover {
|
|
|
|
|
|
filter: var(--hov-dim);
|
|
|
|
|
|
transform: translateY(var(--hov-lift));
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ⑤ 浮在深色遮罩上的按钮:深底上中性薄雾看不见 → 用"提亮"代替,
|
|
|
|
|
|
但**同一套手法**(变亮 + 轻抬升),保持全局手感一致。 */
|
|
|
|
|
|
.lb-btn:hover, .pv-close:hover, .crop-x:hover {
|
|
|
|
|
|
filter: brightness(1.18);
|
|
|
|
|
|
transform: translateY(var(--hov-lift));
|
|
|
|
|
|
}
|
2026-10-11 10:12:11 +08:00
|
|
|
|
/* 🔴🔴 v41 例外(必须写在上面那条**之后**,靠"同特异性、后者胜"生效):
|
|
|
|
|
|
`.lb-nav`(照片左右切换)是**靠 transform 居中**的,一旦被上面的
|
|
|
|
|
|
`translateY(var(--hov-lift))` 覆盖,hover 时按钮会从"居中"跳到"距顶 50%",
|
|
|
|
|
|
位移近半个按钮高 —— 用户报的就是这个("悬停之后位置会变一下,一不小心就会点错")。
|
|
|
|
|
|
⇒ 这里把它的居中 transform 显式写回,只保留提亮。位置前后一字不动。 */
|
|
|
|
|
|
.lb-nav:hover { transform: translateY(-50%); }
|
2026-10-06 03:14:18 +08:00
|
|
|
|
|
|
|
|
|
|
/* v24 第 20 批 第 3 条:`form="id"` 关联用的**表单外壳**。
|
|
|
|
|
|
它们只承载字段、不出现在视觉里(按钮在原来的位置上,用 form= 指过来)。
|
|
|
|
|
|
⚠️ 必须 display:none —— 不藏的话页面底部会多出几块空的表单块。 */
|
|
|
|
|
|
.form-outside { display: none; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 20 批 第 5 条:添加行程的三处版面调整
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 出发地 / 到达地**同一行**(用户原话:"应该在同一行")----
|
|
|
|
|
|
⚠️ 必须显式开一个"一行两列"的容器,不能靠两个 .field 相邻 ——
|
|
|
|
|
|
.form-grid 是两列网格,每个 .field 各占一格;窄屏折行后顺序还会乱。 */
|
|
|
|
|
|
.loc-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
/* 窄屏放不下并排两个地址框(中文地名 + 高德联想候选),改成上下 */
|
|
|
|
|
|
.loc-row { grid-template-columns: 1fr; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② 「车辆」只在出行方式 = 自驾 时出现(第 17 批的**同一句原话**)----
|
|
|
|
|
|
🔴 v24 第 20 批 第 5 条修的是这里:用户又报了一次「车辆,只在出行方式选择自驾时
|
|
|
|
|
|
才出现,其他情况下,默认不出现」—— 说明**上一批的隐藏根本没生效**。
|
|
|
|
|
|
根因:模板里写的是 `<div class="field" data-mode-vehicle hidden>`,
|
|
|
|
|
|
而 `.field` 自己声明了 `display:flex` —— **作者样式优先于浏览器默认的
|
|
|
|
|
|
`[hidden]{display:none}`**,所以 `hidden` 形同虚设、车辆永远显示着。
|
|
|
|
|
|
(与 .pp-item / .pv 那几处是**同一个坑**,项目里已经栽过三次。)
|
|
|
|
|
|
修法:给自己声明过 display 的元素补一条 `[hidden]` 规则。 */
|
|
|
|
|
|
.field[hidden],
|
|
|
|
|
|
.field.full[hidden],
|
|
|
|
|
|
[data-mode-vehicle][hidden],
|
|
|
|
|
|
[data-mode-ticket][hidden] { display: none !important; }
|
|
|
|
|
|
|
2026-10-12 15:31:03 +08:00
|
|
|
|
/* 🔴 v44(用户 2026-10-12 第 2 条):重复那三行(结束条件 / 重复次数 / 重复到)
|
|
|
|
|
|
在观影式排版下是 `.mv-row`(`display:flex`)⇒ 同上面 `.field` 那个坑:
|
|
|
|
|
|
**作者样式优先于 `[hidden]` 的浏览器默认 `display:none`**,`hidden` 形同虚设。
|
|
|
|
|
|
⇒ 一并补上,否则"不重复时它们也显示着"。 */
|
|
|
|
|
|
.mv-row[hidden] { display: none !important; }
|
|
|
|
|
|
|
2026-10-06 03:14:18 +08:00
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 20 批 第 4 条:拖动即时上传的**暂存区** UI
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
`.stage-drop` 是那个"可以往里拖"的落点;`[data-stage-list]` 装卡片。
|
|
|
|
|
|
卡片三态:.is-uploading(转圈感)/ 默认(缩略图)/ .is-failed(标红)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.stage-drop {
|
|
|
|
|
|
border: 1px dashed var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7; padding: 10px 12px; margin-top: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stage-drop.is-over { outline: 2px dashed var(--brand); outline-offset: 3px; background: #FDF3EC; }
|
|
|
|
|
|
.stage-drop-tip { display: block; font-size: 12px; color: var(--muted); margin-bottom: 8px; }
|
|
|
|
|
|
.stage-list { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
|
|
|
|
/* ⚠️ .stage-list 自己声明了 display:flex → 要藏就得补 [hidden](本项目老坑) */
|
|
|
|
|
|
.stage-list[hidden] { display: none; }
|
|
|
|
|
|
.stage-cell {
|
|
|
|
|
|
position: relative; width: 84px; padding: 6px 4px; border-radius: 8px;
|
|
|
|
|
|
border: 1px solid var(--line); background: var(--surface);
|
|
|
|
|
|
display: flex; flex-direction: column; align-items: center; gap: 3px;
|
|
|
|
|
|
font-size: 11px; text-align: center; box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stage-cell img { width: 72px; height: 54px; object-fit: cover; border-radius: 5px; display: block; }
|
|
|
|
|
|
.stage-cell .stage-ico {
|
|
|
|
|
|
width: 72px; height: 54px; border-radius: 5px; background: #5F6672; color: #fff;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center; font-weight: 700;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stage-cell .stage-name {
|
|
|
|
|
|
max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.stage-cell .stage-meta { color: var(--muted); }
|
|
|
|
|
|
.stage-cell.is-uploading { opacity: .7; }
|
|
|
|
|
|
.stage-cell.is-uploading .stage-meta { color: var(--brand); }
|
|
|
|
|
|
.stage-cell.is-failed { border-color: var(--red); background: #FDF1EE; }
|
|
|
|
|
|
.stage-cell.is-failed .stage-meta { color: var(--red); }
|
|
|
|
|
|
.stage-cell .stage-x {
|
|
|
|
|
|
position: absolute; top: -6px; right: -6px; width: 20px; height: 20px;
|
|
|
|
|
|
border-radius: 50%; border: 1px solid var(--line); background: #fff; color: var(--muted);
|
|
|
|
|
|
font-size: 13px; line-height: 1; cursor: pointer; padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.stage-cell .stage-x:hover { color: #fff; background: var(--red); border-color: var(--red); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 20 批 第 6 条:周 / 日视图的「当前时间红线」
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「应该在视图中间显示一条红线,用来表示当前进行的时间,
|
|
|
|
|
|
用一个不断从上到下的红线,来表示当前时间在视图上的刻度和位置。」
|
|
|
|
|
|
⚠️ 用**绝对定位**(top 由服务端/JS 给百分比)—— 与 .tg-block 同一套坐标,
|
|
|
|
|
|
所以线正好落在时间刻度的位置上,不会与日程块错开。
|
|
|
|
|
|
⚠️ 只在**今天那一列**出现(`.is-today`),由模板决定渲染不渲染。
|
|
|
|
|
|
⚠️ `pointer-events: none`:这条线是"刻度提示",不该挡住它下面的日程点击
|
|
|
|
|
|
(用户点线附近想点的是日程,不是这条线)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.tg-now {
|
|
|
|
|
|
position: absolute; left: 0; right: 0; height: 0;
|
|
|
|
|
|
border-top: 2px solid #E0453B; /* 红线(用户点名"红线") */
|
|
|
|
|
|
z-index: 4; /* 在日程块(z-index 2)之上,要看得见 */
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 左端那个小圆点:让"这条线是活的、代表此刻"更明显(也与日历 App 的通行做法一致) */
|
|
|
|
|
|
.tg-now::before {
|
|
|
|
|
|
content: ""; position: absolute; left: -4px; top: -5px;
|
|
|
|
|
|
width: 8px; height: 8px; border-radius: 50%; background: #E0453B;
|
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(255, 255, 255, .9);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 过午夜(或跨天翻页)时线要能"走出去",不要卡在格子边界上闪 */
|
|
|
|
|
|
.tg-col { overflow: hidden; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 20 批 第 7 条:重复日程删除的**范围选择**
|
|
|
|
|
|
(只删这一次 / 这一次及以后 / 全部)
|
|
|
|
|
|
⚠️ 三档要**竖着列**并带说明文字:这是不可逆操作,横排挤成一行会看不清后果。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.ev-del-scope { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
|
|
|
|
|
|
.ev-del-head { margin: 0; font-size: 14px; color: var(--ink); }
|
|
|
|
|
|
.ev-del-picks { display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.ev-del-picks .chk-inline { align-items: flex-start; }
|
|
|
|
|
|
|
|
|
|
|
|
/* v24 第 20 批 第 8 条:提醒多选的排版(勾选框多了要能换行,别挤成一长条) */
|
|
|
|
|
|
.rem-picks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
|
|
|
|
|
|
.rem-pick { font-size: 13px; }
|
2026-10-06 12:08:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 21 批 第 2 条:观影编辑页的**已存图片**要缩成缩略图
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「观影模块,海报和票根以及照片都带进来了,但是没有缩放,
|
|
|
|
|
|
把页面撑破了,应该缩放成缩略图。」
|
|
|
|
|
|
|
|
|
|
|
|
🔴 根因:`.mv-slot` 这个类**在样式表里根本不存在**(第 20 批加模板时只写了
|
|
|
|
|
|
结构没写样式)。于是里面的 <img> 按**原始像素**渲染 —— 海报是 2:3 竖图
|
|
|
|
|
|
(上传时按 600×900 裁的),就在一个 236px 宽的格子里撑出
|
|
|
|
|
|
600×900 + 942px 高,把表单顶破、还让整页横向溢出(实测 docW 1297 > vw 1280)。
|
|
|
|
|
|
「带进来了」这个功能是对的,缺的是"把它当成缩略图看"这一层样式。
|
|
|
|
|
|
|
|
|
|
|
|
现在的规格:左侧固定尺寸缩略图(海报 2:3 → 108×162;票根按同一高度裁切),
|
|
|
|
|
|
右侧「删除这张」按钮,整体是"看得见、不占地方"的一张缩略图。
|
|
|
|
|
|
⚠️ `object-fit: cover` 是必须的:票根那种横长条塞进竖框里,
|
|
|
|
|
|
不用它就会被压扁变形(看着像图坏了)。
|
|
|
|
|
|
⚠️ 缩略图高度**写死**、不能再由图片自身比例决定 —— 那正是撑破的原因。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.mv-slot {
|
|
|
|
|
|
display: flex; align-items: flex-start; gap: 10px;
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mv-slot > a {
|
|
|
|
|
|
display: block; flex: 0 0 auto;
|
|
|
|
|
|
width: 108px; height: 162px; overflow: hidden;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #F1E7D6;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mv-slot > a img {
|
|
|
|
|
|
width: 100%; height: 100%; object-fit: cover; display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mv-slot > .btn { flex: 0 0 auto; align-self: center; }
|
|
|
|
|
|
/* 窄屏:缩略图再小一点,别把"删除这张"挤出去 */
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
.mv-slot > a { width: 84px; height: 126px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 21 批 第 7 条:「点击或拖动进行上传」的那个框
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「所有上传图片等附件的地方,都不再放按钮,而是放一个框,
|
|
|
|
|
|
点击这个框实现点击上传按钮的功能,拖动图片进这个框里,
|
|
|
|
|
|
实现拖动多个上传功能。框里面写一句话:点击或拖动进行上传,
|
|
|
|
|
|
其他的功能和现在保持一致。」
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 这是**全新的统一上传入口**,取代了原来的 `<input class="input" type=file>`
|
|
|
|
|
|
(那个原生控件长得像输入框、写着"选择文件 未选择任何文件",
|
|
|
|
|
|
与旁边那个拖放虚线框是**两个**入口 —— 用户看到的就是"到底点哪个")。
|
|
|
|
|
|
现在原生框整个 `.sr-only` 藏起来,页面上只有这**一个**框。
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 落点高亮 `.is-over` 由 app.js 的 bindZone 加(拖动经过时)——
|
|
|
|
|
|
与既有的 `.dropzone.is-over` 是同一套动作,只是这个框自己有底色,
|
|
|
|
|
|
高亮用"描边+底色变亮"表达(不用 outline,避免与自带虚线边重叠成双线)。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.stage-drop-tip { display: none; } /* 旧的提示位:文案已并进框里,这里留个空占位规则 */
|
|
|
|
|
|
|
|
|
|
|
|
.upbox {
|
|
|
|
|
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
|
|
|
|
gap: 6px; width: 100%; min-height: 96px; box-sizing: border-box;
|
|
|
|
|
|
padding: 16px 14px; cursor: pointer; text-align: center;
|
|
|
|
|
|
border: 1.5px dashed var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7; color: var(--muted);
|
|
|
|
|
|
transition: background-color .15s ease, border-color .15s ease, color .15s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.upbox:hover { border-color: var(--brand-2); background: #FBF6F0; color: var(--brand); }
|
|
|
|
|
|
.upbox:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
|
|
|
|
|
|
/* 拖动经过时的高亮(app.js 的 bindZone 加 .is-over) */
|
|
|
|
|
|
.upbox.is-over {
|
|
|
|
|
|
border-color: var(--brand); border-style: solid;
|
|
|
|
|
|
background: #FDF3EC; color: var(--brand);
|
|
|
|
|
|
}
|
|
|
|
|
|
.upbox-ico { font-size: 22px; line-height: 1; font-weight: 300; }
|
|
|
|
|
|
.upbox-msg { font-size: 13.5px; }
|
2026-10-08 17:41:30 +08:00
|
|
|
|
/* 🔴 v30 第 1 条:「选中文件后,那个文件输入框,得有点反应才对。」
|
|
|
|
|
|
非暂存框(导入型)选中文件后由 app.js 的 bindFileEcho() 加 `.is-picked`
|
|
|
|
|
|
并把框里的话换成文件名 —— 这里把它从"虚线待放"变成"实线已选",
|
|
|
|
|
|
配色也换成品牌色的浅底,一眼能看出"这一步已经做完了"。
|
|
|
|
|
|
⚠️ 与 `.is-over`(拖动经过的高亮)区分开:那个是**临时**高亮,
|
|
|
|
|
|
这个是**已选**的稳定态,两者同时命中时以 is-picked 为准(写在后面)。 */
|
|
|
|
|
|
.upbox.is-picked {
|
|
|
|
|
|
border-style: solid; border-color: var(--brand);
|
|
|
|
|
|
background: #FDF3EC; color: var(--brand-ink, var(--brand));
|
|
|
|
|
|
}
|
|
|
|
|
|
.upbox.is-picked .upbox-ico { font-size: 18px; font-weight: 600; }
|
|
|
|
|
|
.upbox.is-picked .upbox-msg { font-weight: 600; word-break: break-all; }
|
2026-10-06 12:08:40 +08:00
|
|
|
|
/* 窄屏:框再矮一点,别把表单撑太长 */
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
.upbox { min-height: 78px; padding: 12px; }
|
|
|
|
|
|
.upbox-ico { font-size: 18px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 空的提示行(暂存清单下面那句"已上传/失败"):没内容时不占地方 */
|
|
|
|
|
|
.stage-drop-tip:not([hidden]) { display: block; margin-top: 6px; font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 21 批 第 7 条:新建日程的**弹框**
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「日历中新建日程,无论是点击按钮还是点击日历中间,都是采用弹框的形式
|
|
|
|
|
|
进行添加,这样不影响当前日历的显示,添加完成后,动态修改当前视图,
|
|
|
|
|
|
不要刷新。」
|
|
|
|
|
|
⚠️ 原来那张表单是**内联**在日历网格上方的卡片,一展开就把月视图推下去 ——
|
|
|
|
|
|
正是"影响当前日历的显示"。改成浮层后,底下的日历**一动不动**。
|
|
|
|
|
|
⚠️ 视觉沿用站内既有的浮层语言(遮罩 rgba(44,35,29,.55) + 圆角面板 + 阴影),
|
|
|
|
|
|
与选人弹窗 / 名册动作框 / 裁剪器是同一套,用户不用重新认。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.cal-modal {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 200;
|
|
|
|
|
|
display: flex; align-items: flex-start; justify-content: center;
|
|
|
|
|
|
padding: 24px 16px; overflow-y: auto;
|
|
|
|
|
|
background: rgba(44, 35, 29, .55); overscroll-behavior: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-modal[hidden] { display: none; }
|
2026-10-10 00:26:42 +08:00
|
|
|
|
/* 🔴 v37:`max-height` 必须把 `.cal-modal`(本面板的父层)自己的 `padding: 24px`
|
|
|
|
|
|
算进去 —— 只减 48 会让面板底部**刚好探出视口 4px**,
|
|
|
|
|
|
于是 `.cal-modal-foot` 里那两个按钮有半截在屏幕外(用户"看不到按钮"的另一半原因)。
|
|
|
|
|
|
⇒ 减 **64px** = 上下各 24px 的遮罩内边距 + 16px 余量。 */
|
2026-10-06 12:08:40 +08:00
|
|
|
|
.cal-modal-panel {
|
|
|
|
|
|
width: min(680px, 100%); margin: auto;
|
|
|
|
|
|
background: var(--surface); border-radius: 14px;
|
|
|
|
|
|
box-shadow: var(--shadow-l); display: flex; flex-direction: column;
|
2026-10-10 00:26:42 +08:00
|
|
|
|
max-height: calc(100vh - 64px);
|
2026-10-06 12:08:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
.cal-modal-head {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 14px 16px 12px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-modal-head b { font-size: 15.5px; font-weight: 600; }
|
|
|
|
|
|
.cal-modal-x {
|
|
|
|
|
|
margin-left: auto; border: 0; background: transparent; cursor: pointer;
|
|
|
|
|
|
font-size: 15px; line-height: 1; color: var(--muted);
|
|
|
|
|
|
padding: 4px 7px; border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-modal-x:hover { background: var(--hov-veil); color: var(--ink); }
|
|
|
|
|
|
.cal-modal-body { padding: 16px; overflow-y: auto; flex: 1 1 auto; }
|
|
|
|
|
|
.cal-modal-foot {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 16px 14px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 提交键贴右(次要动作在左、主要动作在右,与全站一致) */
|
|
|
|
|
|
.cal-modal-foot .btn[type="submit"] { margin-left: auto; }
|
|
|
|
|
|
.cal-modal-tip { font-size: 12.5px; color: var(--muted); }
|
|
|
|
|
|
.cal-modal-tip.err { color: var(--red); }
|
|
|
|
|
|
|
|
|
|
|
|
/* 日历本:色块 + 下拉(原生 option 画不出色块,见模板里的说明) */
|
|
|
|
|
|
.cal-book-row { display: flex; align-items: center; gap: 8px; }
|
|
|
|
|
|
.cal-book-dot {
|
|
|
|
|
|
flex: 0 0 auto; width: 20px; height: 20px; border-radius: 6px;
|
|
|
|
|
|
border: 1px solid rgba(44, 35, 29, .12);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cal-book-row .select { flex: 1 1 auto; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 21 批 第 7 条:日程新建弹框的显隐(**必须放收尾**)
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
⚠️ 为什么单独补这一条:本项目有一条全局兜底
|
|
|
|
|
|
`.field[hidden], .field.full[hidden], [data-mode-vehicle][hidden], … { display:none !important }`
|
|
|
|
|
|
(第 20 批为了修"车辆藏不住"加的)。而弹框的**面板里就有 `.field`** ——
|
|
|
|
|
|
面板一旦被隐藏,CSS 的 `display:flex` 与那条 `!important` 会打架,
|
|
|
|
|
|
加上 `hidden` 属性同时落在多个层级上,会出现"明明摘了 hidden 却还是不显示"。
|
|
|
|
|
|
这里用 `:not([hidden])` 把"打开态"显式钉死(后写者赢 + 特异性更高),
|
|
|
|
|
|
两种状态各归各的规则、互不牵连。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.cal-modal:not([hidden]) { display: flex; }
|
|
|
|
|
|
.cal-modal[hidden] { display: none !important; }
|
2026-10-06 17:33:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 22 批:CardDAV 卡的窄屏收口
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
⚠️ 为什么必须补这一段:`.node-badge` 是 `white-space: nowrap`(徽标本来就不该折行,
|
|
|
|
|
|
全站都在用),而这一卡的按钮行里放了一句说明性徽标 + 一个长地址输入框 ——
|
|
|
|
|
|
在 360/375/390px 上直接把整页**撑出横向滚动**
|
|
|
|
|
|
(真机几何实测:scrollW 412 > clientW 360,越界元素 = 这句徽标)。
|
|
|
|
|
|
手机上"整页能左右拖"是最刺眼的一类问题,所以:
|
|
|
|
|
|
· 窄屏让 `.btn-row` 能换行(否则按钮 + 徽标永远挤在一行);
|
|
|
|
|
|
· 徽标允许折行(它在这张卡里是**说明**,不是标签)。
|
|
|
|
|
|
只作用于这张卡(`.card[id="carddav"]`),不动全站的 `.node-badge` ——
|
|
|
|
|
|
改全站会把所有徽标都变成可折行,那些地方正是要靠 nowrap 保持一行。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
|
#carddav .btn-row { flex-wrap: wrap; }
|
|
|
|
|
|
#carddav .node-badge { white-space: normal; }
|
|
|
|
|
|
}
|
2026-10-06 20:41:04 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 23 批 用户第 1 条:资源页列表瘦身 + 右上角四色按钮 + 四个弹框
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 标题行:按钮组吸附到最右侧(与标题同一排)----
|
|
|
|
|
|
见上面 `.res-ops` 原位那条注释:**旧规则已经就地改掉了**,不是在这里再覆盖一遍。
|
|
|
|
|
|
(这正是本轮踩的坑:先前只在这里追加,`flex-direction: column` 漏改,按钮竖排。)
|
|
|
|
|
|
⚠️ 按钮组必须是 <span>(phrasing content):<summary> 里放 <div> 是非法 HTML。
|
|
|
|
|
|
这里给 `display:inline-flex` 才能有 flex 布局(span 默认 inline)。 */
|
|
|
|
|
|
.res-caret { color: var(--faint); font-size: 12px; flex: 0 0 auto; }
|
|
|
|
|
|
/* 展开时把箭头翻过来(纯装饰,不影响语义) */
|
|
|
|
|
|
.res-item[open] .res-caret { transform: rotate(180deg); }
|
|
|
|
|
|
.res-caret { transition: transform .15s ease; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② 四个按钮的颜色(用户点名:编辑黄、共享绿、附件蓝、删除红)----
|
|
|
|
|
|
`.btn` 自带边框与底色,这里只覆盖这三样;文字色统一用白(黄底白字对比度偏低,
|
|
|
|
|
|
所以黄色的字色用深棕而不是纯白 —— 与 `.btn-warn` 的既有做法一致)。 */
|
|
|
|
|
|
.btn-info { background: #2C6FB5; color: #fff; border-color: transparent; } /* 附件:蓝 */
|
|
|
|
|
|
.res-op { font-size: 12.5px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ③ 展开区:人员行(附件列完之后才显示)----
|
|
|
|
|
|
用户原话:「附件列完后,列出来人员,所有者、共享给谁了。然后其他的都不要。」 */
|
|
|
|
|
|
.res-people {
|
|
|
|
|
|
display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
|
|
|
|
|
|
padding-top: 10px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ④ 弹框外壳 ----
|
|
|
|
|
|
⚠️ `[hidden]` 必须**自己声明**:下面这两个类都写了 `display:flex`,
|
|
|
|
|
|
而 `[hidden]` 的浏览器默认 `display:none` 优先级更低 → 会被盖过 → 关不掉。
|
|
|
|
|
|
项目在 `.pv` 与 `.pp-item` 上各栽过一次,所以这两行是硬要求(有 e2e 断言盯着)。 */
|
|
|
|
|
|
.res-modal {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 78;
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-modal[hidden] { display: none; }
|
|
|
|
|
|
.res-mask { position: absolute; inset: 0; background: rgba(47, 36, 30, .34); }
|
|
|
|
|
|
.res-panel-lg, .res-panel-sm {
|
|
|
|
|
|
position: relative; z-index: 1;
|
|
|
|
|
|
background: var(--surface); border: 1px solid var(--line);
|
|
|
|
|
|
border-radius: 14px; box-shadow: var(--shadow-l);
|
|
|
|
|
|
width: min(460px, 92vw); max-height: min(88vh, 700px);
|
|
|
|
|
|
display: flex; flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-panel-sm { width: min(400px, 92vw); }
|
|
|
|
|
|
.res-panel-lg[hidden], .res-panel-sm[hidden] { display: none; }
|
|
|
|
|
|
.res-ph {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 12px 14px 10px; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-ph b { font-size: 14.5px; }
|
|
|
|
|
|
.res-x {
|
|
|
|
|
|
margin-left: auto; border: 0; background: transparent; cursor: pointer;
|
|
|
|
|
|
font-size: 15px; color: var(--muted); padding: 4px 6px; border-radius: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-x:hover { background: var(--line-2); color: var(--ink); }
|
|
|
|
|
|
.res-pb { padding: 12px 14px; overflow-y: auto; }
|
|
|
|
|
|
.res-pb .field { margin-bottom: 12px; }
|
|
|
|
|
|
.res-pb .field > label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 5px; }
|
|
|
|
|
|
.res-pf {
|
|
|
|
|
|
display: flex; gap: 8px; justify-content: flex-end;
|
|
|
|
|
|
padding: 10px 14px; border-top: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.res-pb .pp { max-width: none; }
|
|
|
|
|
|
.res-sub { font-size: 13px; color: var(--muted); margin: 14px 0 8px; font-weight: 600; }
|
|
|
|
|
|
.res-share-now { border-top: 1px solid var(--line-2); margin-top: 10px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ⑤ "已共享给" / "已有附件" 两行(脚本按 data 属性现渲染)----
|
|
|
|
|
|
⚠️ 用 <span> + inline-flex 而不是 <div>/<table>:
|
|
|
|
|
|
这些行要能塞进任意容器,且不需要表格语义(就是"一行一行的清单")。 */
|
|
|
|
|
|
.rd-share-row, .rd-att-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 6px 0; border-bottom: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.rd-share-row:last-child, .rd-att-row:last-child { border-bottom: 0; }
|
|
|
|
|
|
.rd-share-name, .rd-att-name { flex: 1 1 auto; min-width: 0; word-break: break-all; font-size: 13.5px; }
|
|
|
|
|
|
/* 附件行里的缩略图:与展开区的附件墙同一个观感(小一号,弹框里放得下) */
|
|
|
|
|
|
.rd-att-thumb {
|
|
|
|
|
|
width: 34px; height: 34px; flex: 0 0 auto;
|
|
|
|
|
|
object-fit: cover; border-radius: 6px; border: 1px solid var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
.rd-att-ico {
|
|
|
|
|
|
width: 34px; height: 34px; flex: 0 0 auto;
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
border-radius: 6px; background: #5F6672; color: #fff;
|
|
|
|
|
|
font-size: 10px; text-align: center; line-height: 1.1;
|
|
|
|
|
|
padding: 2px; overflow: hidden; word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ⑥ 窄屏 ----
|
|
|
|
|
|
四个按钮 + 标题 + 归属人 chip + 权限徽标挤在一行,360px 上必然溢出。
|
|
|
|
|
|
让按钮组整体落到第二行(`.res-head` 本来就能 wrap),并收紧内边距。
|
|
|
|
|
|
⚠️ 这里**不**动全站 `.node-badge` 的 nowrap —— 上一批(CardDAV 卡)已经证明
|
|
|
|
|
|
改全站会把所有徽标都变得可折行。 */
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.res-head { padding: 10px 12px; row-gap: 6px; }
|
|
|
|
|
|
.res-ops { margin-left: 0; width: 100%; justify-content: flex-start; }
|
|
|
|
|
|
.res-caret { display: none; }
|
|
|
|
|
|
.res-op { flex: 0 1 auto; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 23 批 用户第 2 条:财务页类别标签可点 + 上下两图联动
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 概览卡里的标签条 ----
|
|
|
|
|
|
原来是一排纯展示的 <span>(不可点),现在与图表卡那条 chip **并成一套筛选入口**。
|
|
|
|
|
|
⚠️ 元素从 <span> 换成了 <button>:它现在真的有行为了 ——
|
|
|
|
|
|
用 span 加 JS 点击,键盘用户和屏幕阅读器都认不出"这是个能按的东西"。
|
|
|
|
|
|
代价是浏览器会给 <button> 默认样式(灰底、系统字体、内边距),
|
|
|
|
|
|
`.ck-chip` 里已经把这些全部覆盖掉了(它本来就是给 button 写的)。
|
|
|
|
|
|
⚠️ 两条既有规则都在抢 margin:`.led-kinds`(margin-top:6px)在前、
|
|
|
|
|
|
`.ck-filter`(margin:0 0 12px)在后 → 后者赢,6px 那个上边距会被吃掉。
|
|
|
|
|
|
所以这一条写在**文件末尾**,用双类选择器把意图压回来。 */
|
|
|
|
|
|
.led-kinds.ck-filter { margin: 8px 0 0; }
|
|
|
|
|
|
/* 标签上的金额(原来就有,改成 button 后需要重新确认字重/数字对齐) */
|
|
|
|
|
|
.led-kind-chip b { font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② 选中类别后的高亮条 ----
|
|
|
|
|
|
回答用户那句"统计这个标签下的所有财务条目的总数":
|
|
|
|
|
|
看的是哪一类、合计多少、几笔 —— 并且给一个明确的出口(清除筛选)。
|
|
|
|
|
|
⚠️ 没有它的话,"图上少了几条线"会被读成"数据丢了",而不是"我在筛选"。 */
|
|
|
|
|
|
.led-focus {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
|
|
|
|
|
margin-top: 10px; padding: 8px 12px;
|
|
|
|
|
|
background: #FDF6EE; border: 1px solid #EBD9C4; border-radius: 8px;
|
|
|
|
|
|
font-size: 13px; color: #7A4A20;
|
|
|
|
|
|
}
|
|
|
|
|
|
.led-focus[hidden] { display: none; } /* 见 .res-modal 的同一提醒:自己声明了 display 就必须补这条 */
|
|
|
|
|
|
.led-focus-txt { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ③ 图下面的说明:整本账 / 只看某一类,两句话互斥显示 ---- */
|
|
|
|
|
|
.ck-note { margin: 8px 2px 0; }
|
|
|
|
|
|
.ck-note > span[hidden] { display: none; }
|
2026-10-07 05:52:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 24 批 用户第 2、3 条:首页信息面板 + 日程/任务左右各半
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 信息面板:左(问候/日子/数字) + 右(天气,**贴右端**)----
|
|
|
|
|
|
⚠️ 旧的 `.home-brief` 是 `flex-direction: column`,天气自然就落到了下一行。
|
|
|
|
|
|
用户明确要求「天气放在这个信息面板的最右侧…靠右放」→ 改成横排 + margin-left:auto。
|
|
|
|
|
|
⚠️ 这里**必须**把旧规则的那几行一起改掉(v24 第 23 批:只在末尾追加、
|
|
|
|
|
|
漏了 flex-direction,四个按钮竖排撑高标题行 —— 同一个坑不再踩第二次)。 */
|
|
|
|
|
|
.home-brief { display: flex; flex-direction: row; align-items: flex-start; gap: 18px; flex-wrap: wrap; }
|
|
|
|
|
|
.hb-left { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.hb-hello { font-size: 19px; line-height: 1.3; }
|
|
|
|
|
|
.hb-hello b { font-weight: 700; }
|
|
|
|
|
|
.hb-date { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; color: var(--muted); font-size: 13.5px; }
|
|
|
|
|
|
.hb-date .hb-d { color: var(--ink); font-size: 15px; font-weight: 600; }
|
|
|
|
|
|
.hb-date .hb-lunar { color: var(--brand-ink); }
|
|
|
|
|
|
/* 日子标记:节气 / 法定假日 / 传统节日 / 纪念日 / 生日,各给一个色 */
|
|
|
|
|
|
.hb-marks { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
|
|
|
|
.hb-mark {
|
|
|
|
|
|
display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 999px;
|
|
|
|
|
|
font-size: 12.5px; white-space: nowrap; border: 1px solid transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.hb-mark.is-holiday { background: #FDECEC; color: #A8232B; border-color: #F3C9C9; }
|
|
|
|
|
|
.hb-mark.is-term { background: #EDF4E9; color: #3F6B34; border-color: #CFE2C6; }
|
|
|
|
|
|
.hb-mark.is-festival { background: #FDF2E3; color: #96551A; border-color: #F0D9B8; }
|
|
|
|
|
|
.hb-mark.is-anniv { background: #F2ECF7; color: #6B4A86; border-color: #DCCBE8; }
|
|
|
|
|
|
.hb-mark.is-birthday { background: #FDECF3; color: #A03060; border-color: #F3C9DB; }
|
|
|
|
|
|
.hb-stats { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.hb-stats .hbs { display: inline-flex; align-items: baseline; gap: 4px; color: var(--muted); }
|
|
|
|
|
|
.hb-stats .hbs b { color: var(--ink); font-size: 16px; font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.hb-stats .hbs.is-late b { color: var(--red); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 天气卡:贴右端 + **彩色**图标(用户原话「彩色图标的形式」)----
|
|
|
|
|
|
⚠️ 颜色按天气**色调**(后端给的 tone)分档,而不是让 CSS 猜天气码 ——
|
|
|
|
|
|
同一份判断写两遍必然飘。晴=琥珀、云=灰蓝、雨=天蓝、雪=青、雷=紫、雾=灰。 */
|
|
|
|
|
|
.hb-weather {
|
|
|
|
|
|
margin-left: auto; flex: 0 0 auto;
|
|
|
|
|
|
display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto;
|
|
|
|
|
|
align-items: center; gap: 2px 12px; min-width: 168px;
|
|
|
|
|
|
padding-left: 16px; border-left: 1px solid var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.hbw-icon {
|
|
|
|
|
|
grid-row: 1 / span 2; font-size: 40px; line-height: 1;
|
|
|
|
|
|
/* ⚠️ 不能靠 `-webkit-text-fill-color` 之类给**文字**上渐变(见 emoji-glyph 那课),
|
|
|
|
|
|
这里就是普通的彩色文字 + 一点投影,稳定且不挑系统字体。 */
|
|
|
|
|
|
filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .10));
|
|
|
|
|
|
}
|
|
|
|
|
|
.hb-weather.is-sunny .hbw-icon { color: #E8A33D; }
|
|
|
|
|
|
.hb-weather.is-cloud .hbw-icon { color: #7C8AA0; }
|
|
|
|
|
|
.hb-weather.is-rain .hbw-icon { color: #3B7FBF; }
|
|
|
|
|
|
.hb-weather.is-snow .hbw-icon { color: #5AA6B8; }
|
|
|
|
|
|
.hb-weather.is-storm .hbw-icon { color: #7A5BB5; }
|
|
|
|
|
|
.hb-weather.is-fog .hbw-icon { color: #8C8C8C; }
|
|
|
|
|
|
.hbw-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
|
|
|
|
.hbw-temp { font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
|
|
|
|
|
|
.hbw-text { font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.hbw-wind { font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
.hbw-place { grid-column: 2; font-size: 12px; color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② 日程 / 任务 左右各半 ----
|
|
|
|
|
|
⚠️ 高度**固定**(用户原话「为了好看高度需要固定」),滚动条**藏起来**
|
|
|
|
|
|
(「鼠标放上去之后向下可以滚动,暂时不要出现滚动条太丑了」)。
|
2026-10-07 11:35:31 +08:00
|
|
|
|
藏滚动条要三套写法(Firefox / IE-Edge / WebKit 各一套),少一套就在某个浏览器上露出来。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 v24 第 25 批 用户第 3 条修的真 bug:「日程和任务看板,两个模块,
|
|
|
|
|
|
现在有点错位,一个高,一个低,应该完全一样才对。」
|
|
|
|
|
|
|
|
|
|
|
|
根因:这两块原来是 `align-items: start` + 各自内容撑高 ——
|
|
|
|
|
|
左边日程的**刻度行数**由"今天有几件事"决定(掐头去尾之后 3~9 行不等),
|
|
|
|
|
|
右边的任务条数也各不相同 ⇒ 两张卡片高度天然不等,一眼就是"一高一低"。
|
|
|
|
|
|
|
|
|
|
|
|
修法(三步,缺一不可):
|
|
|
|
|
|
① `align-items: stretch` —— 让两栏拉成同一行高(grid 的默认行为,
|
|
|
|
|
|
但上一版显式写成了 `start`,那等于主动放弃对齐);
|
|
|
|
|
|
② `.hd-pane` 给一个**固定总高**并 `display:flex; flex-direction:column`
|
|
|
|
|
|
(它本来就有 flex 列),head 不收缩、body 吃满剩余;
|
|
|
|
|
|
③ `.hd-pane-body` 用 `flex: 1 1 auto` + `min-height: 0`
|
|
|
|
|
|
取代原来的固定 `height: 360px`。
|
|
|
|
|
|
⚠️ `min-height: 0` 不能省:flex 子项的默认 `min-height:auto`
|
|
|
|
|
|
会让它**不肯缩到内容以下**,于是内容一多就把卡片顶高、
|
|
|
|
|
|
对齐又失效(这是"固定高度 + 内部滚动"这套写法的经典坑)。
|
|
|
|
|
|
这样两块的**外框高度恒等**,与各自内容多少无关 —— 对齐不再依赖数据。 */
|
|
|
|
|
|
.home-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: stretch; }
|
|
|
|
|
|
.hd-pane { display: flex; flex-direction: column; height: 440px; min-height: 0; }
|
|
|
|
|
|
.hd-pane-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; flex: 0 0 auto; }
|
2026-10-07 05:52:40 +08:00
|
|
|
|
.hd-pane-head .cinema-h2 { margin: 0; flex: 1 1 auto; }
|
|
|
|
|
|
.hd-pane-body {
|
2026-10-07 11:35:31 +08:00
|
|
|
|
flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
|
2026-10-07 05:52:40 +08:00
|
|
|
|
scrollbar-width: none; /* Firefox */
|
|
|
|
|
|
-ms-overflow-style: none; /* 旧 Edge / IE */
|
|
|
|
|
|
}
|
|
|
|
|
|
.hd-pane-body::-webkit-scrollbar { width: 0; height: 0; } /* Chrome / Safari */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 日程:日视图形式的刻度网格 ----
|
|
|
|
|
|
⚠️ `.ag-row` 的高度就是"一小时"(44px);日程块用**百分比 top** 定位,
|
|
|
|
|
|
所以刻度数与日程块的比例天然一致(都在同一个容器里算)。 */
|
|
|
|
|
|
.ag-allday { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
|
2026-10-07 15:31:26 +08:00
|
|
|
|
/* 🔴 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; }
|
2026-10-07 05:52:40 +08:00
|
|
|
|
.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);
|
|
|
|
|
|
}
|
|
|
|
|
|
.ag-allday-item .ag-ad-t { font-size: 11.5px; color: var(--muted); flex: 0 0 auto; }
|
|
|
|
|
|
.ag-allday-item .ag-ad-w { flex: 1 1 auto; min-width: 0; font-weight: 600; }
|
|
|
|
|
|
.ag-grid { position: relative; }
|
|
|
|
|
|
.ag-row { display: flex; align-items: flex-start; gap: 8px; height: 44px; }
|
|
|
|
|
|
.ag-hour { flex: 0 0 42px; font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; transform: translateY(-6px); }
|
|
|
|
|
|
.ag-line { flex: 1 1 auto; height: 1px; background: var(--line-2); margin-top: 0; }
|
2026-10-12 15:31:03 +08:00
|
|
|
|
/* 当前时刻红线(用户原话「需要在当前的时间或者是时刻那里显示一条红线」)
|
|
|
|
|
|
🔴 v44(用户第 3 条):左端那颗小圆点**删掉**了 ——
|
|
|
|
|
|
用户:「这个红点显示也不全,也不太好看。直接把红点去掉就行了,直接一根红线就可以了。」
|
|
|
|
|
|
⇒ 直接一根 2px 红线;`.ag-now-dot` 这条规则随之删除(不再有那个元素)。 */
|
2026-10-07 05:52:40 +08:00
|
|
|
|
.ag-now { position: absolute; left: 46px; right: 0; height: 0; border-top: 2px solid var(--red); z-index: 2; }
|
|
|
|
|
|
/* 日程块 */
|
2026-10-08 17:41:30 +08:00
|
|
|
|
/* 🔴 v30 第 2 条:「首页上的今天的日程,用色块表示,和日程保持一致。」
|
|
|
|
|
|
⇒ 从原来的"白底卡片 + 左边 3px 色线"改成**与日历页 `.tg-block` 同款的实心色块**:
|
|
|
|
|
|
底色 = 日历本色(内联给)、白字、圆角、无边框阴影。
|
|
|
|
|
|
⚠️ `left` 与 `width` 由**内联样式**给出(冲突分列的结果,见 templates/home.php)——
|
|
|
|
|
|
这里不再写 left/right(绝对定位下 left+right+width 三者同时存在是过约束)。
|
|
|
|
|
|
⚠️ `transform: translateY(2px)` 那点微调去掉了:色块要精确落在刻度上,
|
|
|
|
|
|
偏移 2px 会让"9:00 的块"看起来不在 9:00 那条线上。
|
|
|
|
|
|
⚠️ 白字压浅色本的兜底:加一层极轻的 text-shadow(不加深色罩,保持本色)。 */
|
2026-10-07 05:52:40 +08:00
|
|
|
|
.ag-ev {
|
2026-10-08 17:41:30 +08:00
|
|
|
|
position: absolute; left: 46px; right: 4px;
|
|
|
|
|
|
display: block; overflow: hidden; padding: 3px 7px;
|
|
|
|
|
|
background: var(--brand); border-radius: 4px;
|
|
|
|
|
|
font-size: 12px; line-height: 1.35; color: #fff;
|
|
|
|
|
|
text-decoration: none; box-sizing: border-box;
|
|
|
|
|
|
border: 1px solid rgba(255,255,255,.35);
|
|
|
|
|
|
text-shadow: 0 1px 1px rgba(0,0,0,.18);
|
2026-10-07 05:52:40 +08:00
|
|
|
|
}
|
2026-10-08 17:41:30 +08:00
|
|
|
|
.ag-ev:hover { text-decoration: none; filter: brightness(1.08); z-index: 2; }
|
|
|
|
|
|
.ag-ev .ag-ev-t { display: block; font-weight: 600; font-variant-numeric: tabular-nums; margin-right: 4px; float: left; }
|
|
|
|
|
|
.ag-ev .ag-ev-w { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
|
|
|
|
|
|
/* 日历本名:色块右下角的极淡小字(色块面积小,不加大徽标) */
|
|
|
|
|
|
.ag-ev .ag-ev-cal { display: block; font-size: 10.5px; opacity: .82; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
2026-10-07 05:52:40 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 任务行:标题 + 状态 + **看板名** + 截止 ---- */
|
|
|
|
|
|
.tk-list { display: flex; flex-direction: column; }
|
|
|
|
|
|
.tk-row { align-items: center; }
|
|
|
|
|
|
.tk-board {
|
|
|
|
|
|
flex: 0 0 auto; font-size: 11.5px; color: var(--muted);
|
|
|
|
|
|
background: var(--line-2); border-radius: 999px; padding: 1px 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tk-due { flex: 0 0 auto; font-size: 11.5px; color: var(--faint); }
|
|
|
|
|
|
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* ---- 任务的「完成」复选框(v24 第 25 批 用户第 6 条)----
|
|
|
|
|
|
用户原话:「所有的任务,前面都带一个复选框,在任何地方,点这个复选框,
|
|
|
|
|
|
这个任务就完成了。」
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 它是 `<button>` 不是 `<input type=checkbox>`(见 _task_check.php 的说明):
|
|
|
|
|
|
勾没勾**由服务端状态渲染的 class** 说了算,不是浏览器自己管 checked。
|
|
|
|
|
|
⚠️ 尺寸写死 18px 且 `flex: 0 0 auto`:卡片标题是长文本,
|
|
|
|
|
|
不写死的话它会被 flex 压扁(同一行里"文字优先")。
|
|
|
|
|
|
⚠️ 勾选态用**伪元素画对勾**而不是塞一个 ✓ 字符:
|
|
|
|
|
|
字符在不同字体里基线不同,18px 的方块里会歪。 */
|
|
|
|
|
|
.tk-check {
|
|
|
|
|
|
flex: 0 0 auto; width: 18px; height: 18px; padding: 0; margin: 0;
|
|
|
|
|
|
border: 1.5px solid var(--line); border-radius: 5px; background: #fff;
|
|
|
|
|
|
cursor: pointer; position: relative; transition: border-color .15s, background .15s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tk-check:hover { border-color: var(--brand); }
|
|
|
|
|
|
.tk-check::after {
|
|
|
|
|
|
content: ""; position: absolute; left: 5px; top: 1.5px;
|
|
|
|
|
|
width: 5px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0;
|
|
|
|
|
|
transform: rotate(45deg) scale(0); transition: transform .13s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tk-check.is-done { background: var(--ok, #5E9E4E); border-color: var(--ok, #5E9E4E); }
|
|
|
|
|
|
.tk-check.is-done::after { transform: rotate(45deg) scale(1); }
|
|
|
|
|
|
/* 只读账号:一颗不可点的静态方块 */
|
|
|
|
|
|
.tk-check.is-static { cursor: default; }
|
|
|
|
|
|
.tk-check.is-static:hover { border-color: var(--line); }
|
|
|
|
|
|
/* 已完成的那张卡:标题压灰划掉(一眼看出"这件做完了") */
|
|
|
|
|
|
.kb-card.is-done .kb-title { color: var(--muted); text-decoration: line-through; }
|
|
|
|
|
|
/* ⚠️ 首页/详情那种"一行文字 + 一颗复选框"的场合:
|
|
|
|
|
|
`.dash-row` 是 `align-items: baseline`,而复选框是 18px 的方块 ——
|
|
|
|
|
|
按基线对齐会让它**沉到文字下面半截**(基线是文字的底边,方块没有基线)。
|
|
|
|
|
|
所以带 .tk-check 的行改成 `center`,文字与方块的**中线**对齐,
|
|
|
|
|
|
这才是"复选框在文字前面"该有的样子。
|
|
|
|
|
|
(`.sub-row` 本来就是 center,不用管它。) */
|
|
|
|
|
|
.dash-row:has(.tk-check) { align-items: center; }
|
2026-10-07 15:31:26 +08:00
|
|
|
|
/* ⚠️ v24 第 26 批 用户第 5 条:**详情页页头的复选框已去掉**(那颗由「标记完成」按钮取代),
|
|
|
|
|
|
所以这里原来那条 `.page-head h1:has(> .tk-check)` 一并删除 ——
|
|
|
|
|
|
留一条没有使用者的规则,只会让下一个人以为"页头还该有复选框"。 */
|
2026-10-07 11:35:31 +08:00
|
|
|
|
|
|
|
|
|
|
/* 看板页顶上的「三个状态到底什么意思」(用户第 6 条直接问出来的那句话) */
|
|
|
|
|
|
.tk-legend {
|
|
|
|
|
|
display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center;
|
|
|
|
|
|
margin: 0 0 12px; padding: 9px 12px;
|
|
|
|
|
|
background: var(--surface-2, rgba(0, 0, 0, .02));
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
}
|
|
|
|
|
|
.tk-legend .tk-lg-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; }
|
|
|
|
|
|
.tk-legend .tk-lg-hint { color: var(--muted); }
|
|
|
|
|
|
|
2026-10-07 05:52:40 +08:00
|
|
|
|
/* ---- 窄屏:并排改成上下(各占一半宽度在手机上没法读)---- */
|
|
|
|
|
|
@media (max-width: 760px) {
|
|
|
|
|
|
.home-duo { grid-template-columns: 1fr; }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
/* ⚠️ 窄屏仍要保持**固定高度**(用户要的是"高度固定、内部滚动"),
|
|
|
|
|
|
只是比桌面矮一点。不写成 auto:那样内容一多整页就长得没法用。 */
|
|
|
|
|
|
.hd-pane { height: 320px; }
|
2026-10-07 05:52:40 +08:00
|
|
|
|
.hb-weather { margin-left: 0; padding-left: 0; border-left: 0; padding-top: 10px; border-top: 1px solid var(--line-2); width: 100%; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 24 批 用户第 4 条:个人导航**管理页**样式
|
|
|
|
|
|
(展示页样式在 assets/css/nav-show.css —— 那份是从 SimpleNav 整份搬来的,
|
|
|
|
|
|
这里只管登录后的管理界面,所以用家书自己的视觉语言。)
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.nav-grp-block { margin-bottom: 14px; }
|
|
|
|
|
|
.nav-sub { font-size: 13.5px; margin: 10px 0 6px; color: var(--muted); }
|
|
|
|
|
|
.nav-sortlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.nav-sortrow {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 7px 10px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 隐藏中的条目淡一点,一眼能看出"它还在、只是不显示" */
|
|
|
|
|
|
.nav-sortrow.is-off { opacity: .55; }
|
|
|
|
|
|
.nav-sortrow.is-dragging { box-shadow: var(--shadow-l); border-color: var(--brand-2); }
|
|
|
|
|
|
.nav-drag {
|
|
|
|
|
|
flex: 0 0 auto; cursor: grab; color: var(--faint); font-size: 13px;
|
|
|
|
|
|
letter-spacing: -1px; user-select: none; padding: 0 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav-drag:active { cursor: grabbing; }
|
|
|
|
|
|
.nav-ico {
|
|
|
|
|
|
flex: 0 0 auto; width: 20px; height: 20px; border-radius: 5px; object-fit: contain;
|
|
|
|
|
|
border: 1px solid var(--line-2); background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav-ico-letter {
|
|
|
|
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
|
|
|
|
color: #fff; font-size: 11px; border: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nav-sname { flex: 0 0 auto; font-size: 13.5px; font-weight: 600; }
|
|
|
|
|
|
.nav-surl { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.nav-acts { margin-left: auto; display: inline-flex; gap: 6px; flex-wrap: wrap; }
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.nav-acts { margin-left: 0; width: 100%; }
|
|
|
|
|
|
.nav-surl { display: none; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v24 第 24 批 用户第 5 条:微信读书导入页(书清单 + 样章)
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
.wr-list { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 14px; }
|
|
|
|
|
|
.wr-book {
|
|
|
|
|
|
display: flex; align-items: flex-start; gap: 10px;
|
|
|
|
|
|
padding: 9px 12px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFBF7; cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.wr-book:hover { border-color: var(--brand-2); }
|
|
|
|
|
|
.wr-book > input[type=checkbox] { margin-top: 3px; flex: 0 0 auto; accent-color: var(--brand); }
|
|
|
|
|
|
.wr-main { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.wr-title { font-size: 14px; font-weight: 600; }
|
|
|
|
|
|
/* 样章:原文用斜体、想法用普通体 —— 与读书详情页里笔记的排法一致 */
|
|
|
|
|
|
.wr-sample { flex: 1 1 100%; display: flex; flex-direction: column; gap: 2px; margin-left: 22px; }
|
|
|
|
|
|
.wr-q { font-size: 12.5px; color: var(--muted); line-height: 1.6; }
|
|
|
|
|
|
.wr-q i { font-style: normal; color: var(--ink); }
|
|
|
|
|
|
.wr-q em { font-style: normal; color: var(--brand-ink); }
|
|
|
|
|
|
.wr-q em::before { content: '💭 '; }
|
2026-10-07 11:35:31 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 微信读书:封面(v24 第 25 批 用户第 8 条「封面图看不到」)----
|
|
|
|
|
|
⚠️ 尺寸必须写死(52×74 ≈ 2:3,与 bookcover 槽位的裁剪比例一致):
|
|
|
|
|
|
不写死的话,官方封面各尺寸不一,一行里高低参差(这正是"看起来乱"的原因)。
|
|
|
|
|
|
⚠️ `object-fit: cover` + 固定高宽:封面比例不一时居中裁,不拉伸变形。 */
|
|
|
|
|
|
.wr-cv {
|
|
|
|
|
|
flex: 0 0 auto; width: 52px; height: 74px; border-radius: 6px;
|
|
|
|
|
|
object-fit: cover; background: var(--line-2);
|
|
|
|
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, .10);
|
|
|
|
|
|
}
|
|
|
|
|
|
.wr-cv-ph {
|
|
|
|
|
|
display: flex; align-items: center; justify-content: center; font-size: 22px;
|
|
|
|
|
|
color: var(--faint); box-shadow: none; border: 1px dashed var(--line);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 外链封面(统计块里的「读得最多的书」,直接来自官方 CDN,本站不下载) */
|
|
|
|
|
|
.wr-top-cv {
|
|
|
|
|
|
flex: 0 0 auto; width: 34px; height: 48px; border-radius: 5px;
|
|
|
|
|
|
object-fit: cover; background: var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.wr-top-ph { display: flex; align-items: center; justify-content: center; color: var(--faint); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 自动同步(用户第 8 条)---- */
|
|
|
|
|
|
.wr-sync { display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 13px; }
|
|
|
|
|
|
.wr-sync-item { color: var(--muted); }
|
|
|
|
|
|
.wr-sync-item b { color: var(--ink); font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 阅读统计(用户第 8 条)----
|
|
|
|
|
|
一排数字卡。⚠️ `flex: 0 1 auto` + `min-width` 而不是等宽:
|
|
|
|
|
|
指标个数(时长/天数/日均/读过/读完/笔记)随官方返回而变,
|
|
|
|
|
|
写死等宽会在某个指标缺失时留一块空。 */
|
|
|
|
|
|
.wr-stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 2px 0 4px; }
|
|
|
|
|
|
.wr-stat {
|
|
|
|
|
|
flex: 0 1 auto; min-width: 108px; padding: 10px 14px;
|
|
|
|
|
|
background: var(--line-2); border-radius: var(--radius-s);
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.wr-stat b { font-size: 17px; color: var(--ink); font-weight: 600; }
|
|
|
|
|
|
.wr-stat span { font-size: 12px; color: var(--muted); }
|
|
|
|
|
|
.wr-sub { margin: 18px 0 8px; font-size: 14px; font-weight: 600; color: var(--ink); }
|
|
|
|
|
|
/* 读得最多的书 */
|
|
|
|
|
|
.wr-top { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.wr-top-item { display: flex; align-items: center; gap: 10px; }
|
|
|
|
|
|
.wr-top-b { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
|
|
|
|
|
|
.wr-top-t { font-size: 13.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.wr-top-time { flex: 0 0 auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
/* 偏好分类:名称 + 条 + 数值 */
|
|
|
|
|
|
.wr-cats { display: flex; flex-direction: column; gap: 6px; }
|
|
|
|
|
|
.wr-cat { display: flex; align-items: center; gap: 10px; font-size: 13px; }
|
|
|
|
|
|
.wr-cat-n { flex: 0 0 84px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.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; }
|
2026-10-07 15:31:26 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
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; }
|
2026-10-07 18:22:55 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v27 个人笔记(用户 2026-10-07)
|
|
|
|
|
|
参考 flomo(时间流卡片 + 标签)/ Obsidian(图文混排的直觉)/ 思源(分块),
|
|
|
|
|
|
但一律取**轻**的那一层:块只有 段落/图片/清单,不做块引用、不做富文本。
|
|
|
|
|
|
配色沿用宣纸米 + 砖红,不引入第三套色。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 列表页:左标签云 + 右卡片流 ---- */
|
|
|
|
|
|
.note-layout { display: grid; grid-template-columns: 220px 1fr; gap: 16px; align-items: start; }
|
|
|
|
|
|
.note-side { position: sticky; top: 16px; }
|
|
|
|
|
|
.note-main { min-width: 0; }
|
|
|
|
|
|
.note-search-card { margin-bottom: 12px; }
|
|
|
|
|
|
.note-search-card .search { margin: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
.note-tags { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
|
|
|
|
.note-tag {
|
|
|
|
|
|
display: inline-flex; align-items: center; gap: 5px;
|
|
|
|
|
|
padding: 4px 9px; border-radius: 999px; cursor: pointer;
|
|
|
|
|
|
border: 1px solid var(--line); background: #fff;
|
|
|
|
|
|
font-size: 12.5px; color: var(--muted); text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-tag:hover { border-color: var(--brand-2); color: var(--brand-ink); text-decoration: none; }
|
|
|
|
|
|
.note-tag.is-on { border-color: var(--brand); color: var(--brand-ink); background: var(--brand-soft, #FDF3EC); }
|
|
|
|
|
|
.note-tag b { font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.note-tag.is-on b { color: var(--brand-ink); }
|
|
|
|
|
|
.note-tags-inline { margin-top: 10px; }
|
|
|
|
|
|
.note-tags-suggest { margin-top: 8px; align-items: center; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 卡片 ---- */
|
|
|
|
|
|
.note-card { margin-bottom: 12px; }
|
|
|
|
|
|
.note-head { display: flex; align-items: center; gap: 8px; }
|
|
|
|
|
|
.note-meta { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.note-ava { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
|
|
|
|
|
|
.note-who { font-size: 13px; color: var(--ink); font-weight: 500; }
|
|
|
|
|
|
.note-time { font-size: 12px; color: var(--faint); margin-left: auto; padding-right: 4px; }
|
|
|
|
|
|
/* 共享/私有标记:一眼分清"这是我写给自己看的"还是"全家都能看的" */
|
|
|
|
|
|
.note-share, .note-private {
|
|
|
|
|
|
font-size: 11px; padding: 1px 7px; border-radius: 999px; flex: 0 0 auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-share { color: #2F6B4F; background: #E7F2EC; }
|
|
|
|
|
|
.note-private { color: var(--faint); background: var(--line-2); }
|
|
|
|
|
|
.note-ops { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
|
|
|
|
|
|
.note-ops .inline-form { display: inline; }
|
|
|
|
|
|
|
|
|
|
|
|
.note-title { margin: 10px 0 6px; font-size: 16px; font-weight: 600; color: var(--ink); }
|
|
|
|
|
|
.note-body { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.note-text { margin: 0; font-size: 14.5px; line-height: 1.7; color: var(--ink); white-space: pre-wrap; }
|
|
|
|
|
|
.note-list { margin: 0; padding-left: 20px; font-size: 14.5px; line-height: 1.7; color: var(--ink); }
|
|
|
|
|
|
.note-list li { margin: 2px 0; }
|
|
|
|
|
|
/* 图片:等比缩到卡片宽,圆角与卡片一致;点开走全站预览层(data-prev) */
|
|
|
|
|
|
.note-img { display: block; }
|
|
|
|
|
|
.note-img img {
|
|
|
|
|
|
max-width: 100%; max-height: 420px; border-radius: var(--radius-s);
|
|
|
|
|
|
border: 1px solid var(--line); display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-more { text-align: center; margin: 16px 0 8px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 编辑页:分块 ---- */
|
|
|
|
|
|
.note-form .card { margin-bottom: 12px; }
|
|
|
|
|
|
.note-block-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
|
|
|
|
|
|
.note-block-head .cinema-h2 { margin: 0; flex: 1 1 auto; }
|
|
|
|
|
|
.note-add { display: flex; gap: 6px; flex: 0 0 auto; }
|
|
|
|
|
|
.note-blocks { display: flex; flex-direction: column; gap: 8px; }
|
|
|
|
|
|
.note-block {
|
|
|
|
|
|
display: flex; gap: 8px; align-items: flex-start;
|
|
|
|
|
|
border: 1px dashed var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
padding: 8px; background: #FDFCFA;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-block:focus-within { border-color: var(--brand-2); border-style: solid; }
|
|
|
|
|
|
.note-block-ops { display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; }
|
|
|
|
|
|
.nb-btn {
|
|
|
|
|
|
width: 24px; height: 22px; line-height: 1; padding: 0;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 5px; background: #fff;
|
|
|
|
|
|
color: var(--muted); cursor: pointer; font-size: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nb-btn:hover { border-color: var(--brand-2); color: var(--brand-ink); }
|
|
|
|
|
|
.nb-del:hover { border-color: var(--red); color: var(--red); }
|
|
|
|
|
|
.note-block-body { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.note-block-ta { width: 100%; resize: vertical; font-size: 14.5px; line-height: 1.7; }
|
|
|
|
|
|
.note-block-img {
|
|
|
|
|
|
max-width: 100%; max-height: 320px; border-radius: var(--radius-s);
|
|
|
|
|
|
border: 1px solid var(--line); display: block; margin-bottom: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 还没选图时:不要显示破图框(那是 <img src=""> 的默认表现,很难看) */
|
|
|
|
|
|
.note-block-img.is-empty { display: none; }
|
|
|
|
|
|
.note-img-pick {
|
|
|
|
|
|
padding: 4px 10px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #fff; color: var(--muted); cursor: pointer; font-size: 12.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-img-pick:hover { border-color: var(--brand-2); color: var(--brand-ink); }
|
|
|
|
|
|
.note-share-toggle {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px; margin-top: 12px;
|
|
|
|
|
|
font-size: 13.5px; color: var(--muted); cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-share-toggle input { width: 16px; height: 16px; accent-color: var(--brand); }
|
|
|
|
|
|
.note-actions { display: flex; gap: 8px; margin: 4px 0 20px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 窄屏:标签云折到上面,卡片满宽 ---- */
|
|
|
|
|
|
@media (max-width: 760px) {
|
|
|
|
|
|
.note-layout { grid-template-columns: 1fr; }
|
|
|
|
|
|
.note-side { position: static; }
|
|
|
|
|
|
.note-side .card { margin-bottom: 12px; }
|
|
|
|
|
|
/* 长英文/URL 不要把卡片撑出横向滚动(全站反复栽在这条上) */
|
|
|
|
|
|
.note-text, .note-list, .note-title { overflow-wrap: anywhere; }
|
|
|
|
|
|
}
|
2026-10-08 02:20:19 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
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; }
|
|
|
|
|
|
|
2026-10-08 10:54:43 +08:00
|
|
|
|
/* ---- 平铺列表:**仍然单列**(只是不再有"栏"的分隔线)----
|
|
|
|
|
|
🔴🔴 v29 用户第 3 条:「名册页面完全错乱」—— 这个 bug 是 v28 **我自己引入的**。
|
|
|
|
|
|
v28 我把这里写成了多列 grid(`repeat(auto-fill, minmax(320px,1fr))`),
|
|
|
|
|
|
真实后果有两个,都实测到了:
|
|
|
|
|
|
① 卡片上有 `content-visibility: auto` + `contain-intrinsic-size: auto 68px`
|
|
|
|
|
|
(v24 为"千人名册不卡死"加的)。它在**单列流**里是安全的,
|
|
|
|
|
|
一旦卡片变成 grid item,屏外卡片的"估算高度"与网格轨道互相打架,
|
|
|
|
|
|
布局当场乱掉;
|
|
|
|
|
|
② 每列只剩 ~339px(1280 宽 ÷ 3),而卡片里是
|
|
|
|
|
|
[拖柄][头像 52px + 姓名/徽标][标签+编辑+删除 三个按钮 ≈213px] ——
|
|
|
|
|
|
实测 `person-main` 只分到 **106px**(含 52px 头像 → 姓名区仅 42px),
|
|
|
|
|
|
姓名、徽标全被挤碎,动作区还会折行。
|
|
|
|
|
|
⇒ 修法:**回到单列**(`.people-grid` 本来就是单列 flex,见文件上方 328 行),
|
|
|
|
|
|
把 v28 那条 grid 规则整个删掉。名册人数从 3 到 1000+ 都是单列,
|
|
|
|
|
|
与"分栏时代每一栏的卡片"同宽 —— 那才是这套卡片的原始设计宽度。
|
|
|
|
|
|
⚠️ 别再用"多列网格"来塞名册卡片:它的内容是**横向三段式**的,
|
|
|
|
|
|
天生吃宽度;窄了就一定碎。 */
|
2026-10-08 02:20:19 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- 🔴 用户第 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); }
|
2026-10-08 10:54:43 +08:00
|
|
|
|
/* 🔴 v29 第 6 条:「笔记,首页显示的时候,里面的图片,和行程的类似,
|
|
|
|
|
|
把图片按照比例缩放到固定的高度或者宽度,放在下面就行了。」
|
|
|
|
|
|
⇒ 固定高度 + **等比完整显示**(contain),不再 cover 裁切。
|
|
|
|
|
|
⚠️ 从 cover 改 contain 是有意的取舍:
|
|
|
|
|
|
cover 能让每张图铺满、看着"实",但**看不到完整内容**(横图两端被切掉)——
|
|
|
|
|
|
用户要的是"按比例缩小放在下面",那就是要看到**整张**。
|
|
|
|
|
|
代价是宽高比与格子不一致时两侧留浅底,所以给个底色让留白显得是有意的。 */
|
2026-10-08 02:20:19 +08:00
|
|
|
|
.note-thumb img {
|
2026-10-08 10:54:43 +08:00
|
|
|
|
width: 100%; height: 110px; object-fit: contain; display: block;
|
|
|
|
|
|
background: #F6F4F0;
|
2026-10-08 02:20:19 +08:00
|
|
|
|
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; }
|
|
|
|
|
|
}
|
2026-10-08 10:54:43 +08:00
|
|
|
|
/* 🔴 v29 第 3 条(窄屏半边):360px 下卡片只有 328px,
|
|
|
|
|
|
[拖柄 24][头像 52 + 姓名][标签+编辑+删除 ≈197] 硬塞在一行 → 姓名区只剩 ~40px。
|
|
|
|
|
|
⇒ 窄屏把动作区**整体折到第二行**(卡片改纵向),姓名那一行就宽裕了。
|
|
|
|
|
|
用 flex-direction: column 而不是给动作区定宽:后者的宽度随标签数变化,
|
|
|
|
|
|
定了也会被长标签顶开(v28 就是这么栽的)。 */
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
.person { flex-wrap: wrap; }
|
|
|
|
|
|
.person .person-main { flex: 1 1 calc(100% - 40px); }
|
|
|
|
|
|
.person-actions {
|
|
|
|
|
|
flex: 1 1 100%; justify-content: flex-start;
|
|
|
|
|
|
padding: 0 10px 10px 34px; /* 左边缩进到与姓名对齐(躲开拖柄) */
|
|
|
|
|
|
}
|
|
|
|
|
|
.person-tag-btn { max-width: 46vw; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
v29 用户第 7 / 8 / 9 条:笔记 —— 阅读态 / 工具条 / 斜线命令 / 图片调大小
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 阅读态(第 8 条:点进来默认是"看")----
|
|
|
|
|
|
与编辑态的区别要**一眼看得出**:没有虚线框、没有按钮,就是一篇排好版的文档。 */
|
2026-10-14 01:20:40 +08:00
|
|
|
|
/* 🔴 v47(用户 2026-10-13):「标题和内容这个块的宽度并没有撑满整个页面,
|
|
|
|
|
|
它和下面那个共享给谁、还有权限那一块,宽度是不一致的。」
|
|
|
|
|
|
⇒ 原来这里写着 `max-width: 820px`,而下面的「共享」卡是满宽的 ⇒ 上下两块对不齐。
|
|
|
|
|
|
⚠️ 不要改成"给共享卡也加 820px":用户要的是**撑满**,不是一起变窄;
|
|
|
|
|
|
正文卡与其它页面的 .card 保持同宽,视觉上才是一列。
|
|
|
|
|
|
⇒ 直接放开限宽(.card 本身已有全页统一的内边距与最大宽度约束)。 */
|
|
|
|
|
|
.note-read { max-width: none; }
|
2026-10-08 10:54:43 +08:00
|
|
|
|
.note-read-title { margin: 0 0 6px; font-size: 22px; font-weight: 600; color: var(--ink); }
|
|
|
|
|
|
.note-read-tags { margin: 0 0 14px; }
|
|
|
|
|
|
.note-read-body { display: flex; flex-direction: column; gap: 14px; }
|
|
|
|
|
|
.note-read-block { font-size: 15px; line-height: 1.8; color: var(--ink); }
|
|
|
|
|
|
/* 图片:默认满宽,可调(内联 style 给百分比);圆角与卡片一致 */
|
|
|
|
|
|
.note-read-fig { margin: 0; }
|
|
|
|
|
|
.note-read-fig img {
|
|
|
|
|
|
max-width: 100%; height: auto; display: block;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-read-fig a { display: inline-block; max-width: 100%; }
|
|
|
|
|
|
.note-read-h2 {
|
|
|
|
|
|
margin: 0 0 8px; font-size: 14px; font-weight: 600; color: var(--muted);
|
|
|
|
|
|
letter-spacing: .5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 附件区:一条细线把它与正文分开("在最下方"要看得出来是**另一块**) */
|
|
|
|
|
|
.note-read-files { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--line-2); }
|
|
|
|
|
|
.note-read .note-share-now { margin-top: 16px; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 编辑态:Markdown 工具条(第 7 条"要么有工具条")---- */
|
|
|
|
|
|
.note-cmdbar {
|
|
|
|
|
|
display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
|
|
|
|
|
|
padding: 6px 8px; margin-bottom: 8px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: #FDFCFA;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-cmdbar .cmd {
|
|
|
|
|
|
min-width: 28px; height: 26px; padding: 0 7px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: 5px; background: #fff;
|
|
|
|
|
|
color: var(--ink); cursor: pointer; font-size: 13px; line-height: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-cmdbar .cmd:hover { border-color: var(--brand-2); color: var(--brand-ink); background: var(--brand-soft, #FDF3EC); }
|
|
|
|
|
|
.note-cmdbar .cmd-sep { width: 1px; height: 18px; background: var(--line); margin: 0 4px; }
|
|
|
|
|
|
.note-cmdbar .note-live { margin-left: auto; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 斜线命令菜单(第 7 条"要么有代码提示")----
|
|
|
|
|
|
⚠️ 绝对定位在**块内**(不是 body):跟着块走,块删除/移动时不会留孤儿菜单。 */
|
|
|
|
|
|
.note-block-body { position: relative; }
|
|
|
|
|
|
.slash-menu {
|
|
|
|
|
|
position: absolute; left: 0; top: 100%; z-index: 30; display: none;
|
|
|
|
|
|
min-width: 190px; max-height: 220px; overflow-y: auto;
|
|
|
|
|
|
background: #fff; border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
box-shadow: var(--shadow); padding: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.slash-menu.is-on { display: block; }
|
|
|
|
|
|
.slash-item {
|
|
|
|
|
|
display: flex; align-items: baseline; gap: 8px; width: 100%;
|
|
|
|
|
|
padding: 5px 8px; border: 0; border-radius: 5px; background: transparent;
|
|
|
|
|
|
cursor: pointer; text-align: left; font-size: 13px; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
.slash-item b { color: var(--brand); font-family: ui-monospace, Consolas, monospace; }
|
|
|
|
|
|
.slash-item span { color: var(--muted); font-size: 12px; }
|
|
|
|
|
|
.slash-item:hover, .slash-item.is-on { background: var(--brand-soft, #FDF3EC); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 图片块:尺寸档位(第 8 条"图文混排时,需要可以调整大小")---- */
|
|
|
|
|
|
.note-img-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
|
|
|
|
.note-img-sizes { display: inline-flex; gap: 3px; margin-left: auto; }
|
|
|
|
|
|
.note-img-size {
|
|
|
|
|
|
padding: 2px 7px; border: 1px solid var(--line); border-radius: 5px;
|
|
|
|
|
|
background: #fff; color: var(--muted); cursor: pointer; font-size: 11.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.note-img-size:hover { border-color: var(--brand-2); color: var(--brand-ink); }
|
|
|
|
|
|
.note-img-size.is-on { border-color: var(--brand); background: var(--brand-soft, #FDF3EC); color: var(--brand-ink); }
|
|
|
|
|
|
/* 图上标着当前档位,编辑器里一眼能看出"这张被缩过了" */
|
|
|
|
|
|
.note-block[data-kind="image"] .note-block-img { transition: width .12s ease; }
|
2026-10-08 17:41:30 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
通知消息(v30 第 5 条)
|
|
|
|
|
|
------------------------------------------------------------
|
|
|
|
|
|
用户原话:「引入通知模块,这个模块,不在导航显示,在个人头像点击那里显示,
|
|
|
|
|
|
放在个人设置前面,名字:通知消息。」
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 三处共用这一套样式:头像下拉里的入口、?r=notifications 页、首页那一块。
|
|
|
|
|
|
分开写三遍迟早长歪(本项目在"设置下拉"上刚吃过这个亏)。
|
|
|
|
|
|
⚠️ 未读用**左侧一条品牌色竖线 + 浅底**表达,不用加粗字重 ——
|
|
|
|
|
|
字重变化会让整行宽度轻微跳动,一列通知看下来眼睛累。
|
|
|
|
|
|
============================================================ */
|
|
|
|
|
|
/* 头像下拉里的入口:文案 + 未读角标(角标推到最右) */
|
|
|
|
|
|
.menu-list a:has(.menu-badge),
|
|
|
|
|
|
.menu-list a .menu-badge {
|
|
|
|
|
|
display: inline-flex; align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.menu-list a .menu-badge {
|
|
|
|
|
|
margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px;
|
|
|
|
|
|
border-radius: 999px; background: var(--red); color: #fff;
|
|
|
|
|
|
font-size: 11px; line-height: 18px; justify-content: center; font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ntf-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
|
|
|
|
.ntf-row {
|
|
|
|
|
|
display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
padding: 8px 10px; border-radius: var(--radius-s);
|
|
|
|
|
|
border-left: 3px solid transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ntf-row:hover { background: var(--line-2); }
|
|
|
|
|
|
/* 未读:左侧品牌色竖线 + 极浅底(见上面的说明:不用字重) */
|
|
|
|
|
|
.ntf-row.is-unread { border-left-color: var(--brand); background: var(--brand-soft, #FDF6F1); }
|
|
|
|
|
|
.ntf-av {
|
|
|
|
|
|
flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
|
|
|
|
|
|
object-fit: cover; background: var(--line-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
.ntf-main {
|
|
|
|
|
|
flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 10px;
|
|
|
|
|
|
color: var(--ink); text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ntf-main:hover { text-decoration: none; color: var(--brand); }
|
|
|
|
|
|
.ntf-title { flex: 1 1 auto; min-width: 0; font-size: 14px; overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.ntf-title b { font-weight: 600; margin-right: 2px; }
|
|
|
|
|
|
.ntf-time { flex: 0 0 auto; font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
|
|
|
|
|
|
.ntf-kind { flex: 0 0 auto; font-size: 15px; line-height: 1; }
|
|
|
|
|
|
.ntf-del { flex: 0 0 auto; }
|
|
|
|
|
|
/* 首页那块:行距紧一点(它只是"瞥一眼",不是消息中心) */
|
|
|
|
|
|
.ntf-list-home .ntf-row { padding: 6px 8px; }
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
/* 窄屏把时间挪到下一行,别把标题挤成两三个字 */
|
|
|
|
|
|
.ntf-main { flex-wrap: wrap; gap: 2px 10px; }
|
|
|
|
|
|
.ntf-title { flex: 1 1 100%; }
|
|
|
|
|
|
}
|
2026-10-10 00:26:42 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
v37(2026-10-09) —— 弹框:按钮位置 / 标签加粗 / 观影弹框宽度
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
用户原话(4 条,都指向"弹框"):
|
|
|
|
|
|
⑤「日程模块的新建日程里,弹出一个对话框。但是"加上"和"取消"两个按钮在
|
|
|
|
|
|
右上角,离得特别远,根本看不到。应该把它们放在下方,或者放在"新建日程"
|
|
|
|
|
|
标题的右侧,不要放那么远。
|
|
|
|
|
|
另外,每个输入框前面的标题都太小了…比如"放在哪本""标题""地点""提醒"这些,
|
|
|
|
|
|
都应该加粗、变大,这样跟里面的内容产生一些差异,看起来更醒目一些。」
|
|
|
|
|
|
⑥「新建任务也和新建日程一样,新建时弹出一个框…」
|
|
|
|
|
|
============================================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* 🔴🔴 日程弹框"按钮跑到右上角、还根本看不到"的真根因(实测定位,不是猜):
|
|
|
|
|
|
`.cal-modal-panel` 是 flex 列(head / form / foot 三段),但**它下面的 <form>
|
|
|
|
|
|
不是** —— form 是块级元素,`cal-modal-body{flex:1 1 auto}` 的 flex 上下文
|
|
|
|
|
|
只到 form 为止。于是 form 的高度 = head + 内容**全部**高度,而面板 `max-height`
|
|
|
|
|
|
又把外层卡住 ⇒ foot 被挤出面板可视区,出现在**面板底部之外**,
|
|
|
|
|
|
而面板本身不滚(滚的是 body)→ 用户看到的就是"按钮飘在很远的地方 / 看不见"。
|
|
|
|
|
|
⇒ 让 form 也参与那个 flex 列、body 才能真正被压缩到可滚动。 */
|
|
|
|
|
|
.cal-modal-panel > form {
|
|
|
|
|
|
display: flex; flex-direction: column;
|
|
|
|
|
|
flex: 1 1 auto; min-height: 0;
|
|
|
|
|
|
overflow: hidden; /* 圆角裁切:body 滚动时不要顶出面板 */
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ v37 起"加上"主键改用 `form="calAddForm"` 关联 ——
|
|
|
|
|
|
它不再长在 form 内部,`:not()` 那条老规则会失效,这里按 id 补回。 */
|
|
|
|
|
|
.cal-modal-foot .btn[type="submit"],
|
|
|
|
|
|
.cal-modal-foot #calAddSubmit { margin-left: auto; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 弹框里的字段标签:加粗、变大、深色 ----
|
|
|
|
|
|
用户原话:「每个输入框前面的标题都太小了…都应该加粗、变大,这样跟里面的内容
|
|
|
|
|
|
产生一些差异,看起来更醒目一些。」
|
|
|
|
|
|
⚠️ 只改**弹框里**的(.cal-modal / .pp-modal 等浮层面板内):
|
|
|
|
|
|
页面内的普通表单标签维持原样,避免"改一处动了全站"。
|
|
|
|
|
|
⚠️ 用 `.cal-modal .field > label` 而不是 `.cal-modal label`:
|
|
|
|
|
|
后者会连"提醒"那排 checkbox 的每个小标签一起加粗,看起来一片糊。 */
|
|
|
|
|
|
.cal-modal .field > label,
|
|
|
|
|
|
.cal-modal .field > .dt-range-label,
|
|
|
|
|
|
.cn-panel .field > label,
|
|
|
|
|
|
.pp-modal .field > label {
|
|
|
|
|
|
font-size: 14px; font-weight: 600; color: var(--ink);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 观影"记一场电影"弹框 ----
|
|
|
|
|
|
⚠️ 字段比日程多得多(海报 + 观影照片 + 简介 + 同行人…),620px 太窄了,
|
|
|
|
|
|
用 760px 让两列字段摆得开;高度放到 88vh,长表单才有足够的可视区。 */
|
|
|
|
|
|
.cal-modal-panel.mv-panel { width: min(760px, 100%); max-height: calc(100vh - 64px); }
|
|
|
|
|
|
.mv-form-inner { padding: 16px; } /* 弹框里的内边距(编辑态用的是 .card-pad) */
|
|
|
|
|
|
/* 弹框形态下,页面上那条"记下这场电影 / 取消"一整行是多余的(foot 里已有),
|
|
|
|
|
|
但它在**编辑态**必须留着 —— JS 没跑时它是唯一的提交入口。 */
|
|
|
|
|
|
.mv-foot-inner { display: none; }
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
.cal-modal-panel.mv-panel { width: 100%; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 窄屏:弹框字段全部单列(form-grid 是两列,手机上会把标签挤成两个字) ---- */
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.cal-modal .form-grid { grid-template-columns: 1fr; }
|
|
|
|
|
|
}
|
2026-10-10 11:01:22 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
v38(2026-10-10) 观影"记一场电影"弹框:标签内联排版 + Ant Design 日期控件
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
用户原话(两条,一起改的):
|
|
|
|
|
|
「记录一场电影,这个弹框因为标题和下面的输入框都是两行的,所以导致弹框非常长。
|
|
|
|
|
|
能不能排排版,让前面的标题后面加个冒号,后面的输入框直接跟在它后面,
|
|
|
|
|
|
这样就变成一行。包括开始、结束时间、影院、同行的人、简介等等,能把它排成
|
|
|
|
|
|
一行的都排成一行,但是一定要注意对齐的问题,如果不对齐的话可能不好看。」
|
|
|
|
|
|
「我终于找到了一个我比较认可的日期选择插件
|
|
|
|
|
|
https://ant-design.antgroup.com/components/date-picker-cn 现在观影这个模块
|
|
|
|
|
|
进行测试吧…等这个模块测试完没问题了,再更新到其他的模块。」
|
|
|
|
|
|
============================================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 「标签:控件」内联网格 ----
|
|
|
|
|
|
🔴 对齐靠的是**固定宽度的标签列**(62px + 右对齐),不是靠调间距 ——
|
|
|
|
|
|
标签长短差很多(片名/时间/影院/同行的人),但它们冒号后的控件左缘
|
|
|
|
|
|
必须落在同一条竖线上,看起来才整齐。
|
|
|
|
|
|
⚠️ 标签**自带冒号**(CSS 的 ::after 给)—— 让每个模板都手写":"迟早漏一个。
|
|
|
|
|
|
⚠️ `> .mv-lb` 而**不是** `.mv-row label`:后者会把同行人那排 checkbox 的
|
|
|
|
|
|
小标签一起卷进来(它们不是"字段标签")。 */
|
|
|
|
|
|
.mv-grid { display: flex; flex-direction: column; gap: 12px; }
|
|
|
|
|
|
.mv-row { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
|
|
|
|
|
|
.mv-row > .mv-lb {
|
|
|
|
|
|
flex: 0 0 62px; width: 62px; /* 固定宽 = 对齐的基准 */
|
|
|
|
|
|
text-align: right; padding-top: 9px; /* 与 40px 高输入框的文字基线对齐 */
|
|
|
|
|
|
font-size: 14px; font-weight: 600; color: var(--ink);
|
|
|
|
|
|
line-height: 1.4; word-break: keep-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mv-row > .mv-lb::after { content: ':'; font-weight: 400; color: var(--muted); }
|
|
|
|
|
|
/* 必填星号:跟在标签文字后、冒号前 */
|
|
|
|
|
|
.mv-row > .mv-lb > i { font-style: normal; color: var(--red, #C0392B); margin-left: 1px; }
|
|
|
|
|
|
/* 控件区:占满剩余宽度(min-width:0 让它能被压缩,不会把标签挤出去) */
|
|
|
|
|
|
.mv-row > *:not(.mv-lb) { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
/* 片名那一行:输入框 + 「自动获取」按钮并排 */
|
|
|
|
|
|
.mv-row .db-title-row { display: flex; gap: 8px; align-items: center; }
|
|
|
|
|
|
.mv-row .db-title-row .input { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.mv-row .db-title-row .btn { flex: 0 0 auto; }
|
|
|
|
|
|
/* 影院那一行:自定义下拉 + 「新建影院」并排 */
|
|
|
|
|
|
.mv-row .cinema-select-row { display: flex; gap: 8px; align-items: center; }
|
|
|
|
|
|
.mv-row .cinema-select-row .cs { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 时间那一行是 `.mv-row.dt-range`:它既是"标签+控件"的行,又是**范围组**。
|
|
|
|
|
|
⚠️ 这两重身份会打架:`.dt-range.dt-cols` 是 `flex-direction: row`,
|
|
|
|
|
|
会把标签也当成"一个端点"排进去。⇒ 这里把它拉回"标签一行、两端在下",
|
|
|
|
|
|
标签仍占固定 62px(与上面的字段对齐)。 */
|
|
|
|
|
|
.mv-row.dt-range.dt-cols { flex-direction: row; flex-wrap: wrap; align-items: flex-start; }
|
|
|
|
|
|
.mv-row.dt-range.dt-cols > .dt-range-label { flex: 0 0 62px; width: 62px; }
|
|
|
|
|
|
/* 🔴 v38 对齐修正(真机量出来的 8px 偏差):
|
|
|
|
|
|
`.dt-cols` 是 `gap: 10px 18px`(行距 10 / **列距 18**),而普通 `.mv-row`
|
|
|
|
|
|
只有 `gap: 10px`。于是"标签 → 控件"这段在时间行是 18px、在别的行是 10px
|
|
|
|
|
|
⇒ 控件左缘差了 8px(实测 452 vs 444),一眼就看得出没对齐。
|
|
|
|
|
|
⇒ 时间行的列距拉回 10px,与别的行一致。 */
|
|
|
|
|
|
.mv-row.dt-range.dt-cols { column-gap: 10px; }
|
|
|
|
|
|
/* 两端并排(沿用 v37 的 .dt-cols 规则),并**从标签右边开始** */
|
|
|
|
|
|
.mv-row.dt-range.dt-cols > .dt-input {
|
|
|
|
|
|
flex: 1 1 0; min-width: 220px; margin-top: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mv-row.dt-range .err { flex: 1 1 100%; margin-left: 72px; }
|
|
|
|
|
|
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* 海报 / 观影照片:**与简介同一套 `.mv-row`**(标签在左、内容在右)。
|
|
|
|
|
|
🔴🔴 v39(用户 2026-10-10):「海报和观影照片为什么和上面的标题不一样呢?
|
|
|
|
|
|
海报的字体和简介是一样的,也带一个冒号。然后把后面点击或拖动进行上传往后放,
|
|
|
|
|
|
和简介后面的输入框保持一样大小。观影照片…也是加粗。和简介的字体保持一致,
|
|
|
|
|
|
不带冒号。]
|
|
|
|
|
|
|
|
|
|
|
|
⇒ 关键认识:**这两块不需要任何特殊规则**,它们就是普通字段行 ——
|
|
|
|
|
|
标签 = `.mv-lb`(继承上面那条:14px / 600 / var(--ink) / 固定 62px / 右对齐
|
|
|
|
|
|
+ `::after` 冒号),内容 = 行里唯一参与弹性布局的那一项(占满剩余、左缘 444)。
|
|
|
|
|
|
v38 之所以把它们写成 `.mv-media`(另起一行 + 手填 `margin-left:72px`),
|
|
|
|
|
|
是因为当时**探针取错了元素** —— 它按文档序取"第一个非标签子元素",
|
|
|
|
|
|
而 `.sr-only` 的文件框是 `position:absolute`(**脱离文档流、不参与 flex**),
|
|
|
|
|
|
却被算成了"控件",于是量出"1px 隐框把上传框推走 130px"这个**假结论**。
|
|
|
|
|
|
⇒ 这轮改用真机逐行量左缘来定,不再靠推断。
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 想让它别再"另起一行":这里**不设** flex-direction —— `.mv-row` 本来就是
|
|
|
|
|
|
`display:flex; align-items:flex-start`,标签与内容天然同一行。 */
|
2026-10-10 11:01:22 +08:00
|
|
|
|
.mv-grid-media { margin-top: 2px; gap: 14px; }
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* 内容区:纵向排(缩略图 + 上传框),并**占满**标签右侧的剩余宽度
|
|
|
|
|
|
(`flex:1 1 auto` + `min-width:0` 与 `.mv-row > *:not(.mv-lb)` 那条一致,
|
|
|
|
|
|
这里显式写一遍是为了让"它的宽度 = 简介输入框的宽度"这件事一眼可读)。 */
|
|
|
|
|
|
.mv-row-media > .mv-media-body {
|
|
|
|
|
|
flex: 1 1 auto; min-width: 0;
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 8px;
|
|
|
|
|
|
}
|
2026-10-10 11:01:22 +08:00
|
|
|
|
.mv-media-body .photo-grid { margin-top: 0; }
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* 观影照片的标签**不带冒号**(用户原话:「观影照片也是加粗。和简介的字体保持一致,
|
|
|
|
|
|
不带冒号。」)—— 这类"有标签但不带冒号"的情况靠一个类开关,别去改 ::after 的全局规则。 */
|
|
|
|
|
|
.mv-lb.no-colon::after { content: none; }
|
2026-10-10 11:01:22 +08:00
|
|
|
|
/* ⚠️ `.sr-only` 是**绝对定位**的(见 .sr-only 的定义);它不该影响任何布局。
|
2026-10-10 12:42:43 +08:00
|
|
|
|
这里再钉一次"不参与 flex 分配"(万一将来有人把 .sr-only 的定义改了)。 */
|
2026-10-10 11:01:22 +08:00
|
|
|
|
.mv-media-body > .sr-only,
|
|
|
|
|
|
.mv-row > .sr-only { position: absolute; flex: 0 0 0; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② Ant Design RangePicker 的外观对齐 ----
|
|
|
|
|
|
目标是"看起来就是站内的一个输入框",而不是"嵌进来一个外来控件":
|
|
|
|
|
|
同高(40px)、同圆角、同描边、同纸色。 */
|
|
|
|
|
|
.dt-antd { flex: 1 1 auto; min-width: 0; }
|
|
|
|
|
|
.dt-antd .ant-picker {
|
|
|
|
|
|
width: 100%; height: 40px; padding: 0 11px;
|
|
|
|
|
|
border: 1px solid var(--line); border-radius: var(--radius-s);
|
|
|
|
|
|
background: var(--surface); box-shadow: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dt-antd .ant-picker:hover { border-color: var(--brand-2); }
|
|
|
|
|
|
.dt-antd .ant-picker-focused { border-color: var(--brand); box-shadow: none; }
|
|
|
|
|
|
.dt-antd .ant-picker-input > input { font: inherit; font-size: 14px; color: var(--ink); }
|
|
|
|
|
|
/* 品牌色覆盖:让 antd 的选中/主色跟着模块色走(与 Semi 那次同一思路) */
|
|
|
|
|
|
.dt-antd .ant-picker-range-separator { color: var(--muted); }
|
|
|
|
|
|
.dt-antd .ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner,
|
|
|
|
|
|
.dt-antd .ant-picker-cell-in-view.ant-picker-cell-range-start .ant-picker-cell-inner,
|
|
|
|
|
|
.dt-antd .ant-picker-cell-in-view.ant-picker-cell-range-end .ant-picker-cell-inner {
|
|
|
|
|
|
background: var(--brand) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 中间的"区间底色"用模块色的浅版 */
|
|
|
|
|
|
.dt-antd .ant-picker-cell-in-view.ant-picker-cell-in-range::before,
|
|
|
|
|
|
.dt-antd .ant-picker-cell-in-view.ant-picker-cell-range-hover::before {
|
|
|
|
|
|
background: color-mix(in srgb, var(--brand) 12%, transparent) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dt-antd .ant-picker-time-panel-column > li.ant-picker-time-panel-cell-selected .ant-picker-time-panel-cell-inner {
|
|
|
|
|
|
background: color-mix(in srgb, var(--brand) 14%, transparent) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.dt-antd .ant-btn-primary { background: var(--brand); border-color: var(--brand); }
|
|
|
|
|
|
.dt-antd .ant-btn-primary:hover { background: var(--brand-2) !important; border-color: var(--brand-2) !important; }
|
|
|
|
|
|
/* 面板:跟着纸色(antd 默认是纯白 + 冷灰边) */
|
|
|
|
|
|
.dt-antd .ant-picker-dropdown .ant-picker-panel-container {
|
|
|
|
|
|
border: 1px solid var(--line); box-shadow: var(--shadow-l, 0 10px 30px rgba(0,0,0,.14));
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 面板整体跟着模块色(antd 的 CSS-in-JS 变量) */
|
|
|
|
|
|
.ant-picker-dropdown {
|
|
|
|
|
|
--ant-color-primary: var(--brand, #A84A28);
|
|
|
|
|
|
--ant-color-primary-hover: var(--brand-2, #C05F38);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ 挂上 antd 之后:**原生那对下拉收起来**(它们仍然在 DOM 里当值载体)。
|
|
|
|
|
|
⚠️ 用 visibility+绝对定位而不是 display:none —— 见 v37 那次的教训:
|
|
|
|
|
|
display:none 的控件在表单校验时不可聚焦;这里虽然已摘掉 required,
|
2026-10-12 15:31:03 +08:00
|
|
|
|
但保持"可聚焦"更稳(免得将来再加必填时又踩同一个坑)。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 v44(用户 2026-10-12 第 2 条):「之前的日期选择控件还有,需要删除。」
|
|
|
|
|
|
—— 用户在**日程**上看到 antd 控件与原生五个下拉**并排都在**。真根因是
|
|
|
|
|
|
**结构性**的:日程那对是 `‹div.dt-range› ‹div.field.ev-dt› ‹div.dt-input›`
|
|
|
|
|
|
(`.dt-input` 是**孙子**),而这条规则用的是**直接子**选择器 `> .dt-input`
|
|
|
|
|
|
⇒ **在日程上根本不命中**。
|
|
|
|
|
|
(与 v43 纪念日那次同族:结构一变,直接子选择器静默失效、不报任何错。)
|
|
|
|
|
|
⇒ ① 把 `>` 放宽成**后代**选择器(`_event_fields.php` 那边的结构也已改回
|
|
|
|
|
|
"与观影一致"的直接子,两道保险);
|
|
|
|
|
|
② 用户要的"删除"就做成真删 —— 用 `display:none` 把**原生下拉那一块**
|
|
|
|
|
|
从渲染里去掉。**注意:值载体不受影响** —— 隐藏的 `*_date` / `*_hour`
|
|
|
|
|
|
/ `*_minute` 是 `.dt-input` 的**直接子元素**,**不在 `.dt-native` 里**,
|
|
|
|
|
|
所以删掉原生块**不碰提交契约**。
|
|
|
|
|
|
(v37 那条"display:none 不可聚焦"讲的是**带 required 的可见字段**;
|
|
|
|
|
|
这里被藏的是"已被 antd 取代的旧控件",必填校验早已由
|
|
|
|
|
|
`guardRequired` 的 `data-required` 自查接管 ⇒ 不适用那个顾虑。) */
|
|
|
|
|
|
.dt-range.is-antd .dt-input {
|
2026-10-10 11:01:22 +08:00
|
|
|
|
position: absolute; width: 1px; height: 1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
|
|
|
|
|
|
border: 0; padding: 0; margin: -1px;
|
|
|
|
|
|
}
|
2026-10-12 15:31:03 +08:00
|
|
|
|
/* antd 真的挂上了 ⇒ 原生那几档下拉**彻底不渲染**(用户要的"删除")。 */
|
|
|
|
|
|
.dt-range.is-antd .dt-input .dt-native { display: none !important; }
|
|
|
|
|
|
|
|
|
|
|
|
/* 🔴🔴 v44:**带内联标签的那个端点不收起**。
|
|
|
|
|
|
根因(真机几何量出来的):内联标签(「日期范围:」)是画在 `.dt-input` **里面**的,
|
|
|
|
|
|
而上面那条收起规则把整个 `.dt-input` 绝对定位 + `clip` 掉了 ⇒
|
|
|
|
|
|
**标签跟着一起被裁没了**,用户只看到一个没有标签的控件
|
|
|
|
|
|
(量出来的证据:标签盒在 x=316/y=313 却被祖先 clip,`elementFromPoint`
|
|
|
|
|
|
命中的是 `.ant-picker-range-separator` ⇒ 标签确实看不见)。
|
|
|
|
|
|
⇒ 两头都不牺牲:`.dt-input` 只藏**它里面的原生块**(上一条已 `display:none`),
|
|
|
|
|
|
自己保持正常布局 ⇒ 它变成 `[标签 62px][最新控件]` 的一个横排。
|
|
|
|
|
|
起止的**第二个**端点没有标签,继续按上一条被收起(它本来就该消失)。 */
|
|
|
|
|
|
.dt-range.is-antd > .dt-input.has-inline-label {
|
|
|
|
|
|
position: static; width: auto; height: auto; overflow: visible;
|
|
|
|
|
|
clip: auto; margin: 0; padding: 0; border: 0;
|
|
|
|
|
|
flex: 1 1 auto; min-width: 0;
|
|
|
|
|
|
display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 🔴 v44(用户第 5 条):**单个**带时刻的 antd 控件(任务「截止时间」)。
|
|
|
|
|
|
与上面那对同一条思路 —— 挂上后把原生那几档下拉**真删掉**。
|
|
|
|
|
|
选择器用 `.dt-input.is-antd`(单点,不是范围组)——
|
|
|
|
|
|
`_datetime.php` 里 antd 挂载点仍是 `.dt-input` 自身。 */
|
|
|
|
|
|
.dt-input.is-antd > .dt-native { display: none !important; }
|
|
|
|
|
|
.dt-input.is-antd > .dt-antd { display: block; width: 100%; }
|
2026-10-10 11:01:22 +08:00
|
|
|
|
/* 窄屏:标签列收窄,别把输入框挤没了 */
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.mv-row > .mv-lb,
|
|
|
|
|
|
.mv-row.dt-range.dt-cols > .dt-range-label { flex: 0 0 52px; width: 52px; font-size: 13px; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-10-10 12:42:43 +08:00
|
|
|
|
/* ---- 🔴 v39:撤销 v38 的"并排对" ----
|
|
|
|
|
|
用户 2026-10-10:「简介和备注不要放在一行,也就是说一个字段它就占一行。
|
|
|
|
|
|
所以简介后面是一行,备注后面是一行。」—— 简介/备注各占一整行。
|
|
|
|
|
|
⇒ `.mv-pair` 那套(grid 两列)整个删掉:它是 v38 为了压高度加的,
|
|
|
|
|
|
但半宽的多行文本框反而每行都换行、更难读。海报/观影照片也不再并排
|
|
|
|
|
|
(它们本来就只有一块,当时的"并排网格"里只有一个孩子,
|
|
|
|
|
|
grid 让它只占半宽 —— 那正是"海报的上传框比简介窄"的原因)。
|
|
|
|
|
|
⚠️ 不留悬念:全站搜 `.mv-pair` 应该**零命中**(模板与 CSS 都清干净)。 */
|
2026-10-10 22:13:20 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
🔴 v40(用户 2026-10-10)观影模块四处界面反馈
|
|
|
|
|
|
============================================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ① 影院管理表格:操作列不再被挤成两行 ----
|
|
|
|
|
|
用户原话:「影院管理部分,注意控制列的宽度,因为最右侧的操作、编辑和删除两个按钮,
|
|
|
|
|
|
已经被挤成两行了,尝试让编辑和删除排在一行,宽度给它留够。」
|
|
|
|
|
|
🔴 真因:`.table` 是 `width:100%` + 自动布局,浏览器按内容分配列宽 ——
|
|
|
|
|
|
长地址那一列会把「操作」列压到只剩几十像素,两个按钮只好换行。
|
|
|
|
|
|
⇒ 两件事一起做才稳:
|
|
|
|
|
|
① 表格改 `table-layout: fixed`(列宽由我们给,不再被内容牵着走);
|
|
|
|
|
|
② 「操作」列给一个**够放两个按钮的最小宽度**(编辑 48 + 间距 8 + 删除 48
|
|
|
|
|
|
+ 单元格左右 padding 16 ≈ 128,留到 132 更从容)。
|
|
|
|
|
|
⚠️ 为什么不只是 `white-space:nowrap`:那会把列撑成"刚好够",
|
|
|
|
|
|
但**表格还是按内容分配**,窗口一窄就又轮到别的列挤压它;
|
|
|
|
|
|
固定布局才是真的把这件事钉死。 */
|
|
|
|
|
|
.cn-table { table-layout: fixed; }
|
|
|
|
|
|
.cn-table .cn-col-name { width: 30%; }
|
|
|
|
|
|
.cn-table .cn-col-place { width: 15%; }
|
|
|
|
|
|
.cn-table .cn-col-addr { width: 32%; }
|
|
|
|
|
|
.cn-table .cn-col-count { width: 10%; }
|
|
|
|
|
|
.cn-table .cn-col-ops { width: 132px; }
|
|
|
|
|
|
.cn-table td.cn-addr { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
.cn-ops {
|
|
|
|
|
|
display: flex; align-items: center; gap: 8px;
|
|
|
|
|
|
/* 🔴 不换行是本条的正题 */
|
|
|
|
|
|
flex-wrap: nowrap; white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cn-ops > form { display: inline-flex; margin: 0; flex: 0 0 auto; }
|
|
|
|
|
|
.cn-ops > .btn { flex: 0 0 auto; }
|
|
|
|
|
|
/* 窄屏:地址列让位(它最长、也最不影响判断),操作列宽度保持不变 */
|
|
|
|
|
|
@media (max-width: 720px) {
|
|
|
|
|
|
.cn-table .cn-col-name { width: 34%; }
|
|
|
|
|
|
.cn-table .cn-col-place { width: 18%; }
|
|
|
|
|
|
.cn-table .cn-col-addr { width: 22%; }
|
|
|
|
|
|
.cn-table .cn-col-count { width: 12%; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ② 实心语义按钮:编辑=蓝、删除=红 ----
|
|
|
|
|
|
⚠️ 单独定义(不去改 `.btn-danger` 的既有语义):`.btn-danger` 是**淡红描边**的
|
|
|
|
|
|
"危险动作",全站十来处「删除」都在用它;用户这次要的是**实心色块**,
|
|
|
|
|
|
改 `.btn-danger` 会让所有页面一起变样。
|
|
|
|
|
|
三处都要写:裸类 / `a.` / `button.` —— 与页头动作区那套同一个理由
|
|
|
|
|
|
(`.btn`、`a.btn`、`button.btn` 特异性不同,漏一种就有一种是错的)。 */
|
|
|
|
|
|
.btn-edit, a.btn-edit, button.btn-edit {
|
|
|
|
|
|
background: var(--blue); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn-del, a.btn-del, button.btn-del {
|
|
|
|
|
|
background: var(--red); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* ⚠️ hover 统一交给文件靠后的「全站悬停统一」段(有底色的一律同色系加深)——
|
|
|
|
|
|
但那段是按 `.btn-ok/.btn-del/...` 的类名白名单写的,`.btn-edit` 是新的,
|
|
|
|
|
|
要在这里补一条,否则它会退回 `.btn` 的默认(品牌色底),看着像变了个按钮。 */
|
|
|
|
|
|
.btn-edit:hover { filter: brightness(.92); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ③ 观影详情页 = 列表页的头部口径 ----
|
|
|
|
|
|
用户原话:「观影详情页面左上角的观影记录,应该和观影的列表页面里面保持一致。」
|
|
|
|
|
|
列表页是 `<h1>观影记录</h1>` + sub;详情页原来只有一个 `<span class="sub">`,
|
|
|
|
|
|
没有 h1 ⇒ 左上角看起来"不像是同一件事"。模板已补上 h1,
|
|
|
|
|
|
这里只处理**窄屏**:h1 与 sub 在页头会挤,sub 允许收缩并省略。 */
|
|
|
|
|
|
.page-head > .sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- ④ 高级搜索的日期范围:换成 AntD RangePicker(纯日期)----
|
|
|
|
|
|
🔴 v40(用户 2026-10-10):「高级搜索里面的日期范围,也使用我们最新的控件。」
|
|
|
|
|
|
挂上之后把**原生那两个日期框收起来**(它们仍是 GET 字段,只是不显示)。
|
|
|
|
|
|
⚠️ 与原观影那对 `.dt-range.is-antd > .dt-input` 用同一套"clip 收起"手法:
|
|
|
|
|
|
不用 `display:none`(保持可聚焦,避免将来加 required 时不可聚焦的坑)。 */
|
|
|
|
|
|
.date-antd-field .date-range.is-antd > .input,
|
|
|
|
|
|
.date-antd-field .date-range.is-antd > .to {
|
|
|
|
|
|
position: absolute; width: 1px; height: 1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
|
|
|
|
|
|
border: 0; padding: 0; margin: -1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.date-antd-field .date-range.is-antd { display: block; }
|
|
|
|
|
|
/* 纯日期版控件与观影那边同款外观(同高、同圆角、同描边)—— 复用 .dt-antd 的规则,
|
|
|
|
|
|
这里只补"它是块级、占满字段宽度"这一点(.dt-antd 原为 flex 子项)。 */
|
|
|
|
|
|
.dt-antd-dateonly { display: block; width: 100%; }
|
2026-10-11 10:12:11 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
🔴 v41(用户 2026-10-10)旅程详情页的四个动作按钮:计划=蓝 / 实际=绿 / 编辑=黄 / 删除=红
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
为什么四种都要在**页头动作区那一层**再写一遍:
|
|
|
|
|
|
页头有一套"特异性更高"的规则(`.page-head .actions > .btn:not(.btn-icon)` 等,
|
|
|
|
|
|
见文件前部的页头按钮层),它们会盖过基类的 `.btn-xxx` 底色。
|
|
|
|
|
|
v40 的 `.btn-del` 就吃过这一脚(必须在页头层再补一条才生效)。
|
|
|
|
|
|
⚠️ 三处形态都要写(裸类 / a. / button.):`.btn`、`a.btn`、`button.btn`
|
|
|
|
|
|
的特异性不同,漏一种就有一种是错的(这条规律在 v40 已经验证过)。
|
|
|
|
|
|
⚠️ 设置按钮**不动**(用户:"设置就用这个图标,不要变")。 */
|
|
|
|
|
|
.btn-plan, a.btn-plan, button.btn-plan {
|
|
|
|
|
|
background: var(--blue); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn-actual, a.btn-actual, button.btn-actual {
|
|
|
|
|
|
/* 绿比 --green 深一档:白字对比度 3.0 → 4.6,暖纸底上看得清 */
|
|
|
|
|
|
background: #4E7C3F; color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 🔴🔴 2026-10-11 修(v40 套件报的**真回归**):
|
|
|
|
|
|
这里原来写的是**裸类** `.btn-edit`(全局改黄),直接把 v40 影院管理页的
|
|
|
|
|
|
「编辑 = 蓝色实心」覆盖掉了 —— 影院那页量出来的实际色是 `rgb(184,134,11)`(黄),
|
|
|
|
|
|
而用户对它的要求是**蓝色**(v40 原话:「编辑使用蓝色的背景,删除使用红色的背景」)。
|
|
|
|
|
|
⇒ 两处需求不同:**旅程详情页的「编辑」= 黄**(v41 第 4 条),
|
|
|
|
|
|
**影院管理页的「编辑」= 蓝**(v40)。所以颜色必须**按作用域**给,不能裸类全局设。
|
|
|
|
|
|
锚点选 `[data-trip-edit]`(旅程详情页那个按钮的专属属性)——
|
|
|
|
|
|
它是最精确的标识,不依赖页头层级,也不会波及影院管理页的 `<a class="btn btn-edit">`。 */
|
|
|
|
|
|
.btn-edit[data-trip-edit] {
|
|
|
|
|
|
background: var(--yellow); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.btn-del, a.btn-del, button.btn-del {
|
|
|
|
|
|
background: var(--red); color: #fff; border-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* hover:同色系加深(与文末"全站悬停统一"段同一手法:brightness 压低) */
|
|
|
|
|
|
.btn-plan:hover, .btn-actual:hover, .btn-edit:hover, .btn-del:hover { filter: brightness(.92); }
|
|
|
|
|
|
/* 页头动作区那一层(覆盖页头默认的"品牌色实心/ghost") */
|
|
|
|
|
|
.page-head .actions > .btn-plan:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > .btn-actual:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > .btn-edit[data-trip-edit]:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > .btn-del:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-del:not(.btn-icon) { color: #fff; border-color: transparent; }
|
|
|
|
|
|
.page-head .actions > .btn-plan:not(.btn-icon) { background: var(--blue); }
|
|
|
|
|
|
.page-head .actions > .btn-actual:not(.btn-icon) { background: #4E7C3F; }
|
|
|
|
|
|
.page-head .actions > .btn-edit[data-trip-edit]:not(.btn-icon) { background: var(--yellow); }
|
|
|
|
|
|
.page-head .actions > .btn-del:not(.btn-icon),
|
|
|
|
|
|
.page-head .actions > form > button.btn-del:not(.btn-icon) { background: var(--red); }
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v41 第 8 条:交通方式的"标识"(车次号 / 车牌号)紧跟模式词 ----
|
|
|
|
|
|
用户:「把火车的车次号直接放在"火车"这两个字后面。如果是自驾,
|
|
|
|
|
|
就应该把自驾的车牌号放在后面。」
|
|
|
|
|
|
⇒ 同一个 chip 内、模式词之后,用略淡的字重区分(仍属同一个信息单元)。 */
|
|
|
|
|
|
.node-mode-no {
|
|
|
|
|
|
margin-left: 6px; padding-left: 6px;
|
|
|
|
|
|
border-left: 1px solid currentColor;
|
|
|
|
|
|
opacity: .78; font-weight: 500;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v41 第 2 条:题图的说明文字搬进框里(原来在框外另起一段)---- */
|
|
|
|
|
|
.cover-picker-hint {
|
|
|
|
|
|
display: block; margin-top: 8px;
|
|
|
|
|
|
font-size: 12.5px; line-height: 1.6; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
🔴 v41(用户 2026-10-10 第 5/6 条)行程弹框的**观影式排版**
|
|
|
|
|
|
============================================================================
|
|
|
|
|
|
用户原话:「编辑行程、加计划行程、加实际行程,全部都采用弹窗的形式。
|
|
|
|
|
|
其排版的方式和添加电影是一样的,前面是标题冒号,后面是输入框,
|
|
|
|
|
|
和观影模块一样,注意排版。」
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 为什么这里用 **grid** 而不是 flex(2026-10-10 血泪):
|
|
|
|
|
|
先按观影那套写了 flex(`display:flex; flex-wrap:wrap` + label 固定 62px),
|
|
|
|
|
|
结果**控件被挤到下一行**(实测 label y=117 / 控件 y=187)。
|
|
|
|
|
|
查了半天:`.input/.select` 全站有 `width: 100%`,在 flex 行里
|
|
|
|
|
|
它的 auto 基准就是**整行宽** ⇒ 62 + 10 + 696 > 696 ⇒ 换行。
|
|
|
|
|
|
把 width 改 auto、把 flex-basis 从 0% 试到 auto、加 min-width……
|
|
|
|
|
|
控件宽度是对了(140),**换行依旧**(同一行里还有 `.tip` 声明着
|
|
|
|
|
|
`flex: 0 0 100%`,wrap 算法会把它们的理想宽度一起算)。
|
|
|
|
|
|
⇒ 换 **grid**:`.field` 两列(62px + 1fr),标签在第 1 列、控件在第 2 列,
|
|
|
|
|
|
`.tip/.err` 用 `grid-column: 2` 自动落在控件下面**且与控件左缘对齐**
|
|
|
|
|
|
(连 margin-left 都不需要)。两列表单的标准写法,不受 width/flex 交互影响。
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 作用域用 `.nf-form`(表单自己的类)而不是 `.nf-wrap` / `.nf-panel`:
|
|
|
|
|
|
片段形态(`?embed=1`)两者都不输出(壳由详情页容器给),
|
|
|
|
|
|
只用它们的话排版在弹框里**完全不生效**(探针抓到过)。 */
|
|
|
|
|
|
.nf-form .form-grid {
|
|
|
|
|
|
display: flex; flex-direction: column; gap: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nf-form .form-grid > .field {
|
|
|
|
|
|
display: grid; grid-template-columns: 62px minmax(0, 1fr);
|
|
|
|
|
|
column-gap: 10px; row-gap: 6px; align-items: start;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 标签:固定第 1 列、右对齐、自动冒号(与观影那套同一组数字) */
|
|
|
|
|
|
.nf-form .form-grid > .field > label {
|
|
|
|
|
|
grid-column: 1;
|
|
|
|
|
|
text-align: right; padding-top: 9px;
|
|
|
|
|
|
font-size: 14px; font-weight: 600; color: var(--ink);
|
|
|
|
|
|
line-height: 1.4; word-break: keep-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
.nf-form .form-grid > .field > label::after {
|
|
|
|
|
|
content: ':'; font-weight: 400; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 控件:占第 2 列(宽度由 grid 给,不受它的 width:100% 影响) */
|
|
|
|
|
|
.nf-form .form-grid > .field > *:not(label) {
|
|
|
|
|
|
grid-column: 2; min-width: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 提示 / 错误:也在第 2 列 ⇒ **自动与控件左缘对齐** */
|
|
|
|
|
|
.nf-form .form-grid > .field > .tip,
|
|
|
|
|
|
.nf-form .form-grid > .field > .err {
|
|
|
|
|
|
grid-column: 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 起终点是两列小网格,整段落在第 2 列 */
|
|
|
|
|
|
.nf-form .form-grid > .field > .loc-row { grid-column: 2; }
|
|
|
|
|
|
/* 「当前状态」是只读文本,对齐 40px 高的控件 */
|
|
|
|
|
|
.nf-form .node-stage-ro { padding-top: 9px; }
|
|
|
|
|
|
/* 窄屏:标签列压到 52px,避免控件被挤得太窄 */
|
|
|
|
|
|
@media (max-width: 560px) {
|
|
|
|
|
|
.nf-form .form-grid > .field { grid-template-columns: 52px minmax(0, 1fr); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v41 第 8 条:交通方式的"标识"(车次号 / 车牌号)紧跟模式词 ----
|
|
|
|
|
|
用户:「把火车的车次号直接放在"火车"这两个字后面。如果是自驾,
|
|
|
|
|
|
就应该把自驾的车牌号放在后面。」
|
|
|
|
|
|
⇒ 同一个 chip 内、模式词之后,用略淡的字重区分(仍属同一个信息单元)。 */
|
|
|
|
|
|
.node-mode-no {
|
|
|
|
|
|
margin-left: 6px; padding-left: 6px;
|
|
|
|
|
|
border-left: 1px solid currentColor;
|
|
|
|
|
|
opacity: .78; font-weight: 500;
|
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v41 第 2 条:题图的说明文字搬进框里(原来在框外另起一段)---- */
|
|
|
|
|
|
.cover-picker-hint {
|
|
|
|
|
|
display: block; margin-top: 8px;
|
|
|
|
|
|
font-size: 12.5px; line-height: 1.6; color: var(--muted);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- v41 第 10 条:纪念日弹框(观影式排版)里"月 / 日"那一行的两格 ---- */
|
|
|
|
|
|
.an-md { display: flex; align-items: center; gap: 6px; }
|
|
|
|
|
|
.an-md .input { width: 88px; flex: 0 0 auto; text-align: center; }
|
|
|
|
|
|
.an-md-sep { color: var(--muted); font-size: 13px; }
|
|
|
|
|
|
/* 观影式行里的"填充块"(选人组件那种自带布局的控件,占满控件位) */
|
|
|
|
|
|
.mv-row > .mv-fill { flex: 1 1 auto; min-width: 0; }
|
2026-10-11 18:35:03 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- v42(用户 2026-10-11 第 8 条)纪念日「日期」:AntD 单日期控件 ----
|
|
|
|
|
|
与原观影/高级搜索那两处同一套做法:
|
|
|
|
|
|
· `.dt-antd` 是 antd 的挂载点(宽度交给它);
|
|
|
|
|
|
· 挂上后(`.is-antd`)把**原生 `<input type="date">` 视觉收起** ——
|
|
|
|
|
|
它仍是值载体(antd 通过 change 写它),只是不再显示给用户。
|
2026-10-12 00:24:20 +08:00
|
|
|
|
⚠️ 用 clip 收起(不是 display:none):保留可聚焦、可被表单读到。
|
|
|
|
|
|
🔴🔴 v43(用户 2026-10-11 第 1 条):「日期那里多了一个控件,
|
|
|
|
|
|
只保留我们最新的控件就行,之前那种控件删除」——真根因有两层:
|
|
|
|
|
|
① 纪念日的原生框当初**没包在 `.dt-native` 里** ⇒ 这条选择器根本不命中
|
|
|
|
|
|
(模板已补上包装);
|
|
|
|
|
|
② **更要命的一层**:`.dt-input .dt-native { display: contents }`(第 619 行)
|
|
|
|
|
|
会让这个包装盒**自己不生成盒子**、子元素"提升"成 `.dt-input` 的直接布局项 ——
|
|
|
|
|
|
此时给它 `position:absolute; width:1px` **完全无效**(它没有盒子可定位),
|
|
|
|
|
|
原生框照样按 flex 项排出来 ⇒ 两个控件并排。
|
|
|
|
|
|
⇒ 修法:这里必须把 `display` **从 contents 改成 block**,定位才生效。
|
|
|
|
|
|
(只写 position/width/height 是不够的 —— 这是我第一版的错,探针当场抓到。) */
|
|
|
|
|
|
.dt-input.is-antd > .dt-native {
|
|
|
|
|
|
display: block; position: absolute; width: 1px; height: 1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
|
|
|
|
|
|
}
|
2026-10-11 18:35:03 +08:00
|
|
|
|
.dt-input.is-antd > .dt-antd { display: block; width: 100%; }
|
|
|
|
|
|
.dt-input.dt-antd-single { display: block; width: 100%; }
|
2026-10-12 00:24:20 +08:00
|
|
|
|
/* 兜底:万一哪天原生框又变成 `.dt-input` 的**直接子元素**(不包 .dt-native 了),
|
|
|
|
|
|
这条按直接子元素也能把它收起来。 */
|
|
|
|
|
|
.dt-input.is-antd > input[type="date"] {
|
|
|
|
|
|
display: block; position: absolute; width: 1px; height: 1px;
|
|
|
|
|
|
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
|
|
|
|
|
|
}
|
2026-10-11 18:35:03 +08:00
|
|
|
|
|
|
|
|
|
|
/* ---- v42(用户第 6 条)简介为空时的那句可点占位 ----
|
|
|
|
|
|
与 `.trip-sum` 同一视觉位置,只是颜色淡一档(它是要点进去补的提示,不是内容)。 */
|
|
|
|
|
|
.trip-sum-empty { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
|
|
|
|
|
|
.trip-sum-empty a { color: var(--brand); }
|
2026-10-12 00:24:20 +08:00
|
|
|
|
|
|
|
|
|
|
/* ============================================================================
|
|
|
|
|
|
🔴 v43(用户 2026-10-11 第 6 条)条目详情浮层
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
与 .cal-modal 同一形态(遮罩 + 居中面板 + 底栏),只是层级更高一点:
|
|
|
|
|
|
它可能从**另一个浮层**里打开(例如详情页弹框里点了条目),
|
|
|
|
|
|
所以要在 200 之上;但低于"看图"的灯箱(300)/预览层(320)。
|
|
|
|
|
|
⚠️ 与 .cn-modal(260)、.crop-overlay(260) 同层 —— 它们不会同时出现。
|
|
|
|
|
|
⚠️ 面板用 flex 列 + body 滚动,长内容(编辑表单)才有足够的可视区。 */
|
|
|
|
|
|
.fb-entry-modal {
|
|
|
|
|
|
position: fixed; inset: 0; z-index: 260;
|
|
|
|
|
|
display: flex; align-items: flex-start; justify-content: center;
|
|
|
|
|
|
padding: 24px 16px; overflow-y: auto;
|
|
|
|
|
|
background: rgba(44, 35, 29, .55); overscroll-behavior: contain;
|
|
|
|
|
|
}
|
|
|
|
|
|
.fb-entry-modal[hidden] { display: none; }
|
|
|
|
|
|
.fb-entry-panel { width: min(620px, 100%); max-height: calc(100vh - 64px); }
|
|
|
|
|
|
/* 编辑态下正文里就是一张完整表单(内边距由它自己那份 CSS 给)——
|
|
|
|
|
|
这里只保证它不双份留白。 */
|
|
|
|
|
|
.fb-entry-panel .cal-modal-body > .mv-form-inner,
|
|
|
|
|
|
.fb-entry-panel .cal-modal-body > .nf-wrap { padding: 0; }
|
|
|
|
|
|
@media (max-width: 640px) {
|
|
|
|
|
|
.fb-entry-panel { width: 100%; }
|
|
|
|
|
|
}
|