v24 第 9 批:名册九条(分组按钮/加入名册/生日月日/地址四级/千人性能/拖动修复/删除人员/返回名册/Semi DatePicker)
- #131 名册卡片加「分组」按钮(details+radio,显示当前分组,选中即改) - #132 修复「从已有人里加入名册」无反应 - #133 生日只显示月和日(阳历 MM-DD / 农历中文名),PersonQuery::birthdaysOf 取代 birthdayOf - #134 地址结构化为 国家/省/市/区+详细:regions 表(3429 行全国区划)+ Region.php + ?r=regions 级联接口 + 表单 .addr-grid + 老地址回填(Schema v16) - #135 千人名册性能:.person content-visibility:auto + 名册页 ob_gzhandler (实测 服务端 1.15s/3.8MB → 0.17s/87KB;客户端导航→load 1.35s → 0.37s) - #136 拖动排序改 Pointer Events(Chrome 下 HTML5 DnD 在 DOM 变动时断) - #137 个人详情页底部「删除人员」 - #138 编辑资料页加「返回名册」 - #139 所有日期选择换 Semi Design DatePicker(渐进增强:原生四字段保 POST 契约, 懒加载 vendor semi UMD,值回写原字段;工作经历 type=month 一并升级;宣纸主题对齐) 验证:e2e 785/0、batch9 37/0、upgrade 126/0、picker 28/0、mobile 688/0、interact 97/0、 batch_e 91/0、import 21/0、douban 22/0、drag 5/0、semi-integrate 28/0、semi-probe 17/0、 geom 5/5;部署后线上自检 16/16(含 4 个 semi 资源 200 + regions 路由)。
This commit is contained in:
+120
-17
@@ -315,11 +315,23 @@ a:hover { text-decoration: underline; }
|
||||
.people-grid {
|
||||
display: flex; flex-direction: column; gap: 8px; margin-top: 4px;
|
||||
}
|
||||
/* ⚠️ 整行是**一条 flex**:[拖柄] [头像+信息(占满剩下的)] [右侧动作]。
|
||||
原来右侧的「编辑 / ⋯」各自写死 right:46px / right:8px 绝对定位,
|
||||
于是再往里加第三个按钮只能继续猜偏移、且「分组」按钮宽度随分组名变化必然重叠;
|
||||
改 flex 之后按钮自然排开,姓名那边也不用靠 padding-right 让位了。 */
|
||||
.person {
|
||||
display: block; color: var(--ink); position: relative;
|
||||
display: flex; align-items: stretch; color: var(--ink); position: relative;
|
||||
background: var(--surface); border: 1px solid var(--line);
|
||||
border-radius: var(--radius-s);
|
||||
transition: border-color .15s ease, box-shadow .15s ease;
|
||||
/* v24 第 9 批 #5:千人名册不「卡死」的关键 —— 屏外的卡片浏览器直接跳过
|
||||
布局/绘制(4 万+ DOM 节点的排版是一次性成本的大头)。
|
||||
contain-intrinsic-size 给屏外卡片一个估算高度撑滚动条,
|
||||
auto 前缀让浏览器记住真实渲染高度,滚过后就精确了。
|
||||
⚠️ 拖动排序用的是实时 getBoundingClientRect:目标被自动滚进视口时
|
||||
content-visibility 会立刻出真实布局,落点计算不受影响(drag probe 已验证)。 */
|
||||
content-visibility: auto;
|
||||
contain-intrinsic-size: auto 68px;
|
||||
}
|
||||
.person:hover { border-color: var(--brand-2); box-shadow: var(--shadow); }
|
||||
/* 头像:列表里用小方图(正方形、cover 裁切),不再是整块大图 */
|
||||
@@ -331,6 +343,7 @@ a:hover { text-decoration: underline; }
|
||||
.person .person-main {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
padding: 10px 12px; color: var(--ink); text-decoration: none;
|
||||
flex: 1 1 auto; min-width: 0; /* 剩下的宽度都给它,按钮那头不挤它 */
|
||||
}
|
||||
.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; }
|
||||
@@ -521,6 +534,37 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
中文环境渲染成「下午 03:30」且没有秒,所以自己拼一个。
|
||||
日期部分仍是原生 date 控件 → app.js 的 showPicker 让它整框可点。 */
|
||||
.dt-input { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
||||
/* v24 第 9 批 #9:Semi DatePicker 升级态 —— .dt-native 是 display:contents(不干扰
|
||||
flex 布局),升级成功后由 app.js 内联 display:none 藏掉;.dt-semi 顶上同一格。 */
|
||||
.dt-input .dt-native { display: contents; }
|
||||
.dt-input .dt-semi { display: none; flex: 1 1 220px; min-width: 0; }
|
||||
.dt-input.is-semi .dt-semi { display: block; }
|
||||
/* 工作经历的月份选择器(type="month" 升级):占满原 .job-cell 格子 */
|
||||
.dt-semi.dt-semi-month { display: none; }
|
||||
.dt-semi.dt-semi-month.is-live { display: block; width: 100%; }
|
||||
.dt-input.dt-missing .semi-input-wrapper { border-color: #C0392B !important; box-shadow: 0 0 0 1px #C0392B inset; }
|
||||
/* Semi 主题对齐宣纸色。semi.min.css 是懒加载的、必然排在 app.css 之后,
|
||||
所以这里赢在**优先级**:body[class] 特异性(0,1,1) > semi 的 body(0,0,1)。 */
|
||||
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);
|
||||
}
|
||||
/* 输入框本体:跟站内 .input / .dt-date 同一轮廓(描边、圆角、纸面底色、同高) */
|
||||
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);
|
||||
}
|
||||
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); }
|
||||
/* 日历面板:白纸底色统一成卡片的纸色,选中/悬停色走上面的 brand 变量 */
|
||||
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); }
|
||||
.dt-input .dt-date {
|
||||
flex: 1 1 150px; min-width: 0;
|
||||
padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-s);
|
||||
@@ -926,21 +970,19 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
/* 卡片改成 div > a + details:表单不能套在链接里(非法 HTML,浏览器会把 DOM 拆开) */
|
||||
.person-main { display: block; color: var(--ink); }
|
||||
.person-main:hover { text-decoration: none; }
|
||||
.person-more { display: none; }
|
||||
/* 列表形态下「⋯ 调整分组」改到行的**右侧**(原来在卡片下方,列表里会撑高一行) */
|
||||
.person-more {
|
||||
position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
|
||||
border: 0; background: none;
|
||||
|
||||
/* ---- 行右侧的动作区(分组 / 编辑 / ⋯)----
|
||||
⚠️ 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-10-03 第 7 条:⋯ **前面**多了一个「编辑」按钮,所以 ⋯ 要往左让位。
|
||||
编辑按钮同样绝对定位在行右侧(在 ⋯ 左边 46px 处)—— 两个都贴着行的右边缘,
|
||||
这样"改资料(常用)"在前、"更多操作(低频)"在后,手指/鼠标扫过去就是从左到右。 */
|
||||
.person-edit {
|
||||
position: absolute; right: 46px; top: 50%; transform: translateY(-50%);
|
||||
padding: 3px 10px; font-size: 13px;
|
||||
padding: 3px 10px; font-size: 13px; white-space: nowrap;
|
||||
}
|
||||
/* ⚠️ 预留出右侧两个按钮的位置,否则姓名/信息会钻到按钮底下 */
|
||||
.people-grid .person .person-main { padding-right: 96px; }
|
||||
.person-more > summary {
|
||||
list-style: none; cursor: pointer; padding: 4px 10px;
|
||||
font-size: 16px; color: var(--muted); border-radius: 8px;
|
||||
@@ -960,18 +1002,53 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
.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 第 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; }
|
||||
|
||||
/* ---------------- 名册:拖动排序 / 拖到别栏改分组 ----------------
|
||||
拖动是"锦上添花":没有它,卡片上的「⋯ → 调整分组」表单照样能改分组,
|
||||
手机上 HTML5 拖放本来也不生效,那套表单就是窄屏的正路。 */
|
||||
⚠️ 2026-10-04 起这一段是 **Pointer Events**(不再用 HTML5 拖放)——
|
||||
原因写在 app.js 那段注释里(Chrome 下"只有第一组能拖"就是 HTML5 DnD 的锅)。
|
||||
没有它,行上的「分组」按钮照样能改分组,功能不缺。 */
|
||||
.roster.is-droppable .person { cursor: grab; }
|
||||
.roster.is-droppable .person.is-dragged { opacity: .45; cursor: grabbing; }
|
||||
/* ⚠️ 拖动中被拖的那张卡必须 pointer-events:none:落点是用 elementFromPoint
|
||||
现算的,卡自己压在指针底下就只能算到自己,永远插不进别人中间。 */
|
||||
.roster.is-droppable .person.is-dragged { opacity: .55; cursor: grabbing; pointer-events: none; }
|
||||
.drag-handle {
|
||||
position: absolute; left: 3px; top: 50%; transform: translateY(-50%); z-index: 2;
|
||||
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);
|
||||
pointer-events: none; /* 手柄只是个记号,抓取要落在整张卡上 */
|
||||
/* ⚠️ 手柄现在是**能抓的**(不再 pointer-events:none):
|
||||
鼠标可以拖整行,但**触摸只能抓这个手柄** —— 否则手指在行上一划
|
||||
就被浏览器当成滚页面,永远拖不起来。touch-action:none 就是这句话。 */
|
||||
touch-action: none; cursor: grab;
|
||||
}
|
||||
.drag-handle-inline { color: var(--muted); }
|
||||
/* 列表里每行要留出左侧拖柄的位置(否则⠿会压在头像上) */
|
||||
@@ -992,6 +1069,14 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
.roster.is-dragging .group-block .group-n { display: none; }
|
||||
.roster.is-dragging .people-grid { min-height: 24px; }
|
||||
|
||||
/* 窄屏:一行上「分组 + 编辑 + ⋯」三个按钮,分组名会吃掉姓名的空间 ——
|
||||
把分组名的上限压一压,先保住姓名能读(分组点开照样看得到全名)。 */
|
||||
@media (max-width: 640px) {
|
||||
.person-group-btn { max-width: 76px; }
|
||||
.person-actions { gap: 4px; padding-right: 6px; }
|
||||
.person-edit { padding: 3px 7px; }
|
||||
}
|
||||
|
||||
/* 拖完/没拖成的轻提示(2 秒自己消失,不打断操作) */
|
||||
.roster-note {
|
||||
position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 12px);
|
||||
@@ -2414,3 +2499,21 @@ textarea.input { min-height: 76px; resize: vertical; }
|
||||
.brand span { display: none; }
|
||||
.who .who-name { display: none; }
|
||||
}
|
||||
|
||||
/* ---- 地址五级(国家 / 省 / 市 / 区 / 详细地址,用户 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; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user