界面(用户 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。
106 lines
6.9 KiB
ApacheConf
106 lines
6.9 KiB
ApacheConf
# 家书 FamilyBook · Apache 重写规则
|
||
#
|
||
# ⚠️ 这个文件**不随包上线**(familybook_push.sh 的打包白名单里没有它)。
|
||
# 原因:线上站点根那份 .htaccess 是**宝塔面板生成的**(PHP 版本段、防盗链、
|
||
# 缓存段、伪静态…),整份覆盖会把面板的东西清空,而且面板下次重写还会改回来,
|
||
# 变成"时好时坏"。
|
||
# /dav/ 与 /carddav/ 的重写规则由 `familybook_deploy.sh` 第 5c 段**追加**到线上那份里
|
||
# (带 `# >>> FamilyBook CalDAV` 标记,幂等)。
|
||
#
|
||
# 那这份文件是干什么用的?
|
||
# · 新建站点(没有宝塔那层)时,可直接把它作为站点根的 .htaccess;
|
||
# · 它是那段规则的**唯一书面来源**,push 脚本会断言部署脚本里的规则串
|
||
# 与它完全一致(防两处漂移)。
|
||
#
|
||
# 只做一件事:把 /dav/ 与 /carddav/ 开头的 URL 分别交给 dav.php / carddav.php。
|
||
# 其余一律不动 —— index.php 那套 ?r=xxx 路由不依赖重写,
|
||
# 少写规则就少一处"上线才发现 404"的地方。
|
||
|
||
<IfModule mod_rewrite.c>
|
||
RewriteEngine On
|
||
|
||
# 🔴 v31:`/.well-known/*` 是 RFC 6764 规定的 DAV 发现入口,客户端**第一句**就问这里。
|
||
# ⚠️ 它必须排在 `^dav` / `^carddav` 之前 —— 这两条是前缀通配(`^dav(/.*)?$`),
|
||
# 而 `.well-known/caldav` 并不以 dav 开头,所以严格说互不干扰;
|
||
# 但放在最前面是"发现链优先于资源访问"的意图表达,后人加规则时不易搞错。
|
||
# 交给 dav.php / carddav.php 回 301(它们在**鉴权之前**处理这条路径:
|
||
# .well-known 是免鉴权入口,在这里 401 会让客户端以为"不支持 DAV")。
|
||
RewriteRule ^\.well-known/caldav$ dav.php [L,QSA]
|
||
RewriteRule ^\.well-known/carddav$ carddav.php [L,QSA]
|
||
|
||
# 🔴 v33:站点根的 **DAV 方法**也交给 dav.php(RFC 6764 允许从域名根发现)。
|
||
# 病根:`PROPFIND /` 被交给 index.php → 302 跳登录页 → Thunderbird 判定
|
||
# "这个域名下没有日历",用户报的就是「提示没有任何联系人和日程」。
|
||
# ⚠️ 必须用 `RewriteCond` 限住 **REQUEST_METHOD**:不加的话 `GET /` 也会被吞掉、
|
||
# 站点首页直接 404。只放行 PROPFIND/REPORT/OPTIONS 三种 DAV 方法。
|
||
# ⚠️ 这条要排在下面 `^dav` / `^carddav` **之前**(空 Pattern 匹配的是根,
|
||
# 与那两条前缀互不包含,但先写更清楚)。
|
||
RewriteCond %{REQUEST_METHOD} ^(PROPFIND|REPORT|OPTIONS)$ [NC]
|
||
RewriteRule ^$ dav.php [L,QSA]
|
||
|
||
# CalDAV:/dav/、/dav/3.ics/、/dav/3.ics/12.ics 全部交给 dav.php
|
||
RewriteRule ^dav(/.*)?$ dav.php [L,QSA]
|
||
|
||
# CardDAV(v24 第 22 批):/carddav/、/carddav/1.vcf/、/carddav/1.vcf/12.vcf 交给 carddav.php
|
||
# ⚠️ 两条规则**顺序无关但都必须有**:它们的前缀(dav vs carddav)互不包含,
|
||
# 不会互相抢;写成 `^dav` 在前是因为历史顺序,真要调也不能写成 `^dav(/|$)` 之外的
|
||
# 宽松形式 —— 那会把 /dav2/ 之类也吞进来。
|
||
RewriteRule ^carddav(/.*)?$ carddav.php [L,QSA]
|
||
|
||
# 🔴 v31:`/.well-known/caldav` 与 `/.well-known/carddav`(RFC 6764)。
|
||
# 标准客户端(DAVx⁵ / iOS / Evolution)添加账号时**第一句**就试这里 ——
|
||
# 原来这里 404,客户端直接判定"域名下没有 DAV 服务",连口令框都不弹。
|
||
# 症状正是用户报的「同步不出任何数据」(账号根本建不起来)。
|
||
# ⚠️ 这两条必须**排在 `^dav` / `^carddav` 之前**吗?不需要 ——
|
||
# `.well-known/...` 不以 dav/carddav 开头,两条规则互不干扰。
|
||
# 但**必须**在站点根的"真实文件"判断之前:Apache 对 .htaccess 里的
|
||
# RewriteRule 天然就是先于文件查找生效的,所以这里无需额外处理。
|
||
# 交给 dav.php / carddav.php 自己回 301(它们在鉴权**之前**处理,
|
||
# 因为 .well-known 是免鉴权入口 —— 在这里 401 会让客户端以为"不支持")。
|
||
RewriteRule ^\.well-known/caldav$ dav.php [L,QSA]
|
||
RewriteRule ^\.well-known/carddav$ carddav.php [L,QSA]
|
||
|
||
# 导航展示页(v24 第 24 批 用户第 4 条):/nav/?<短语> —— 全站唯一免登录页面。
|
||
# ⚠️ suggest 那条**必须排在前面**:`^nav(/.*)?$` 会把 /nav/suggest.php 也吞进去,
|
||
# 顺序反了就变成"每次联想都去渲染展示页"(返回一页 HTML、前端拿到非 JSON)。
|
||
# 这也是本批新踩的一条:之前只有 dav/carddav 两条互不包含的前缀,
|
||
# 到这里第一次出现"一个前缀包含另一个"的情况,顺序**变成有语义的**了。
|
||
RewriteRule ^nav/suggest\.php$ nav_suggest.php [L,QSA]
|
||
RewriteRule ^nav/?$ nav_show.php [L,QSA]
|
||
|
||
# 🔴 v44(用户 2026-10-12 第 6 条):移动端 API —— `/api/v1/...` → api.php。
|
||
# ⚠️ `/api/v1/tasks` 不是真实文件,没有这条规则就会被交给 index.php,
|
||
# 而 index.php 不认识它 ⇒ 302 到登录页 ⇒ App 拿到一坨 HTML(JSON 解析失败)。
|
||
# ⚠️ 顺序:这条前缀(`^api`)与上面 dav/carddav/nav 互不包含,放哪都行;
|
||
# 但**只能在 `RewriteEngine On` 之后**。本地等价物在 router.php 里。
|
||
RewriteRule ^api(/.*)?$ api.php [L,QSA]
|
||
</IfModule>
|
||
|
||
# ⚠️ 导航图标与展示页头像**不需要重写规则**(v24 第 25 批):
|
||
# nav_icon.php / nav_avatar.php 是站点根下的**真实文件**,Apache 直接就能执行。
|
||
# 展示页里的地址由 Nav::abs() 拼成 `<base_url>/nav_icon.php?f=…`,落在站点根,
|
||
# 不经过 /nav/ 这个重写前缀 —— 所以上面那两条规则一个字都不用动。
|
||
# (这正是选"站点根下的两个独立入口"而不是"塞进 /nav/ 子路径"的原因:
|
||
# 塞进去就得再加两条重写规则,而重写规则的顺序语义已经踩过一次坑了。)
|
||
|
||
# ⚠️⚠️ DAV 的 Basic 鉴权**必须**靠这一行才能在 Apache 上工作:
|
||
# Apache 默认**不把 `Authorization` 头交给 PHP-FPM** → `$_SERVER['PHP_AUTH_USER']`
|
||
# 和 `HTTP_AUTHORIZATION` 都是 null → /dav/ 与 /carddav/ 无论口令填得多正确都 401。
|
||
# 线上实测(Apache 2.4.53,直接监听 80/443):
|
||
# 没有这行 : {"PHP_AUTH_USER":null,"HTTP_AUTHORIZATION":null}
|
||
# 加上这行 : {"PHP_AUTH_USER":"abc","HTTP_AUTHORIZATION":"(有)"}
|
||
# `CGIPassAuth` 是 Apache **2.4.13+ 的核心指令**,不需要额外模块。
|
||
# (本地 `php -S` 会自己填好 PHP_AUTH_USER,所以 e2e 全绿而线上全 401 ——
|
||
# 典型的"本地好好的、线上不行"。部署脚本也会把这一段追加到线上那份里。)
|
||
<IfModule mod_authz_core.c>
|
||
CGIPassAuth On
|
||
</IfModule>
|
||
|
||
# 备份/临时文件永远不给出去(这条线上很要紧:*.php.bak 曾经可被直接下载)
|
||
<FilesMatch "\.(bak|old|orig|save|swp|swo|tmp)$">
|
||
Require all denied
|
||
</FilesMatch>
|
||
<FilesMatch "^\.|~$">
|
||
Require all denied
|
||
</FilesMatch>
|