diff --git a/assets/css/app.css b/assets/css/app.css index 2eedbab..961fc89 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -584,126 +584,126 @@ textarea.input { min-height: 76px; resize: vertical; } .search { display: flex; gap: 8px; margin-bottom: 16px; } .search .input { max-width: 260px; } -/* ---------------- 日期 + 时:分:秒 组合控件(templates/_datetime.php) ---------------- - 原生 datetime-local 的显示格式由浏览器 UI 语言/系统时间格式决定, - 中文环境渲染成「下午 03:30」且没有秒,所以自己拼一个。 - 日期部分仍是原生 date 控件 → app.js 的 showPicker 让它整框可点。 */ +/* ============================================================================ + 日期 + 时:分 组合控件(templates/_datetime.php)—— v37 重做 + ---------------------------------------------------------------------------- + 形态(用户 2026-10-09 第 4 次反馈点名要的): + 日期 = 年 / 月 / 日 三个原生下拉;时间 = 时 : 分 两个原生下拉。 + 起止两端默认同一行,放不下时自动换到下一行(flex-wrap,见 .dt-cols)。 + + 为什么把浏览器自带的 换掉: + 它的日历弹层是浏览器自己画的,我们碰不到 DOM、也控制不了流程; + Chrome 在"点顶部 2026年 10月 切到年月视图"之后要靠用户再点一次日期或 + 按 Esc 才回得到日期视图,各家还不一致 → 用户遇到的就是"选完年月就卡住、 + 选不了日"。三个原生下拉选完即生效,不需要任何确定按钮。 + + 这一整段不再有"未升级就藏原生控件"的逻辑(v24~v36 有过)。 + 服务端给的就是最终形态,JS 只负责绑事件 —— 所以"JS 没跑 / 加载失败"时 + 控件依然完整可用,不是"骨架占位"。 + ============================================================================ */ .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; } -/* ---- v24 第 12 批 #2:消除「先闪原生框、再变 Semi」---- - html.js 由
里的内联脚本立刻加上(见 layout.php 的 no-js/js 二态)。 - 有 JS 时:原生控件**从一开始就不显示**,等 Semi 就绪(app.js 加 .is-semi)再露出。 - 没 JS 时(html 仍是 no-js):什么都不藏,原生控件照旧可用 —— 渐进增强的兜底不变。 - ⚠️ 用 visibility:hidden 而不是 display:none —— 保留元素占位高度, - 否则升级完成的那一瞬表单会"跳"一下(高度从 0 变 40px)。 */ -html.js .dt-input:not(.is-semi) .dt-native { visibility: hidden; } -/* 🔴🔴 v36:`.is-native` 态下,原生控件**必须可见**。 - 用 `!important` 是**故意**的:v35 那次就是被 - `html.js .dt-input:not(.is-semi) .dt-native{visibility:hidden}` - (特异性 0,3,0,比我那条覆盖规则更强/更早)又藏回了 hidden —— - 用户看到"一片空白、点不到",而探针因为用错判据(offsetParent)还"全绿"两轮。 - ⇒ 这条用 `!important` 一次性钉死,别再让任何历史规则把它藏起来。 */ -html.js .dt-input.is-native .dt-native { visibility: visible !important; } -html.js .dt-input.is-native::after { display: none !important; } -html.js .dt-range.is-native-range .dt-input { visibility: visible !important; } -html.js .dt-range.is-native-range > .dt-range-label { visibility: visible !important; } -html.js .dt-range.is-native-range::before { display: none !important; } -html.js .dt-range.is-native-range > .dt-input, -html.js .dt-range.is-native-range > .field { display: flex !important; } -/* ⚠️ v24 第 21 批 第 7 条:两端现在各自被 `.field` 包着,所以选择器要跟着下沉一层。 - 写成 `> .dt-input` 的话这条**永远不会命中** → 未升级时原生控件照旧可见, - 与下面那块"占位骨架"叠在一起,会看到两套控件重影。 */ -html.js .dt-range:not(.is-semi-range) .dt-input { visibility: hidden; } -html.js .dt-range:not(.is-semi-range) > .dt-range-label { visibility: hidden; } -/* Semi 未就绪前,先给一个同高的"占位骨架",让表单高度在升级前后保持一致 */ -html.js .dt-input:not(.is-semi)::after { - content: ''; display: block; flex: 1 1 150px; height: 40px; - border: 1px solid var(--line); border-radius: var(--radius-s); - background: var(--surface); opacity: .55; -} -html.js .dt-range:not(.is-semi-range)::before { - content: ''; display: block; width: 100%; max-width: 460px; height: 40px; - border: 1px solid var(--line); border-radius: var(--radius-s); - background: var(--surface); opacity: .55; -} -html.js .dt-range.is-semi-range::before { display: none; } .dt-input .dt-semi { display: none; flex: 1 1 220px; min-width: 0; } -.dt-input.is-semi .dt-semi { display: block; } -.dt-input.is-semi::after { display: none; } -/* 工作经历的月份选择器(type="month" 升级):占满原 .job-cell 格子 */ + +/* ---- 日期:年 / 月 / 日 三个下拉 ---- */ +.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 仅剩的用途:工作经历的「年月选择」( 的升级) + ---------------------------------------------------------------------------- + ⚠️ 日期/时间控件(.dt-input)v37 起已完全不用 Semi —— 上面那套自建下拉 + 就是因为它给的弹层交互不可控(选完年月卡住)。这里保留的是另一处。 + ============================================================================ */ .dt-semi.dt-semi-month { display: none; } .dt-semi.dt-semi-month.is-live { display: block; width: 100%; } - -/* ---- v24 第 10 批 #7:起止范围用一个控件(Semi dateTimeRange)---- - 一对 .dt-input 被包在 .dt-range 里;升级后两端各自 display:none, - 由**一个** .dt-semi-range 顶上来。未升级(JS 没跑/加载失败)时, - 里面两个原生控件照旧各占一行 —— 也就是"功能没变,只是不好看"。 */ -.dt-range { display: flex; flex-direction: column; gap: 8px; } -/* 范围控件自己的标签(只有一个,见 _event_fields.php 的说明) */ -.dt-range-label { font-size: 13px; color: var(--muted); font-weight: 500; } -.dt-range.is-semi-range { display: block; } -.dt-range.is-semi-range > .dt-input { display: none; } /* 两端都让位给范围控件 */ -/* 两端被 .field 包着时的同一条规则(见上面第 21 批的说明) */ -.dt-range.is-semi-range > .field { display: none; } -.dt-semi-range { display: none; width: 100%; max-width: 460px; } -.dt-range.is-semi-range .dt-semi-range { display: block; } -/* Semi 范围输入框:与站内 .input 同高同圆角;宽度撑开一点(要放两个时间) */ -body[class] .dt-semi-range .semi-input-wrapper { - height: 40px; border: 1px solid var(--line); border-radius: var(--radius-s); - background: var(--surface); -} -body[class] .dt-semi-range .semi-input-wrapper:hover { border-color: var(--brand-2); } -body[class] .dt-semi-range .semi-input { font: inherit; font-size: 13.5px; color: var(--ink); } -/* ---- v24 第 12 批 #2:范围控件的「灰底 + 不垂直居中」(实测定位)---- - 用真浏览器量出来两个毛病: - ① 灰底:Semi 的 **外层** `.semi-datepicker-input` 自带 `rgba(46,50,56,.05)` - 灰底、高只有 32px;而内层 `.semi-input-wrapper` 是白底、40px —— - 两层套着,灰的那层露在外面(用户看到的"灰色背景色")。 - ② 不居中:外层 32px < 内层 40px,输入框上下都被挤出去 - (实测 gapTop=1 / gapBottom=17 → 文字贴顶)。 - 修法:把**外层容器**改成透明 + 不限高 + 垂直居中,让内层 40px 的白底框 - 自己撑起来(与站内 .input 完全一致)。 */ -body[class] .dt-semi-range .semi-datepicker-input { - background: transparent !important; - height: auto !important; - min-height: 0 !important; - align-items: center; - padding: 0; - border: 0; -} -body[class] .dt-semi-range .semi-datepicker-range-input-wrapper { - align-items: center; - background: transparent; -} -/* 两端的白底框就是"可见的输入框":撑满高度、文字垂直居中 */ -body[class] .dt-semi-range .semi-input-wrapper { - display: flex; align-items: center; -} -body[class] .dt-semi-range .semi-input-wrapper .semi-input { - height: 100%; line-height: 40px; padding: 0 8px; - background: transparent; -} -@media (max-width: 640px) { - .dt-semi-range { max-width: none; } -} -.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); - /* v24 第 12 批 #2:单点控件也做同样处理 —— 外层半透明灰底去掉、文字垂直居中 - (用户说"这种情况同样出现在其他的日期选择功能中")。 */ display: flex; align-items: center; } body[class] .dt-semi .semi-input-wrapper:hover { border-color: var(--brand-2); background: var(--surface); } @@ -711,43 +711,16 @@ body[class] .dt-semi .semi-input { font: inherit; color: var(--ink); } body[class] .dt-semi .semi-input::placeholder { color: var(--muted); } body[class] .dt-semi .semi-datepicker-input, body[class] .dt-semi .semi-datepicker { - background: transparent !important; - height: auto !important; - min-height: 0 !important; - border: 0; - padding: 0; + background: transparent !important; height: auto !important; + min-height: 0 !important; border: 0; padding: 0; } body[class] .dt-semi .semi-input-wrapper .semi-input { height: 100%; line-height: 40px; padding: 0 11px; background: transparent; } -/* 日历面板:白纸底色统一成卡片的纸色,选中/悬停色走上面的 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); - background: var(--surface); color: var(--ink); font: inherit; - accent-color: var(--brand); -} -.dt-input .dt-date { cursor: pointer; } /* 整框可点,光标也要说明这一点 */ -.dt-input .dt-date::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .65; } -.dt-time { display: flex; align-items: center; gap: 3px; } -.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-variant-numeric: tabular-nums; cursor: pointer; -} -.dt-input .dt-colon { color: var(--muted); font-weight: 600; } - -/* 🔴 v36:时间不再有"合成的时间框"(v35 试过 ``,已弃用)。 - `.dt-merged` / `.dt-time-input` 的规则一并删掉 —— 免得将来有人误以为 - 还有"被收起来的下拉"。用户要的形态就是**日期 + 时/分下拉**直接显示。 */ -.dt-input.is-native-range { gap: 8px; } -.dt-range.is-native-range { display: flex; flex-direction: column; gap: 10px; } /* 「以哪个生日为准」的两块:被选中的那块描一圈,一眼看出填的是哪边 */ .bd-source { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; } @@ -3206,6 +3179,29 @@ body[class] .semi-datepicker-day-inhover { background-color: color-mix(in srgb, 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); } + +/* 🔴🔴 v37:修正面板必须**浮**在按钮列之外,否则它只有 ~22px 宽、完全没法填。 + 真机实测(1400px 视口、品心 1080px): + .dt-range 宽 **22px**、`.nf-grid` 宽 **22px** —— 整张修正表单被压成一条线。 + 根因:`.node-ops` 是"一排小按钮"的容器 + `flex: 0 0 auto; justify-content: flex-end;`(见上面), + 而「修正」是 `- 要加照片请点上方「编辑」——「观影照片」在编辑页里一起传(可多选)。 -
-