diff --git a/admin.php b/admin.php index f629b5d..3793e79 100644 --- a/admin.php +++ b/admin.php @@ -116,17 +116,31 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['act'])) { $msgType = 'error'; } elseif ($act === 'approve') { - $newStatus = ((string)$t['status'] === 'closed') ? 'open' : (string)$t['status']; + /* 「通过并公开」= 两件事一起做: + * ① 可见性:visible=1 + * ② 状态:『未公开』→『待处理』 + * + * 状态流转是用户在 2026-11-03 明确要求的:提交后先落「未公开」, + * 通过了才变「待处理」;如果判定不是问题,直接走 close 变「已关闭」, + * 中间不经过「待处理」。 + * + * 边界:如果这条本来就已经是别的状态(比如以前误操作改成了「处理中」), + * 通过审核不该把状态倒退回去,所以只在「未公开」时才推进。 + * 老数据可能还是 'open' + visible=0,也一并视作待推进。 */ + $oldSt = (string)$t['status']; + $newStatus = ($oldSt === 'hidden' || $oldSt === 'open') ? 'open' : $oldSt; $pdo->prepare('UPDATE threads SET visible = 1, status = ?, mod_note = NULL, moderated_at = ? WHERE id = ?') ->execute([$newStatus, time(), $id]); - fb_mod_log('approve', $id, '通过审核并公开'); + fb_mod_log('approve', $id, '通过审核并公开(状态:' . fb_status_label($newStatus) . ')'); // 通知提交人「已发布」(工单 #2) $errA = ''; try { - list($okA, $errA) = fb_notify_event($pdo, 'approve', $t); + // 用更新后的状态渲染邮件,否则信里还写着「未公开」 + $fresh = fb_admin_thread($pdo, $id); + list($okA, $errA) = fb_notify_event($pdo, 'approve', $fresh ? $fresh : $t); } catch (Throwable $e) { $errA = '发信异常'; } - $msg = '#' . $id . ' 已通过审核,现已公开显示。' + $msg = '#' . $id . ' 已通过审核并公开,状态为「' . fb_status_label($newStatus) . '」。' . ($errA === '' ? '已发邮件通知提交人。' : '(邮件未发出:' . $errA . ')'); } elseif ($act === 'close') { @@ -648,16 +662,23 @@ fb_layout_head('管理后台', ['robots' => 'noindex,nofollow']); query( - "SELECT id, title, body, category, status, author_name, author_email, created_at - FROM threads WHERE visible = 0 AND status <> 'closed' ORDER BY created_at DESC" + "SELECT * FROM threads + WHERE status = 'hidden' OR (visible = 0 AND status = 'open') + ORDER BY created_at DESC" )->fetchAll(); ?> -

待审核 ()

+

待审核 ()

当前没有待审核的反馈。

- +
+ +
@@ -828,7 +849,10 @@ fb_layout_head('管理后台', ['robots' => 'noindex,nofollow']);
- + +
@@ -1411,53 +1435,44 @@ fb_layout_head('管理后台', ['robots' => 'noindex,nofollow']); fb_layout_foot(); /** - * 待审核卡片(含「通过」与「关闭并邮件告知」两个操作) + * 待审核条目(列表式) + * + * 用户 2026-11-03 明确要求: + * ① 列表形式显示,不要每张卡片塞满表单 + * ② 去掉「关闭说明」整块 —— 想关闭就点标题进管理页再填说明, + * 列表页不承担这个职责 + * ③ 后面只留一个「通过并公开」按钮,点一下就通过 + * ④ 标题自己就是进管理页的链接,别再额外挂「进入管理」 */ -function fb_admin_thread_card(array $t) { +function fb_admin_pending_row(array $t) { + $url = 'admin.php?tab=thread&id=' . (int)$t['id']; ob_start(); ?> -
-
+
+
- - - - - - - # +
+ + + + + + + # +
+

+
+ + · + + · + +
- -
- -
- - · - - · - - · - 进入管理 -
- -
+
-
- -
-
- -
- - - -
- -
+
diff --git a/assets/style.css b/assets/style.css index efe3a77..b2b0c87 100644 --- a/assets/style.css +++ b/assets/style.css @@ -189,10 +189,11 @@ main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh} overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .sw-badge-sm .sw-badge-nm{font-size:14px} -.sw-badge-md .sw-badge-nm{font-size:19px} -.sw-badge-lg .sw-badge-nm{font-size:22px; font-weight:700} -/* 顶栏主标题:比「选择软件」标签(13.5px)大两号 = 17px。 - * 之前给到 26px 反而比内容区标题还小,主次颠倒;这里保持克制。 */ +.sw-badge-md .sw-badge-nm{font-size:16px; font-weight:600} +/* 内容区:只是软件标识,字号刻意小于顶栏标题(17px), + * 避免「上面的字比下面的小」这种主次颠倒。 */ +.sw-badge-lg .sw-badge-nm{font-size:15px; font-weight:600} +/* 顶栏主标题:比「选择软件」标签(13.5px)大两号 = 17px,且大于内容区的 15px */ .sw-badge-brand .sw-badge-nm{font-size:17px; font-weight:700; letter-spacing:.2px} /* 页头副行:图标 + 软件名 */ .page-sw-id{margin:0; display:flex; align-items:center} @@ -368,6 +369,37 @@ main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh} .item-ex{color:var(--muted); font-size:14px; margin:8px 0 8px; word-break:break-word} .item-meta{display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:13px; color:var(--muted)} .item-meta .who{color:#3a424d; font-weight:600} + +/* ---------- 后台「待审核」列表 ---------- + * 列表式:一屏能看多条,右侧固定一个「通过并公开」。 + * 详情/关闭说明留在管理页里填,列表页不塞表单。 */ +.plist{display:flex; flex-direction:column; gap:10px} +.prow{ + display:flex; align-items:flex-start; gap:16px; + background:var(--card); border:1px solid var(--line); + border-radius:12px; padding:13px 16px; +} +.prow:hover{border-color:var(--line-strong)} +.prow-main{flex:1; min-width:0} +.prow-top{display:flex; align-items:center; flex-wrap:wrap; gap:8px} +.prow-title{ + font-weight:600; font-size:15.5px; color:var(--fg); + flex:1; min-width:160px; word-break:break-word; +} +.prow-title:hover{color:var(--brand); text-decoration:underline} +.prow-ex{ + color:var(--muted); font-size:13.5px; margin:6px 0; + word-break:break-word; display:-webkit-box; -webkit-line-clamp:2; + -webkit-box-orient:vertical; overflow:hidden; +} +.prow-meta{display:flex; flex-wrap:wrap; align-items:center; gap:6px; font-size:12.5px; color:var(--muted)} +.prow-meta .who{color:#3a424d; font-weight:600} +.prow-act{flex:none; padding-top:2px} +.prow-act .btn{white-space:nowrap} +@media (max-width:600px){ + .prow{flex-direction:column; gap:10px} + .prow-act{align-self:flex-start} +} /* 问题编号:便于按 id 逐条跟进与引用 */ .item-id{ flex:none; font-size:12.5px; font-weight:600; color:var(--muted); @@ -383,6 +415,8 @@ main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh} } .badge.st{background:#f1f3f5; color:#5b636e} .badge.st-open{background:var(--warn-soft); color:var(--warn)} +/* 「未公开」= 还没审过,用中性灰,不要和「已关闭」混淆 */ +.badge.st-hidden{background:#eef0f3; color:#6b7684} .badge.st-doing{background:var(--brand-soft); color:var(--brand)} .badge.st-resolved{background:var(--ok-soft); color:var(--ok)} .badge.st-closed{background:#f1f3f5; color:#8a929c} diff --git a/lib/db.php b/lib/db.php index 7639347..0564418 100644 --- a/lib/db.php +++ b/lib/db.php @@ -399,18 +399,36 @@ SQL } } - // 3) 状态:空表时灌 5 个(4 个原有 + 新增「不予考虑」) + // 3) 状态:空表时灌全部状态 if ((int)$pdo->query('SELECT COUNT(*) FROM statuses')->fetchColumn() === 0) { $rows = [ - ['open', '待处理', '您提交的反馈已收到,我们正在处理中。', 0], - ['doing', '处理中', '我们正在跟进这个问题,有进展会在这里同步。', 1], - ['resolved', '已解决', '这个问题已经处理好了,欢迎回来验证一下。', 2], - ['closed', '已关闭', '这个反馈已关闭,如有新情况可以重新提交。', 3], - ['wontfix', '不予考虑', '经评估这个反馈暂不处理,感谢你的建议。', 4], + // key_name 名称 给用户看的说明(进邮件) 排序 + ['hidden', '未公开', '您的反馈已提交,正在等待管理员查看。', 0], + ['open', '待处理', '您的反馈已公开,我们已收到,会尽快安排处理。', 1], + ['doing', '处理中', '我们正在跟进这个问题,有进展会在这里同步。', 2], + ['resolved', '已解决', '这个问题已经处理好了,欢迎回来验证一下。', 3], + ['closed', '已关闭', '这个反馈已关闭,如有新情况可以重新提交。', 4], + ['wontfix', '不予考虑', '经评估这个反馈暂不处理,感谢您的建议。', 5], ]; $st = $pdo->prepare('INSERT INTO statuses(key_name, name, user_note, sort_order, enabled) VALUES(?,?,?,?,1)'); foreach ($rows as $r) { $st->execute($r); } + } else { + /* 老库补「未公开」状态。 + * 2026-11-03 新增:用户提交后先落「未公开」,审核通过才转「待处理」—— + * 「未公开」本身就是一种状态,不该只靠 threads.visible=0 这个附加字段隐式表达。 */ + $hasHidden = (int)$pdo->query("SELECT COUNT(*) FROM statuses WHERE key_name = 'hidden'")->fetchColumn(); + if ($hasHidden === 0) { + // 先把现有状态整体后移一位,给「未公开」腾出 0 号位 + $pdo->exec('UPDATE statuses SET sort_order = sort_order + 1'); + $pdo->prepare('INSERT INTO statuses(key_name, name, user_note, sort_order, enabled) + VALUES(?,?,?,?,1)') + ->execute(['hidden', '未公开', '您的反馈已提交,正在等待管理员查看。', 0]); + + /* 存量数据:visible=0 且状态还是「待处理」的,语义上就是「没公开」, + * 归到「未公开」;visible=1 的保持「待处理」不动。 */ + $pdo->exec("UPDATE threads SET status = 'hidden' WHERE visible = 0 AND status = 'open'"); + } } // 4) 回填老帖子:software_id / category_id(只填 NULL 的,重复执行无副作用) diff --git a/lib/mailer.php b/lib/mailer.php index e27d4fb..7e15142 100644 --- a/lib/mailer.php +++ b/lib/mailer.php @@ -786,6 +786,15 @@ if (!function_exists('fb_notify_status_meta')) { */ function fb_notify_status_meta($key) { $map = [ + /* 「未公开」:用户刚提交时就是这个状态。 + * 一般不单独发信(提交回执已经说了「等待审核」), + * 但万一从别的状态退回来,也要有话可说,不能落到兜底文案。 */ + 'hidden' => [ + 'badge' => '未公开', 'color' => '#6b7684', 'tone' => 'muted', + 'title' => '您的反馈已提交,正在等待审核', + 'intro' => '管理员会尽快查看您的反馈,确认后才会公开显示。', + 'tip' => '审核结果我们会通过邮件通知您,无需反复回来查看。', + ], 'open' => [ 'badge' => '待处理', 'color' => '#5c6572', 'tone' => 'muted', 'title' => '您的反馈已收到,正在等待处理', diff --git a/new.php b/new.php index d7c7aa2..1340971 100644 --- a/new.php +++ b/new.php @@ -89,8 +89,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $atts = $vList; } else { $now = time(); - // 审核:开启后新提交默认不公开(visible=0),管理员通过后才会出现在列表 + /* 审核:开启后新提交默认不公开(visible=0),管理员通过后才出现在列表。 + * + * 🔴 状态与可见性必须同时设,两者是同一件事的两个侧面: + * 未公开 → status='hidden'(未公开),公开 → status='open'(待处理)。 + * 以前一律写 'open',导致后台「待审核」里全是「待处理」, + * 状态根本反映不出"还没公开"这个事实。 */ $visible = fb_moderation_on() ? 0 : 1; + $initStatus = $visible === 1 ? 'open' : 'hidden'; $ins = $pdo->prepare('INSERT INTO threads(title, body, category, category_id, software_id, author_name, author_email, author_phone, status, visible, reply_count, created_at, updated_at, ip_hash) VALUES(?,?,?,?,?,?,?,?,?,?,0,?,?,?)'); $ins->execute([ $form['title'], $form['body'], @@ -99,7 +105,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $swId > 0 ? $swId : null, $form['name'], $form['email'], $form['phone'] !== '' ? $form['phone'] : null, - 'open', $visible, $now, $now, fb_ip_hash(), + $initStatus, $visible, $now, $now, fb_ip_hash(), ]); $newId = (int)$pdo->lastInsertId(); fb_attach_save($pdo, $newId, null, $vList);