From 59f7466ae48d2a6a3632a116a70af2985c3e3546 Mon Sep 17 00:00:00 2001 From: Yongquan Date: Sun, 1 Nov 2026 11:35:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E8=BD=AF=E4=BB=B6=E5=BD=92=E5=B1=9E?= =?UTF-8?q?=EF=BC=9A=E8=BD=AF=E4=BB=B6=E2=86=92=E5=88=86=E7=B1=BB=E4=B8=A4?= =?UTF-8?q?=E7=BA=A7=EF=BC=8C=E9=85=8D=E7=BD=AE=E5=85=A8=E9=83=A8=E5=85=A5?= =?UTF-8?q?=E5=BA=93=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原先分类写死在 config.example.php,后台改不了;也没有「软件」概念。 现在改为数据库驱动的两级结构,后台可配(管理界面待做)。 ## 数据层(lib/db.php) - 新增 software / categories / statuses 三张表 - categories.software_id 外键:每个软件有自己的分类集合,可同名互不干扰 - threads 加 software_id / category_id;老 category 文本列保留不删(可回退) - fb_db_migrate_taxonomy() 幂等迁移:建表 → 空表灌初始数据 → 回填老帖子 ## 迁移实测 - 老 5 个分类(使用问题/Bug 反馈/功能建议/同步问题/其他)原样落进默认软件 - 老帖子按 category slug 回填 category_id,匹配不到的留 NULL ## 状态(5 个) 待处理 / 处理中 / 已解决 / 已关闭 / 不予考虑(wontfix) 每个状态带 user_note「给用户看的话」,后台可改,将进邮件正文。 待处理 = 刚提交:您提交的反馈已收到,我们正在处理中。 ## 前台 - index.php:软件切换条 + 分类 chip(一级软件、二级分类) - new.php:选软件、分类下拉随软件变、服务端校验分类归属 - URL:?sw=&cat=;老链接 ?cat=xxx 解析不到时退回全部,200 不 404 ## 界面一致性 按用户要求去掉「单软件时隐藏软件选择器」的逻辑: 所有界面一致,配一个就列一个,配多个就列多个。 ## 兼容 fb_categories() 现在必须传软件 id;fb_statuses() 返回行数组, 另有 fb_status_keys() 取 key=>name 映射。 验证:WSL 内临时实例实测——单软件显示 1 个软件条;两软件各显示 自己的分类集合与帖子,互不串;无 PHP 警告/致命错误。 --- assets/style.css | 10 +++- index.php | 65 ++++++++++++++++----- lib/db.php | 146 +++++++++++++++++++++++++++++++++++++++++++++++ lib/layout.php | 2 +- lib/util.php | 121 ++++++++++++++++++++++++++++++++++++--- new.php | 73 +++++++++++++++++++----- 6 files changed, 378 insertions(+), 39 deletions(-) diff --git a/assets/style.css b/assets/style.css index 516363d..6cef4ca 100644 --- a/assets/style.css +++ b/assets/style.css @@ -81,7 +81,15 @@ main.wrap{padding-top:24px; padding-bottom:40px; min-height:60vh} .page-head h1{margin-bottom:4px} .page-head .muted{font-size:14px; margin:0} -/* ---------- 筛选 ---------- */ +/* ---------- 软件切换(一级) ---------- */ +.software-bar{ + display:flex; flex-wrap:wrap; align-items:center; gap:8px; + margin-bottom:14px; padding-bottom:14px; border-bottom:1px solid var(--line); +} +.software-bar .sw-label{font-size:13.5px; color:var(--muted); font-weight:600} +.software-bar .chips{margin-bottom:0} + +/* ---------- 筛选(二级:分类 / 状态) ---------- */ .filters{margin-bottom:16px} .chips{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:12px} .chip{ diff --git a/index.php b/index.php index d2861ae..52ca0ce 100644 --- a/index.php +++ b/index.php @@ -4,16 +4,34 @@ */ require __DIR__ . '/lib/bootstrap.php'; -$pdo = fb_db(); -$cats = fb_categories(); -$statuses = fb_statuses(); +$pdo = fb_db(); + +/* ---- 软件切换:只配一个软件时自动落到它,不暴露软件选择器 ---- */ +$swList = fb_softwares(true); +$swKey = isset($_GET['sw']) ? (string)$_GET['sw'] : ''; +$sw = null; +if ($swKey !== '') { + $sw = fb_software($swKey); + // 指定的软件不存在或已停用 → 退回默认,不报错(老链接要能打开) + if (!$sw || (int)$sw['enabled'] !== 1) { $sw = null; } +} +if ($sw === null && $swList) { $sw = $swList[0]; } +$swId = $sw ? (int)$sw['id'] : 0; + +$cats = fb_categories($swId); +$statuses = fb_status_keys(); $cat = isset($_GET['cat']) ? (string)$_GET['cat'] : ''; $st = isset($_GET['status']) ? (string)$_GET['status'] : ''; $q = isset($_GET['q']) ? trim((string)$_GET['q']) : ''; $sort = isset($_GET['sort']) ? (string)$_GET['sort'] : 'active'; -if ($cat !== '' && !isset($cats[$cat])) { $cat = ''; } +// 分类按 slug 在当前软件内解析;解析不到退回「全部」,不许 404 +$curCat = null; +if ($cat !== '') { + $curCat = fb_category_by_slug($swId, $cat); + if (!$curCat) { $cat = ''; } +} if ($st !== '' && !isset($statuses[$st])) { $st = ''; } if ($sort !== 'new') { $sort = 'active'; } @@ -21,8 +39,9 @@ $where = []; $args = []; // 审核(先审后显):访客只看已通过审核的;管理员登录审核后台后可看全部 if (fb_moderation_on() && !fb_is_admin()) { $where[] = 'visible = 1'; } -if ($cat !== '') { $where[] = 'category = ?'; $args[] = $cat; } -if ($st !== '') { $where[] = 'status = ?'; $args[] = $st; } +if ($swId > 0) { $where[] = 'software_id = ?'; $args[] = $swId; } +if ($curCat) { $where[] = 'category_id = ?'; $args[] = (int)$curCat['id']; } +if ($st !== '') { $where[] = 'status = ?'; $args[] = $st; } if ($q !== '') { $like = '%' . addcslashes($q, '%_\\') . '%'; $where[] = "(title LIKE ? ESCAPE '\\' OR body LIKE ? ESCAPE '\\')"; @@ -43,7 +62,7 @@ if ($page < 1) { $page = 1; } if ($page > $pages){ $page = $pages; } $offset = ($page - 1) * $pageSize; -$sql = 'SELECT id, title, category, status, author_name, reply_count, created_at, updated_at,' +$sql = 'SELECT id, title, category, category_id, software_id, status, author_name, reply_count, created_at, updated_at,' . ' substr(body, 1, 300) AS excerpt FROM threads' . $wsql . ' ORDER BY ' . $order . ' LIMIT ' . $pageSize . ' OFFSET ' . $offset; $sth = $pdo->prepare($sql); @@ -56,25 +75,41 @@ foreach ($threads as $t) { $tids[] = (int)$t['id']; } $attImgs = $tids ? fb_attach_map_images($pdo, $tids, 3) : []; $attCount = $tids ? fb_attach_count_map($pdo, $tids) : []; -fb_layout_head('全部问题'); +$siteName = (string)fb_cfg('site_name'); +$headTitle = $siteName !== '' ? $siteName . ' · 问题反馈' : '问题反馈'; +fb_layout_head($sw ? ((string)$sw['name']) : $headTitle); ?>
-

全部问题

-

+

+

+
+ 我要反馈 +
+ +
+ 选择软件: +
+ + +
- 我要反馈
全部 - $v): ?> - + +
+
+ + +
+ 所属软件 *换软件会刷新下面的分类 +
+ + + +
+
+ + + + + +