2026-10-03 08:18:05 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 日程表单的字段块(新建与编辑共用一份 —— 复制一遍迟早改漏一处)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 字段按 **RFC 5545(iCalendar)/ RFC 4791(CalDAV)** 的 VEVENT 属性定:
|
|
|
|
|
|
* 标题 = SUMMARY
|
|
|
|
|
|
* 地点 = LOCATION
|
|
|
|
|
|
* 开始/结束 = DTSTART / DTEND(DATETIME,精确到秒)
|
|
|
|
|
|
* 全天 —— VEVENT 没有"全天"这个属性,约定俗成是把 DTSTART 写成 DATE 值;
|
|
|
|
|
|
* 我们统一存 DATETIME,全天时时间部分为 00:00:00,导出 ics 时再落成 DATE 值。
|
|
|
|
|
|
* 提醒 = VALARM 的 TRIGGER(提前多久);不提醒 = 不写 VALARM
|
|
|
|
|
|
* 状态 = STATUS(CONFIRMED / TENTATIVE / CANCELLED)
|
|
|
|
|
|
* 忙闲 = TRANSP(OPAQUE=忙 / TRANSPARENT=空闲)
|
|
|
|
|
|
* 备注 = DESCRIPTION
|
|
|
|
|
|
* 附件 = ATTACH
|
|
|
|
|
|
*
|
|
|
|
|
|
* 用法(include 前设好):
|
|
|
|
|
|
* $evFields 正在编辑的日程(新建时传空数组)
|
|
|
|
|
|
* $evAllDay 全天的默认值(新建默认**不勾**,用户 2026-10-02 第 6 条)
|
2026-10-12 00:24:20 +08:00
|
|
|
|
* $evMvStyle 🔴 v43:「标签 62px 右对齐 + 冒号 + 控件」的**观影式**排版开关。
|
|
|
|
|
|
* 新建日程那个弹框要它(用户:日程新建页排版和观影/行程一样);
|
|
|
|
|
|
* 编辑页(`calendar/event.php`)继续用原来的 `.form-grid` 两列。
|
2026-10-03 08:18:05 +08:00
|
|
|
|
*/
|
|
|
|
|
|
$evF = is_array($evFields ?? null) ? $evFields : [];
|
|
|
|
|
|
$evAllDayDefault = (bool)($evAllDay ?? false);
|
|
|
|
|
|
$evIsAllDay = array_key_exists('all_day', $evF) ? !empty($evF['all_day']) : $evAllDayDefault;
|
2026-10-12 00:24:20 +08:00
|
|
|
|
/* 🔴 v43(用户 2026-10-11 第 5 条):观影式排版开关。 */
|
|
|
|
|
|
$evMv = !empty($evMvStyle);
|
|
|
|
|
|
/* 标签包装:观影式用 `.mv-row` + `.mv-lb`(冒号由 CSS ::after 给);
|
|
|
|
|
|
否则用原来的 `.field` + `<label>`。
|
|
|
|
|
|
⚠️ 抽成闭包是为了**不在下面每处 if/else 手抄两遍结构** ——
|
|
|
|
|
|
抄两遍必然有一天两边不同步(v37 那种"改了 A 忘了 B"的坑)。
|
2026-10-26 06:45:38 +08:00
|
|
|
|
⚠️ 「是否必填」作为**参数**传(不要用 `use` 捕获 —— 闭包定义时那个变量还没赋值,
|
|
|
|
|
|
捕获到的是 null,标记永远不出现)。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 v94(用户 2026-10-25):必填的表示法从「末尾加红色星号」改成
|
|
|
|
|
|
「标签本身红色加粗」,由 CSS 类 `.is-req` 驱动(样式见 `app.css` 末尾
|
|
|
|
|
|
「必填项统一标记」那段)。
|
|
|
|
|
|
⚠️ 第三个参数 v94 起从 `$star` 更名为 `$req`:它原来叫"画星",现在只表示
|
|
|
|
|
|
"这是必填" —— 名字不改会让后来者以为还在画星号,去 CSS 里找不存在的规则。 */
|
2026-10-12 15:31:03 +08:00
|
|
|
|
$evRowOpen = static function (string $full = '', bool $hidden = false) use ($evMv): string {
|
|
|
|
|
|
return '<div class="' . ($evMv ? 'mv-row' : 'field') . ($full !== '' ? ' ' . $full : '') . '"'
|
|
|
|
|
|
. ($hidden ? ' hidden' : '') . '>';
|
2026-10-12 00:24:20 +08:00
|
|
|
|
};
|
2026-10-12 15:31:03 +08:00
|
|
|
|
/* 重复规则**先算好**:下面"结束条件 / 重复次数 / 重复到"三行要不要默认藏起来,
|
|
|
|
|
|
取决于它(见 v44 第 2 条)。原来 `$rp` 是在「重复」那一行才 parse 的,
|
|
|
|
|
|
那三行排在它后面 ⇒ 拿不到。提到最前面,只算一次。 */
|
|
|
|
|
|
$evRp = \App\Repeat::parse((string)($evF['rrule'] ?? ''));
|
|
|
|
|
|
$evRepeating = (string)($evRp['freq'] ?? '') !== '';
|
2026-10-26 06:45:38 +08:00
|
|
|
|
$evLab = static function (string $text, string $for = '', bool $req = false) use ($evMv): string {
|
|
|
|
|
|
$cls = $req ? ' is-req' : '';
|
2026-10-12 00:24:20 +08:00
|
|
|
|
if ($evMv) {
|
|
|
|
|
|
// 观影式:标签是 <span class="mv-lb">,冒号由 CSS ::after 给
|
2026-10-26 06:45:38 +08:00
|
|
|
|
return '<span class="mv-lb' . $cls . '">' . $text . '</span>';
|
2026-10-12 00:24:20 +08:00
|
|
|
|
}
|
2026-10-26 06:45:38 +08:00
|
|
|
|
return '<label' . ($for !== '' ? ' for="' . e($for) . '"' : '')
|
|
|
|
|
|
. ($cls !== '' ? ' class="' . trim($cls) . '"' : '') . '>' . $text . '</label>';
|
2026-10-12 00:24:20 +08:00
|
|
|
|
};
|
2026-10-03 08:18:05 +08:00
|
|
|
|
?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen('full'); ?>
|
|
|
|
|
|
<?= $evLab('标题', 'ev-title', true) ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<input class="input" id="ev-title" name="title" required
|
|
|
|
|
|
value="<?= e((string)($evF['title'] ?? '')) ?>" placeholder="如:家长会">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen(); ?>
|
|
|
|
|
|
<?= $evLab('地点', 'ev-location') ?>
|
2026-10-14 01:20:40 +08:00
|
|
|
|
<?php /* 🔴 v47(用户 2026-10-13):「日程中,当我输入地点的时候,也应该调用高德的接口,
|
|
|
|
|
|
补齐详细地址。」⇒ 地点框挂高德联想。
|
|
|
|
|
|
⚠️ 日程表里**没有**单独的"详细地址"字段(地点就一栏),所以这里不做"回填",
|
|
|
|
|
|
只把**联想选中的正式地名**写回输入框 —— 价值是"把口语化的'学校三楼会议室'
|
|
|
|
|
|
换成高德认得的规范地名",后续要查经纬度/导航才查得到。
|
|
|
|
|
|
⚠️ 这段表单既在整页(各视图的日程弹框)也在 AJAX 片段里出现,
|
|
|
|
|
|
所以打好 `data-addr` 标记即可 —— 由 layout 的 loader 与
|
2026-10-20 21:35:47 +08:00
|
|
|
|
弹框打开时的 `fbLoadAddr(scope)` 负责绑定(与 person_picker 同一套)。
|
|
|
|
|
|
🔴 v68(用户 2026-10-20):「输入地点,应该调用高德接口,获得**准确的详细地址**,
|
|
|
|
|
|
现在这个功能不好用了。」
|
|
|
|
|
|
① 不好用的真根因不在这一行(是 `layout.php` 的加载器取了不带
|
|
|
|
|
|
`plugin=AMap.AutoComplete` 的 SDK 地址,见那里的注释);
|
|
|
|
|
|
② 「详细地址」这一条要额外做点事:这一栏**只有它一个字段**,
|
|
|
|
|
|
光把名字写回来,门牌号仍然没有 ⇒ 加 `data-addr-detail="1"`:
|
|
|
|
|
|
选中候选时把地址一并写进 value(`名字 · 门牌`),
|
|
|
|
|
|
并在这一行下面用一行灰字显示「省市区 · 门牌」。 */ ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<input class="input" id="ev-location" name="location"
|
2026-10-14 01:20:40 +08:00
|
|
|
|
value="<?= e((string)($evF['location'] ?? '')) ?>" placeholder="如:学校三楼会议室"
|
2026-10-20 21:35:47 +08:00
|
|
|
|
data-addr data-addr-detail="1">
|
2026-10-03 08:18:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen(); ?>
|
|
|
|
|
|
<?= $evLab('提醒') ?>
|
2026-10-06 03:14:18 +08:00
|
|
|
|
<?php /* v24 第 20 批 第 8 条:**多选**(用户原话:「一个日程,我可以选择让它
|
|
|
|
|
|
5分钟提醒,10分钟提醒等等。」)。
|
|
|
|
|
|
⚠️ 用 checkbox 而不是 `<select multiple>`:后者在手机上要"按住再点",
|
|
|
|
|
|
几乎没法用(任务共享那个 multiple 下拉就是因此被换掉的)。
|
|
|
|
|
|
⚠️ 字段名必须是 `reminder_minutes[]` —— Calendar::reminderMinutes() 认得数组。
|
2026-10-12 00:24:20 +08:00
|
|
|
|
写成 `reminder_minutes`(不带 [])会让 PHP 只留最后一个勾选。
|
|
|
|
|
|
🔴 v43(用户第 5 条):他要求把这一栏底下那句「多选与不提醒」的说明去掉
|
|
|
|
|
|
⇒ 这里删掉那个 `.tip`(多选语义由复选框本身表达)。 */
|
2026-10-06 03:14:18 +08:00
|
|
|
|
$curReminders = \App\Calendar::reminderList($evF['reminder_minutes'] ?? null); ?>
|
|
|
|
|
|
<div class="rem-picks">
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<?php foreach (\App\Calendar::REMINDERS as $mins => $word): ?>
|
2026-10-06 03:14:18 +08:00
|
|
|
|
<label class="chk-inline rem-pick">
|
|
|
|
|
|
<input type="checkbox" name="reminder_minutes[]" value="<?= (int)$mins ?>"
|
|
|
|
|
|
<?= in_array((int)$mins, $curReminders, true) ? 'checked' : '' ?>>
|
|
|
|
|
|
<span><?= e($word) ?></span>
|
|
|
|
|
|
</label>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<?php endforeach; ?>
|
2026-10-06 03:14:18 +08:00
|
|
|
|
</div>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<?php /* v24 第 5、6 条:起止各一个「日期 + 时分秒」合在一起的控件(全局统一),
|
|
|
|
|
|
不再拆成"日期一格 + 时刻一格"。两个控件长得一样,扫一眼就知道哪个是开始。 */ ?>
|
2026-10-04 10:46:50 +08:00
|
|
|
|
<?php /* 用户 2026-10-04 第 7 条:日程的起止也是一个**范围** ——
|
|
|
|
|
|
升级后由一个 Semi dateTimeRange 一次选完。服务端仍收两组 *_date/_hour/… 字段。 */ ?>
|
2026-10-06 12:08:40 +08:00
|
|
|
|
<?php /* 🔴 v24 第 21 批 第 7 条:「开始时间和结束时间那里,用我们统一的时间范围选择器
|
|
|
|
|
|
重做,现在功能无法使用。」
|
|
|
|
|
|
|
|
|
|
|
|
「功能无法使用」的真根因(真机探针实测出来的,不是猜的):
|
|
|
|
|
|
app.js 的 upgradeRange() 有一道「**两端都得可见**才升级成范围控件」的判断
|
|
|
|
|
|
(`boxes.every(bx => bx.offsetParent !== null)`)。而这一版**结束那一端默认
|
|
|
|
|
|
带 `hidden`**(要点「+ 添加结束时间」才出现)→ 判断永远不成立 →
|
|
|
|
|
|
范围控件**从来没被挂上去过**(实测 data-semi-range-done 恒为 null)。
|
|
|
|
|
|
更糟的是 CSS 还有 `html.js .dt-range:not(.is-semi-range) > .dt-input
|
|
|
|
|
|
{ visibility: hidden }` —— 两端于是都是**不可见**的:
|
|
|
|
|
|
屏幕上一片空白、点哪儿都没反应。这就是「无法使用」的全部。
|
|
|
|
|
|
|
|
|
|
|
|
修法:**结束那一端不再默认藏起来**,范围控件一次性就挂上。
|
|
|
|
|
|
起止成对本来就该一起填。想表达"只有一个时刻"的话,范围控件 clear 一下即可。
|
|
|
|
|
|
⚠️ 顺带删掉「+ 添加结束时间 / 去掉结束时间」那套开关:
|
2026-10-12 00:24:20 +08:00
|
|
|
|
它切换显隐会让范围控件反复重挂;范围控件自己就能表达"没有结束"。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 v43(用户 2026-10-11 第 5 条):「开始和结束时间也没有用我们最新的控件,
|
|
|
|
|
|
直接就是四个字"时间范围"。」
|
|
|
|
|
|
—— 两处真缺陷一起修:
|
|
|
|
|
|
① 这个字段块**没传 `$dtPlugin='antd'`** ⇒ 用户看到的还是年/月/日 + 时/分
|
|
|
|
|
|
五个原生下拉,而不是他点名要的 Ant Design 控件;
|
|
|
|
|
|
② 标签写的是「时间范围」四个字,没告诉人"这是开始 / 结束"。
|
|
|
|
|
|
⇒ `$dtPlugin='antd'`(与观影/行程同一套:面板有可点的时/分列、中文「确定」),
|
|
|
|
|
|
标签改「开始 / 结束」(并去掉那颗必填星号的位置歧义 —— 只标在开始上)。
|
|
|
|
|
|
⚠️ 契约一字未改:隐藏字段仍是 `*_date/_hour/_minute`;antd 拉不动时
|
2026-10-12 15:31:03 +08:00
|
|
|
|
自动退回自建下拉(渐进增强)。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 v44(用户 2026-10-12 第 2 条):「开始/结束,改为:日期范围:。
|
|
|
|
|
|
之前的日期选择控件还有,需要删除。」
|
|
|
|
|
|
—— 用户要三种东西:① 标签「日期范围」;② 标签与**最新控件同行**;
|
|
|
|
|
|
③ 原生那套(年/月/日 + 时/分 五个下拉)**真的消失**。
|
|
|
|
|
|
|
|
|
|
|
|
🔴🔴 **"还在"的真根因(结构性,不是样式没写)**:
|
|
|
|
|
|
观影那对是 `‹div.mv-row.dt-range› ‹div.dt-input›`(**直接子**),
|
|
|
|
|
|
而日程这对是 `‹div.dt-range› ‹div.field.ev-dt› ‹div.dt-input›`
|
|
|
|
|
|
—— `.dt-input` 是**孙子**。
|
|
|
|
|
|
于是那条最常见的收起规则 `.dt-range.is-antd > .dt-input`(**直接子**选择器)
|
|
|
|
|
|
**在日程上根本不命中** ⇒ antd 挂上了、原生五个下拉照样显示
|
|
|
|
|
|
(用户看到两个控件并排,"之前的日期选择控件还有")。
|
|
|
|
|
|
⚠️ 与 v43 纪念日那次是**同一个家族**:结构一变,直接子选择器就静默失效。
|
|
|
|
|
|
⇒ 两手都做:① 把日程的结构改成与观影**一致**(`.dt-input` 直接子);
|
|
|
|
|
|
② CSS 里把 `>` 放宽成后代选择器(0,2,0 → 仍高于基类),
|
|
|
|
|
|
将来结构再变也不会又冒出第二个控件。
|
|
|
|
|
|
|
|
|
|
|
|
⇒ 形态:由 `_datetime.php` 的 `$dtLabel` 把「日期范围:」
|
|
|
|
|
|
**内联在控件那一行**(不靠宿主的行结构),一个 `.mv-lb` 挂在
|
|
|
|
|
|
`.dt-input` 里 → 三样天然同行,宽度不够时整体换行。 */ ?>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="dt-range<?= $evMv ? ' mv-row is-tagged' : '' ?>">
|
|
|
|
|
|
<?php /* ⚠️ 标签只有**一个**,挂在**第一个端点**上(不是各挂各的):
|
2026-10-06 12:08:40 +08:00
|
|
|
|
升级成一个范围控件之后,"开始"与"结束"就是同一个控件的两个端点,
|
2026-10-12 15:31:03 +08:00
|
|
|
|
两个标签会变成"看着像两个字段、其实是一个"的错觉。
|
|
|
|
|
|
⚠️ 观影式:标签由 `_datetime.php` 内联(`$dtLabel`)—— 要的是与控件同行;
|
|
|
|
|
|
两列式(编辑整页):标签仍是 `.dt-range-label`,在两端之上。 */ ?>
|
|
|
|
|
|
<?php if (!$evMv): ?>
|
2026-10-26 06:45:38 +08:00
|
|
|
|
<span class="dt-range-label is-req">日期范围</span>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php endif; ?>
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php $dtName = 'starts_at'; $dtId = 'ev-start';
|
|
|
|
|
|
$dtValue = $evF['starts_at'] ?? null; $dtRequired = true;
|
|
|
|
|
|
$dtRange = 'start'; $dtPlugin = 'antd'; $dtClass = 'field ev-dt'; $dtFieldId = '';
|
2026-10-26 06:45:38 +08:00
|
|
|
|
if ($evMv) { $dtLabel = '日期范围'; $dtLabelReq = true; }
|
2026-10-12 15:31:03 +08:00
|
|
|
|
require __DIR__ . '/../_datetime.php'; ?>
|
|
|
|
|
|
<?php $dtName = 'ends_at'; $dtId = 'ev-end';
|
|
|
|
|
|
$dtValue = $evF['ends_at'] ?? null; $dtRequired = false;
|
|
|
|
|
|
$dtRange = 'end'; $dtPlugin = 'antd';
|
|
|
|
|
|
$dtClass = 'field ev-dt'; $dtFieldId = 'ev-end-field';
|
|
|
|
|
|
/* 结束端点不重复标签(同一个范围控件,标签已经挂在开始那一端上) */
|
2026-10-26 06:45:38 +08:00
|
|
|
|
$dtLabel = ''; $dtLabelReq = false;
|
2026-10-12 15:31:03 +08:00
|
|
|
|
require __DIR__ . '/../_datetime.php'; ?>
|
2026-10-04 10:46:50 +08:00
|
|
|
|
</div><?php /* /dt-range */ ?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php /* 🔴 v43(用户第 5 条):他要求把「结束留空即无明确结束」的那条提示去掉
|
|
|
|
|
|
⇒ 那句 `.field-hint` 整块删除(不再输出)。 */ ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen(); ?>
|
|
|
|
|
|
<label class="chk-inline">
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<input type="checkbox" id="ev-allday" name="all_day" value="1"
|
|
|
|
|
|
<?= $evIsAllDay ? 'checked' : '' ?>>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<span>全天</span>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
</label>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php /* 🔴 v43(用户第 5 条):他要求把「全天只管日期、不管几点」的说明也去掉
|
|
|
|
|
|
⇒ 那句 `.field-hint` 整块删除。 */ ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-03 11:30:48 +08:00
|
|
|
|
<?php /* 用户 2026-10-03 第 5、6 条:重复日程。
|
|
|
|
|
|
放在「全天」之后的自然位置:先定"哪一天/几点",再定"要不要重复"。
|
|
|
|
|
|
周期用 FREQ 记号,结束条件三档(一直 / N 次 / 到某天),另加"工作日"。 */ ?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen(); ?>
|
|
|
|
|
|
<?= $evLab('重复', 'ev-freq') ?>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
<select class="select" id="ev-freq" name="freq">
|
|
|
|
|
|
<?php foreach (\App\Repeat::FREQS as $k => $w): ?>
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<option value="<?= e($k) ?>"<?= (string)$evRp['freq'] === (string)$k ? ' selected' : '' ?>><?= e($w) ?></option>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php /* 🔴 v44(用户 2026-10-12 第 2 条):「重复这里,只有选择重复的时候,
|
|
|
|
|
|
下面的结束条件和重复次数、重复到,这几个选项才出现,否则就隐藏。」
|
|
|
|
|
|
⇒ 三行**服务端**就按"是否重复"给出 `hidden`(不是只靠 JS):
|
|
|
|
|
|
· 回填编辑(本来就有 rrule)时它们该出现;
|
|
|
|
|
|
· 新建(默认"不重复")时它们从一开始就是隐藏的 —— 页面上不会闪一下才收起来。
|
|
|
|
|
|
⚠️ 行**本身**也藏:原来只有行**里面**那个 box 带 hidden,
|
|
|
|
|
|
于是标签还孤零零留在表单里(用户看到的"还在")。
|
|
|
|
|
|
⚠️ 用户同条还要「重复次数(含第一次)」那个括号去掉 ⇒ 标签改「重复次数」。 */ ?>
|
|
|
|
|
|
<?php echo $evRowOpen('', !$evRepeating); ?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?= $evLab('结束条件', 'ev-rep-end') ?>
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<div id="ev-rep-end-box"<?= $evRepeating ? '' : ' hidden' ?>>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<select class="select" id="ev-rep-end" name="rep_end">
|
|
|
|
|
|
<?php foreach (\App\Repeat::ENDS as $k => $w): ?>
|
|
|
|
|
|
<option value="<?= e($k) ?>"><?= e($w) ?></option>
|
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php echo $evRowOpen('', !$evRepeating || (int)$evRp['count'] <= 0); ?>
|
|
|
|
|
|
<?= $evLab('重复次数', 'ev-rep-count') ?>
|
|
|
|
|
|
<div id="ev-rep-count-box"<?= ($evRepeating && (int)$evRp['count'] > 0) ? '' : ' hidden' ?>>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<input class="input" type="number" min="1" max="2000" id="ev-rep-count" name="rep_count"
|
2026-10-12 15:31:03 +08:00
|
|
|
|
value="<?= (int)($evRp['count'] ?: 10) ?>">
|
2026-10-12 00:24:20 +08:00
|
|
|
|
</div>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php echo $evRowOpen('', !$evRepeating || (string)$evRp['until'] === ''); ?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?= $evLab('重复到', 'ev-rep-until') ?>
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<div id="ev-rep-until-box"<?= ($evRepeating && (string)$evRp['until'] !== '') ? '' : ' hidden' ?>>
|
2026-10-12 21:40:53 +08:00
|
|
|
|
<?php /* 🔴 v45(用户 2026-10-12 第 1 条):「添加日程这里,当选择了重复,
|
|
|
|
|
|
并且选择了重复到某天为止,这时候重复到会出现,有一个日历选择框,
|
|
|
|
|
|
这个日历选择框也改为我们最新的控件。」
|
|
|
|
|
|
⇒ 把原来那个原生 `<input type="date">` 换成 AntD **纯日期** DatePicker。
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ 做法与「纪念日 → 日期」完全同一套(v42/v43 已验证):
|
|
|
|
|
|
· 外层 `.dt-input` + `data-antd-date="1"` → app.js 的 `mountAntdDate` 接管;
|
|
|
|
|
|
· 值载体仍是**同一个** `name="rep_until"` 的 `<input type="date">`,
|
|
|
|
|
|
只是被 `.dt-native` 包起来(否则那条"收起原生框"的 CSS 不命中 ⇒
|
|
|
|
|
|
会出现"多了一个控件",正是 v43 纪念日踩过的坑);
|
|
|
|
|
|
· 服务端契约**一字不改**:`Repeat::build($_POST)` 照旧读 `rep_until`。
|
|
|
|
|
|
⚠️ 千万别给这个 `.dt-input` 加 `data-dt="…"`:那是"年/月/日+时/分"那套
|
|
|
|
|
|
四字段契约的标记,加上去会被 `upgrade()` 抢走、反而绑错处理器。 */ ?>
|
|
|
|
|
|
<div class="dt-input dt-antd-single" data-antd-date="1" id="ev-rep-until-wrap">
|
|
|
|
|
|
<span class="dt-native">
|
|
|
|
|
|
<input type="date" class="dt-date" id="ev-rep-until" name="rep_until"
|
|
|
|
|
|
value="<?= e((string)($evRp['until'] ?? '')) ?>" aria-label="重复到">
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
</div>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-14 01:20:40 +08:00
|
|
|
|
<?php /* 🔴 v47(用户 2026-10-13):「日程的那个状态,什么确定、待定、取消,
|
|
|
|
|
|
我觉得没有什么意义,把它给删掉吧,不要了。」
|
|
|
|
|
|
⇒ 「状态」整块**删除**。
|
|
|
|
|
|
⚠️ 服务端契约**刻意保留**(用户明确说"数据库可以保留,后续会有一个整体的清理"):
|
|
|
|
|
|
- `events.status` 列留着、不删;
|
|
|
|
|
|
- `Calendar::save()` 收到不带 status 的表单时,用**原值**(更新)或
|
|
|
|
|
|
`'confirmed'`(新建),与删掉这一栏之前**完全一致** ——
|
|
|
|
|
|
不会因为删了控件就把已有日程的状态改写掉(见 index.php 里那两处
|
|
|
|
|
|
`(string)($ev2['status'] ?? 'confirmed')`)。
|
|
|
|
|
|
- 导出 iCalendar 时 STATUS 照旧按原值走,别人的日历里不会看到状态变化。
|
|
|
|
|
|
下方原来还有一段给 `ev-status` 的联动脚本,也一并删。 */ ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php /* 🔴 v44(用户 2026-10-12 第 2 条):「这段时间算忙碌,这一块直接给它去掉就行了,
|
|
|
|
|
|
没有什么用。」⇒ 「这段时间算 / 忙碌 / 空闲」整块删除。
|
|
|
|
|
|
⚠️ 服务端契约**没变**:`transp` 字段没随表单提交时,`!empty($_POST['transp'])`
|
|
|
|
|
|
一律得 false(= 忙碌),与原来的默认值一致 —— 不会因为删了这一块
|
|
|
|
|
|
而把已有日程的忙闲改掉(更新时传的是 `(int)($ev2['transp'] ?? 0)` 原值)。
|
|
|
|
|
|
下方 script 里原来还有一段给 `ev-transp` 的联动,也一并删。 */ ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen('full'); ?>
|
|
|
|
|
|
<?= $evLab('备注', 'ev-note') ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
<textarea class="input" id="ev-note" name="note" rows="3"
|
|
|
|
|
|
placeholder="要带什么、跟谁一起…"><?= e((string)($evF['note'] ?? '')) ?></textarea>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php echo $evRowOpen('full'); ?>
|
|
|
|
|
|
<?= $evLab('附件(可多选)') ?>
|
2026-10-06 12:08:40 +08:00
|
|
|
|
<?php /* v24 第 21 批 第 7 条:统一成「点击或拖动进行上传」的框。
|
|
|
|
|
|
⚠️ 文件框的 id 保持 `ev-attach`(原来就叫这个)—— e2e 与部署断言里
|
|
|
|
|
|
有按 id 定位的写法,改名会把它们静默打成假红。 */
|
|
|
|
|
|
$sdName = 'attach[]'; $sdId = 'ev-attach'; $sdSlot = 'photo';
|
|
|
|
|
|
require __DIR__ . '/../_stage_drop.php'; ?>
|
2026-10-03 08:18:05 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
(function () {
|
|
|
|
|
|
/* 「全天」勾上就把两个时刻控件的**时间部分**收起来 —— 日期还得留着。
|
|
|
|
|
|
只藏 .dt-time(时/分/秒那一段),.dt-date 是日期,藏了就没法选哪天了。 */
|
|
|
|
|
|
var box = document.getElementById('ev-allday');
|
|
|
|
|
|
if (!box) return;
|
|
|
|
|
|
function sync() {
|
|
|
|
|
|
Array.prototype.forEach.call(document.querySelectorAll('[data-dt] .dt-time'), function (el) {
|
|
|
|
|
|
el.hidden = box.checked;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
box.addEventListener('change', sync);
|
|
|
|
|
|
sync();
|
2026-10-03 11:30:48 +08:00
|
|
|
|
|
2026-10-06 12:08:40 +08:00
|
|
|
|
/* ⚠️ v24 第 21 批 第 7 条:原来这里有一整段「结束时间显隐 + 跟着开始时间走」的 JS。
|
2026-10-12 00:24:20 +08:00
|
|
|
|
现在起止两端**始终可见**,并且由范围控件统一接管(一次选完两端),
|
2026-10-06 12:08:40 +08:00
|
|
|
|
所以那段"同步两端"的逻辑整个删掉 —— 留着不但没用,还会和范围控件抢着改那两个
|
|
|
|
|
|
原生字段(两处都写 → 值互相覆盖)。范围控件选完会自己把两端分别写回原生字段
|
|
|
|
|
|
(见 app.js 的 onRange → writeDT),服务端契约不变。 */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
|
|
|
|
|
|
/* 重复:选了周期才显示"结束条件";结束条件选"次数"才显示次数框、选"到某天"才显示日期框。
|
2026-10-12 15:31:03 +08:00
|
|
|
|
三行默认都 hidden —— 不重复时一个都不该出现(少即是清楚)。
|
|
|
|
|
|
🔴 v44(用户第 2 条):藏的是**整行**(`.mv-row` / `.field`),不是行里那个 box ——
|
|
|
|
|
|
只藏 box 的话标签还孤零零留在表单里。行 = box 的 `closest('.mv-row, .field')`。 */
|
2026-10-03 11:30:48 +08:00
|
|
|
|
var freq = document.getElementById('ev-freq');
|
|
|
|
|
|
var endBox = document.getElementById('ev-rep-end-box');
|
|
|
|
|
|
var endSel = document.getElementById('ev-rep-end');
|
|
|
|
|
|
var cntBox = document.getElementById('ev-rep-count-box');
|
|
|
|
|
|
var untilBox = document.getElementById('ev-rep-until-box');
|
2026-10-12 15:31:03 +08:00
|
|
|
|
function rowOf(el) {
|
|
|
|
|
|
return el && el.closest ? el.closest('.mv-row, .field') : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
function toggle(el, on) {
|
|
|
|
|
|
if (!el) { return; }
|
|
|
|
|
|
el.hidden = !on;
|
|
|
|
|
|
var row = rowOf(el);
|
|
|
|
|
|
if (row) { row.hidden = !on; } // 连带整行一起显隐
|
|
|
|
|
|
}
|
2026-10-03 11:30:48 +08:00
|
|
|
|
function syncRep() {
|
2026-10-12 15:31:03 +08:00
|
|
|
|
if (!freq || !endBox) { return; }
|
2026-10-03 11:30:48 +08:00
|
|
|
|
var repeating = freq.value !== '';
|
2026-10-12 15:31:03 +08:00
|
|
|
|
toggle(endBox, repeating);
|
2026-10-03 11:30:48 +08:00
|
|
|
|
var how = endSel ? endSel.value : 'never';
|
2026-10-12 15:31:03 +08:00
|
|
|
|
toggle(cntBox, repeating && how === 'count');
|
|
|
|
|
|
toggle(untilBox, repeating && how === 'until');
|
2026-10-03 11:30:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (freq) { freq.addEventListener('change', syncRep); }
|
|
|
|
|
|
if (endSel) { endSel.addEventListener('change', syncRep); }
|
|
|
|
|
|
// 回填:编辑一条已有的重复日程时,把结束条件按库里的值选对
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php if ((int)$evRp['count'] > 0): ?>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
if (endSel) { endSel.value = 'count'; }
|
2026-10-12 15:31:03 +08:00
|
|
|
|
<?php elseif ((string)$evRp['until'] !== ''): ?>
|
2026-10-03 11:30:48 +08:00
|
|
|
|
if (endSel) { endSel.value = 'until'; }
|
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
|
syncRep();
|
|
|
|
|
|
|
|
|
|
|
|
/* 「全天」+「重复」的组合提示:重复日程必须有开始日期,
|
|
|
|
|
|
否则展开时找不到锚点(后端会当成"不重复"处理)。 */
|
|
|
|
|
|
var startDate = document.querySelector('[data-dt] input.dt-date');
|
|
|
|
|
|
if (freq && startDate) {
|
|
|
|
|
|
freq.addEventListener('change', function () {
|
|
|
|
|
|
if (freq.value !== '' && startDate.value === '') {
|
|
|
|
|
|
startDate.setCustomValidity('重复日程要先选开始日期');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
startDate.setCustomValidity('');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-10-03 08:18:05 +08:00
|
|
|
|
})();
|
|
|
|
|
|
</script>
|
2026-10-26 06:45:38 +08:00
|
|
|
|
<?php /* 🔴 v94:顺手去掉了 unset 列表里的 `$evLabelStar` —— 它在整个仓库里
|
|
|
|
|
|
**从来没有被赋过值**(只有这一行 unset 提到它),是历史遗留的死引用。 */ ?>
|
2026-10-12 00:24:20 +08:00
|
|
|
|
<?php unset($evF, $evAllDayDefault, $evIsAllDay, $evFields, $evAllDay, $evMv, $evMvStyle,
|
2026-10-26 06:45:38 +08:00
|
|
|
|
$evRowOpen, $evLab, $evRp, $evRepeating); ?>
|