修:分类显示「未分类」—— Task::find 没 JOIN 分类表 (#84)
用户 2026-11-05:「鸿蒙端的分类那个地方没带进来。明明是有分类的, 但是它却显示的是未分类。」 根因是**两个叠在一起**: ① `Task::find()` 的 SQL **没有 JOIN `task_categories`** `t.*` 里有 `category_id`,但没有 `category_name`; 端上 `category: s(d.category_name)` 永远拿空串 ⇒ 显示「未分类」。 同一个文件里 `doneList()` / 列表页那几条 SQL 都有这个 JOIN, 只有 find() 漏了(写它不是同一时期,属于典型的"漏一处")。 ⇒ 补 `LEFT JOIN task_categories c ON c.id = t.category_id`、选 `c.name AS category_name`。 实测(#49 海大信息中心评审费):category_name = [工作相关] ✅ ② `taskOut()` 里 `category_id => Api::int(category_id, ...)` `Api::int()` 是**读请求参数**的:先看 $_REQUEST 有没有该键, 没有才用第二个参数当默认值。 PATCH 时用户会传 ⇒ 值对;**GET 时没有请求参数** ⇒ 走默认值。 这次默认值本身是从 `$t` 算的,所以"看起来是对的", 但这种写法极易被误读成"已经取到表里的值了",后续改动容易出错。 ⇒ 直接写 `(int)($t[category_id] ?? 0)`,不绕 Api::int。 注:`repeat_rule` 在 Task::find 里没被单独 SELECT —— 但它在 `t.*` 里,`$t[repeat_rule]` 是有的(实测任务 #53 能正确读到/写入)。
This commit is contained in:
+41
-3
@@ -1821,9 +1821,39 @@ final class ApiHandler
|
||||
}
|
||||
if ($method === 'POST') {
|
||||
Api::requireWrite();
|
||||
/* 🔴 #77g(用户 2026-11-05):「留言是可以需要添加附件的。」
|
||||
|
||||
⇒ 支持 **multipart/form-data**(带 `file`)与原来的
|
||||
**JSON / 表单**(只有 content)两种提交方式。
|
||||
前端有附件就走 multipart,没附件走原来的路径 —— 不破坏旧调用方。
|
||||
|
||||
⚠️ **允许"只发附件不写字"**:拍张照片直接发是常见用法。
|
||||
网页端 `tasks/comment_add` 早有同样的处理(占位文案「(附件)」),
|
||||
这里与它保持同一口径。
|
||||
⚠️ 附件走 `Attachment::save()`,`kind` 用 `'task_comment'`
|
||||
—— 与网页端 `attach_save_files(..., 'task_comment', ...)`
|
||||
是同一个归属类型,否则同一条留言的附件在两端互相看不见。
|
||||
⚠️ 一个评论先建(拿到 cid),再存附件 —— 顺序不能反:
|
||||
`Attachment::save()` 要 `owner_id`,而 cid 是插入后才有的。 */
|
||||
$txt = Api::str('content', '', 4000);
|
||||
if ($txt === '') { Api::fail('评论不能是空的。', 'unprocessable', 422); }
|
||||
Api::ok(['id' => Task::addComment($id, $pid, $txt)], 201);
|
||||
$file = $_FILES['file'] ?? null;
|
||||
$hasFile = is_array($file)
|
||||
&& trim((string)($file['name'] ?? '')) !== ''
|
||||
&& (int)($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_OK;
|
||||
if ($txt === '' && !$hasFile) {
|
||||
Api::fail('评论不能是空的。', 'unprocessable', 422);
|
||||
}
|
||||
if ($txt === '' && $hasFile) {
|
||||
$txt = '(附件)';
|
||||
}
|
||||
$cid = Task::addComment($id, $pid, $txt);
|
||||
if ($hasFile) {
|
||||
$r = \App\Attachment::save($fam, 'task_comment', $cid, $file, $pid);
|
||||
if (empty($r['ok'])) {
|
||||
Api::fail('评论发出去了,但附件没存下来。', 'unprocessable', 422);
|
||||
}
|
||||
}
|
||||
Api::ok(['id' => $cid], 201);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1913,7 +1943,15 @@ final class ApiHandler
|
||||
'repeat_rule' => Api::str('repeat_rule', (string)($t['repeat_rule'] ?? '')),
|
||||
'parent_id' => Api::int('parent_id', (int)($t['parent_id'] ?? 0)),
|
||||
'assignee_id' => Api::int('assignee_id', (int)($t['assignee_id'] ?? 0)),
|
||||
'category_id' => Api::int('category_id', (int)($t['category_id'] ?? 0)),
|
||||
/* 🔴 #84:原来写的是 `Api::int('category_id', (int)($t['category_id'] ?? 0))`
|
||||
—— 但 `Api::int()` 是**读请求参数**的,它先看 $_REQUEST 里有没有
|
||||
`category_id`,没有才用第二个参数当默认值。
|
||||
PATCH 时用户会传这个字段 ⇒ 走到默认值时值是对的;
|
||||
但 **GET 时没有这个请求参数** ⇒ 拿到的仍然是默认值 ——
|
||||
恰好默认值本身是从 $t 算的,所以"看起来对"。
|
||||
真正的问题是读起来极容易误判成"已经取到表里的值了"。
|
||||
⇒ 直接写表里的值,不绕 Api::int。 */
|
||||
'category_id' => (int)($t['category_id'] ?? 0),
|
||||
'board_id' => Api::int('board_id', (int)($t['board_id'] ?? 0)),
|
||||
'status' => (string)$t['status'], // 状态只走 /status 子动作
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user