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:
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
require __DIR__ . '/app/bootstrap.php';
|
||||
|
||||
use App\Account;
|
||||
use App\Api;
|
||||
use App\Attachment;
|
||||
use App\Auth;
|
||||
use App\Birthday;
|
||||
@@ -121,6 +122,22 @@ $r = isset($_GET['r']) ? trim((string)$_GET['r'], '/') : 'home';
|
||||
$r = $r === '' ? 'home' : $r;
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||||
|
||||
/* 🔴 v44(用户 2026-10-12 第 6 条):移动端 API 也会走到这里 ——
|
||||
`?r=api/v1/tasks` 这种形式(个别网络库 / 代理会把 PATH_INFO 吃掉,
|
||||
只留 query)。⇒ 必须在**登录门槛之前**交给 API 内核,否则未带 session
|
||||
的 App 请求会被 302 到登录页(拿到一坨 HTML,JSON 解析失败)。
|
||||
⚠️ 这里**不 require api.php**:那个文件会再 require 一次 bootstrap.php,
|
||||
导致 `Constant FB_ROOT already defined` 警告(实测过)。
|
||||
bootstrap 在 index.php 开头已经加载,直接调内核即可。
|
||||
⚠️ 只认 `api/` 前缀,别的一律照旧走网页路由。 */
|
||||
if (strpos($r, 'api/') === 0) {
|
||||
// `$r` 形如 `api/v1/tasks` ⇒ 去掉 `api/` 四字、补回 `/api/` 前缀,
|
||||
// 得到内核认识的标准路径 `/api/v1/tasks`(与 .htaccess/router.php 同一口径)。
|
||||
$_SERVER['REQUEST_URI'] = '/api/' . substr($r, 4);
|
||||
Api::dispatch();
|
||||
exit;
|
||||
}
|
||||
|
||||
$publicRoutes = ['auth/login'];
|
||||
if (!Auth::check() && !in_array($r, $publicRoutes, true)) {
|
||||
redirect('auth/login');
|
||||
@@ -286,10 +303,17 @@ function render_me_settings(array $person, array $errors = []): void
|
||||
// 通讯录同步范围要和名册页**完全一致**(用户 2026-10-06 第 22 批确认):
|
||||
// 名册页看到谁就同步谁。这里把人数带过去,用户当场就能对上。
|
||||
'davRosterN' => PersonRoster::countFor($familyId, $me),
|
||||
/* 🔴 v44(用户 2026-10-12 第 6 条):移动端 API 令牌。
|
||||
⚠️ 明文同样只在**一次性会话槽位**里取一次(`api_plain`),
|
||||
取完后面 unset —— 与 DAV 口令同一条纪律。 */
|
||||
'apiTokens' => \App\ApiToken::listFor($me),
|
||||
'apiPlain' => (string)($_SESSION['api_plain'] ?? ''),
|
||||
'apiLabel' => (string)($_SESSION['api_plain_label'] ?? ''),
|
||||
'apiBase' => rtrim((string)fb_config('base_url', ''), '/'),
|
||||
], 'settings');
|
||||
// ⚠️ 取完即清:明文口令只该被看到一次(刷新页面就没了)。
|
||||
// ⚠️ 取完即清:明文令牌只该被看到一次(刷新页面就没了)。
|
||||
// 放在 View::render **之后** —— 早了就拿不到值了。
|
||||
unset($_SESSION['dav_plain']);
|
||||
unset($_SESSION['dav_plain'], $_SESSION['api_plain'], $_SESSION['api_plain_label']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4633,6 +4657,29 @@ $want = array_keys($want);
|
||||
redirect('settings/me');
|
||||
break;
|
||||
|
||||
/* 🔴 v44(用户 2026-10-12 第 6 条):移动端 API 令牌的**签发 / 吊销**。
|
||||
与 DAV 那两条同一个形态(明文进一次性会话槽位、只显示一次)。 */
|
||||
case 'settings/api_token':
|
||||
case 'settings/api_revoke':
|
||||
$me = (int)Auth::personId();
|
||||
Auth::requireWrite();
|
||||
csrf_check();
|
||||
if ($r === 'settings/api_token') {
|
||||
$label = trim((string)($_POST['label'] ?? ''));
|
||||
$_SESSION['api_plain'] = \App\ApiToken::issue($me, $label);
|
||||
$_SESSION['api_plain_label'] = $label;
|
||||
flash('ok', 'API 令牌已生成(只显示这一次,请立刻复制到 App 里)。');
|
||||
} elseif ((int)($_POST['id'] ?? 0) > 0) {
|
||||
\App\ApiToken::revoke($me, (int)$_POST['id']);
|
||||
flash('ok', '这枚 API 令牌已吊销。');
|
||||
} else {
|
||||
\App\ApiToken::revokeAll($me);
|
||||
unset($_SESSION['api_plain'], $_SESSION['api_plain_label']);
|
||||
flash('ok', '全部 API 令牌已吊销,所有 App 都需要重新登录。');
|
||||
}
|
||||
redirect('settings/me', [], 'api');
|
||||
break;
|
||||
|
||||
case 'calendar/calendars':
|
||||
$familyId = (int)Auth::familyId();
|
||||
$me = (int)Auth::personId();
|
||||
|
||||
Reference in New Issue
Block a user