后台管理界面:软件/分类/状态可配,反馈可改挂归属 (#1)
## 新增 lib/admin_taxonomy.php - 软件:增删改、排序、启停;新增时自动预置 Bug/功能建议/其他 三个分类 - 分类:在选定软件下增删改、排序、启停 - 状态:改名、改「给用户看的话」、排序、启停;标识不可改(历史数据靠它对应) - 反馈改挂:th_move,可把反馈移到别的软件/分类,跨软件的非法分类会被拒 ## 安全与边界 - 所有动作走 CSRF 校验(沿用现有机制) - 不能删最后一个软件 / 没有分类的软件至少要留一个启用分类 - 有反馈挂着的软件或分类不能删,提示改为停用(停用后前台消失、数据保留) - th_move 加入 fb_admin_is_taxonomy_act 白名单,否则会被「问题不存在」静默吞掉 ## admin.php 接线 - 引入模块 + 动作分发 + tab 白名单加 taxonomy/statuses + 导航两项 - 前置检查放行不依赖 $t 的动作(否则新增软件报「问题不存在」) - 全部问题列表:加软件筛选、分类跟着软件走;修掉三处仍在用旧 fb_statuses()/fb_categories() 的遍历(那会渲染出错) - 详情页加「归属」表单,软件徽章可显示 ## 其他文件 - api.php:状态/分类改数据库;新增 ?sw= / ?software_id= / ?cid= 过滤, 老的 ?category=<slug> 仍可用(在所属软件内解析) - thread.php:详情页显示软件与分类徽章 - config.example.php:移除 categories / statuses,改由数据库管理 ## 修掉两个真实 bug 1. 移除配置后出厂分类兜底只剩 4 个,漏了「同步问题」—— 建库后核对数量才发现 2. th_move 不在白名单,POST 后返回 200 却静默不生效 验证:后台 e2e 29/29;改挂与联动 13/13;PHP 8.5 全部入口 0 弃用; 19 个 PHP 文件语法全过。
This commit is contained in:
@@ -34,8 +34,7 @@ $action = isset($_GET['action']) ? (string)$_GET['action'] : 'list';
|
||||
$contacts = !empty($_GET['contacts']);
|
||||
$limit = isset($_GET['limit']) ? max(1, min(500, (int)$_GET['limit'])) : 100;
|
||||
|
||||
$cats = fb_categories();
|
||||
$statuses = fb_statuses();
|
||||
$statuses = fb_status_keys();
|
||||
|
||||
/** 过滤条件 */
|
||||
function fb_api_where(&$args, $cats, $statuses) {
|
||||
@@ -43,8 +42,32 @@ function fb_api_where(&$args, $cats, $statuses) {
|
||||
if (!empty($_GET['status']) && isset($statuses[(string)$_GET['status']])) {
|
||||
$w[] = 'status = ?'; $args[] = (string)$_GET['status'];
|
||||
}
|
||||
if (!empty($_GET['category']) && isset($cats[(string)$_GET['category']])) {
|
||||
$w[] = 'category = ?'; $args[] = (string)$_GET['category'];
|
||||
// 软件:?sw=<slug> 或 ?software_id=<id>
|
||||
$swArg = '';
|
||||
if (!empty($_GET['sw'])) {
|
||||
$sw = fb_software((string)$_GET['sw']);
|
||||
if ($sw) { $w[] = 'software_id = ?'; $args[] = (int)$sw['id']; $swArg = 'sw'; }
|
||||
} elseif (!empty($_GET['software_id'])) {
|
||||
$sw = fb_software((int)$_GET['software_id']);
|
||||
if ($sw) { $w[] = 'software_id = ?'; $args[] = (int)$sw['id']; $swArg = 'id'; }
|
||||
}
|
||||
// 分类:?cid=<id> 优先;兼容老的 ?category=<slug>,在其所属软件内解析
|
||||
if (!empty($_GET['cid'])) {
|
||||
$c = fb_category((int)$_GET['cid']);
|
||||
if ($c) { $w[] = 'category_id = ?'; $args[] = (int)$c['id']; }
|
||||
} elseif (!empty($_GET['category'])) {
|
||||
$slug = (string)$_GET['category'];
|
||||
$swId = 0;
|
||||
if (!empty($_GET['sw'])) {
|
||||
$sw0 = fb_software((string)$_GET['sw']);
|
||||
if ($sw0) { $swId = (int)$sw0['id']; }
|
||||
}
|
||||
if ($swId <= 0) {
|
||||
$d = fb_default_software();
|
||||
if ($d) { $swId = (int)$d['id']; }
|
||||
}
|
||||
$c = fb_category_by_slug($swId, $slug);
|
||||
if ($c) { $w[] = 'category_id = ?'; $args[] = (int)$c['id']; }
|
||||
}
|
||||
if (!empty($_GET['since'])) {
|
||||
$w[] = 'updated_at >= ?'; $args[] = (int)$_GET['since'];
|
||||
@@ -58,7 +81,9 @@ function fb_api_thread(array $t, $contacts) {
|
||||
'id' => (int)$t['id'],
|
||||
'title' => $t['title'],
|
||||
'category' => $t['category'],
|
||||
'category_cn' => fb_category_label($t['category']),
|
||||
'category_id' => isset($t['category_id']) ? (int)$t['category_id'] : null,
|
||||
'category_cn' => fb_category_label(isset($t['category_id']) ? $t['category_id'] : 0),
|
||||
'software_id' => isset($t['software_id']) ? (int)$t['software_id'] : null,
|
||||
'status' => $t['status'],
|
||||
'status_cn' => fb_status_label($t['status']),
|
||||
'author' => $t['author_name'],
|
||||
|
||||
Reference in New Issue
Block a user