v44 第 44 批:界面 5 条 + 移动端 API v1 全量

界面(用户 2026-10-12 第 1~5 条)
1. 新建日程「日历本」并入 .cs 自绘下拉,颜色画进候选项,三字与下拉同行。
2. 新建日程「开始/结束」改「日期范围:」,删旧日期控件;
   重复相关三行仅选重复时出现;删「(含第一次)」与「这段时间算忙碌」。
3. 条目浮层加「地点」、去掉「状态」行;首页红线按分钟定位(原只取整小时);
   去掉左侧红点只留红线。
4. 任务页删掉状态说明提示(STATUS_HINT 三值清空)。
5. 新建任务:标题在前树框在后;截止时间改最新日历控件;负责人默认自己;
   删冗余提示;「上面要做什么」→「任务名称」;清理括号说明。

移动端 API(用户第 6 条:导航模块除外,其余全量)
- 新增 Bearer 令牌鉴权(api_tokens 表,Schema v32),与登录口令 / DAV 口令三套分立。
- Api.php 内核(鉴权/取参/信封/分页/分发 + _method 覆写)+
  ApiHandler.php 17 条资源 + ApiToken.php + api.php 入口。
- 路由:router.php / .htaccess / index.php 三处 /api/ 兜底(部署脚本自动追加线上规则)。
- 个人设置新增「App 接口令牌」卡;docs/API.md 接口文档;
  docs/API-QUESTION-LIST.md 自主决策与待确认缺口清单。

验证:本地 e2e 1510/0、v43 真机 33/0、v43 反向 9/0、
v44 真机 41/0、v44 API 63/0、v44 反向 19/0;全流水线 PUSH_RC=0。
This commit is contained in:
2026-10-12 15:31:03 +08:00
parent 8c651b43eb
commit 075ac6bbeb
21 changed files with 2886 additions and 185 deletions
+70 -6
View File
@@ -1308,8 +1308,11 @@
/* 🔴 v42(用户第 8 条):单个**纯日期**控件(纪念日的「日期」)——
`[data-antd-date]`。它挂的是不带 showTime 的单 DatePicker。 */
var antdDates = document.querySelectorAll('[data-antd-date]');
if (antdHosts.length || antdDateRanges.length || antdDates.length) {
bootAntd(antdHosts, antdDateRanges, antdDates);
/* 🔴 v44(用户第 5 条):单个**带时刻**的控件(任务「截止时间」)——
`[data-dt-antd-single]`。挂的是带 showTime 的单 DatePicker。 */
var antdSingles = document.querySelectorAll('[data-dt-antd-single]');
if (antdHosts.length || antdDateRanges.length || antdDates.length || antdSingles.length) {
bootAntd(antdHosts, antdDateRanges, antdDates, antdSingles);
}
/* 🔴🔴 v42(用户 2026-10-11 第 2 条)——**关键时序修复**:
@@ -1332,7 +1335,8 @@
window.fbBootAntd = function () {
bootAntd(document.querySelectorAll('[data-dt-antd]'),
document.querySelectorAll('[data-antd-daterange]'),
document.querySelectorAll('[data-antd-date]'));
document.querySelectorAll('[data-antd-date]'),
document.querySelectorAll('[data-dt-antd-single]'));
return true;
};
@@ -1618,11 +1622,12 @@
⚠️ 这个适配层**不认识的页面不受影响**:没有 `[data-dt-antd]` 就直接返回。
============================================================================ */
function bootAntd(hosts, dateRanges, dates) {
function bootAntd(hosts, dateRanges, dates, singles) {
hosts = hosts || [];
dateRanges = dateRanges || [];
dates = dates || [];
if (!hosts.length && !dateRanges.length && !dates.length) { return; }
singles = singles || [];
if (!hosts.length && !dateRanges.length && !dates.length && !singles.length) { return; }
var meta = document.querySelector('meta[name="fb-antd"]');
if (!meta) { return; }
var conf;
@@ -1667,6 +1672,9 @@
Array.prototype.forEach.call(dates, function (el) {
if (mountAntdDate(el)) { done++; }
});
Array.prototype.forEach.call(singles, function (box) {
if (mountAntdSingleDT(box)) { done++; }
});
if (window.console && done) { console.info('AntD 日期控件已挂上 ' + done + ' 处'); }
}).catch(function (err) {
// 拉不动就留在自建下拉上 —— 渐进增强的兜底,不弹任何打扰
@@ -1864,6 +1872,61 @@
return true;
}
/* 🔴 v44(用户 2026-10-12 第 5 条):「截止时间也用我们最新的日历控件,
记得把现在这个控件删掉。」
⇒ 单个**带时刻**的 AntD DatePicker(`showTime`),不是 RangePicker ——
任务的「截止时间」只有一个时刻,套范围控件会多一个空端点。
操作对象是 `.dt-input[data-dt]`(隐藏 `*_date` + `*_hour/_minute` 是值载体),
与 `mountAntd()`(成对范围)同一套「选完写回原生字段」的路子,
所以**服务端契约一字不改**。
⚠️ 原生那几档下拉的"删除"由 CSS 负责(`.dt-input.is-antd > .dt-native{display:none}`),
这里只管加 `.is-antd` 类 + 挂控件。 */
function mountAntdSingleDT(box) {
if (!box || box.getAttribute('data-antd-done')) { return false; }
var native = box.querySelector('.dt-native');
if (!native) { return false; }
var host = document.createElement('span');
host.className = 'dt-antd';
box.insertBefore(host, box.firstChild);
function cur() {
var s = readDT(box).trim();
var m = s.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/);
return m ? m[1] + '-' + m[2] + '-' + m[3] + ' ' + m[4] + ':' + m[5] : '';
}
var last = '';
function writeBack(str) {
var s = (str || '');
if (s === last) { return; }
last = s;
writeDT(box, s); // 写回隐藏四字段
if (box.__fbSyncParts) { box.__fbSyncParts(); }
box.classList.toggle('has-value', !!s);
}
var v0 = cur();
try {
var picker = React.createElement(antd.DatePicker, {
showTime: { format: 'HH:mm' },
format: 'YYYY-MM-DD HH:mm',
allowClear: true,
placeholder: '选择时间',
defaultValue: v0 ? window.dayjs(v0, 'YYYY-MM-DD HH:mm') : undefined,
onChange: function (val, str) { writeBack(str); }
});
var loc = (window.antd.locales && window.antd.locales.zh_CN) || undefined;
if (loc) { picker = React.createElement(antd.ConfigProvider, { locale: loc }, picker); }
ReactDOM.createRoot(host).render(picker);
} catch (e) {
if (window.console) { console.warn('antd 单点时间控件挂载失败,留在自建下拉:', e && e.message); }
host.parentNode.removeChild(host);
return false;
}
box.classList.add('is-antd');
box.setAttribute('data-antd-done', '1');
return true;
}
function upgrade(box) {
if (box.getAttribute('data-semi-done')) { return; }
// 范围对的成员由 upgradeRange 统一处理
@@ -2065,7 +2128,8 @@
window.fbBootAntd = function () {
bootAntd(document.querySelectorAll('[data-dt-antd]'),
document.querySelectorAll('[data-antd-daterange]'),
document.querySelectorAll('[data-antd-date]'));
document.querySelectorAll('[data-antd-date]'),
document.querySelectorAll('[data-dt-antd-single]'));
return true;
};