首页改介绍页;列表只服务当前软件;新增UUID追踪让提交人看得到未审核反馈
用户提的两个核心问题:
一、首页不该列全部问题
场景:这套系统是给某个软件配反馈入口、把地址贴进那软件的「意见反馈」里。
访客总是从某个软件过来的,看别的软件的问题对他没意义。
⇒ / 不带 sw 时渲染介绍页(特点介绍 + 「点右上角设置按钮选软件」+ 软件卡片)
带 sw 才是该软件的问题列表,检索/筛选/分类全在本软件范围内
二、提交后未审核,用户点不进去(真实缺陷)
邮件里给了「点击查看您刚才提交的反馈」,但 thread.php 只在 visible=1 时
才给看,未审核的一律 404 / 只看到「等待审核」静态页 —— 链接等于白给。
⇒ threads 加 track_token(32位hex = 128位熵),提交时生成:
- 邮件里所有链接一律带 ?t=<token>(不再是裸 id)
- 带对 token:可看完整详情、可回复,哪怕未公开/已关闭
- 没 token 或 token 错:对外一律 404,不泄露存在性
- 公开列表仍用 id 链接(公开内容谁都能看,用于避免重复提交)
实现细节:
- threads.track_token + 唯一索引;幂等迁移,存量数据自动回填
- fb_track_new_token / fb_track_token_ok(hash_equals 防时序探测)
/ fb_thread_viewable / fb_thread_link(thread, personal)
- thread.php 权限从 fb_thread_public 改为 fb_thread_viewable
- 带 token 看自己未公开的反馈时,顶部给「私人跟踪链接」提示条
- 回复表单与回复后跳转都保留 token,否则回复完就失去访问权
- 提交完成后直接带 token 跳详情页,不再只给静态等待页
- close 类邮件补上「查看这条反馈」按钮(原来完全没链接)
- 顶栏「全部问题」改为「问题列表」且只在选中软件后显示
- 详情/提交页「返回问题列表」按所属软件返回,不再回介绍页
- new.php 无 sw 时不再默认落到第一个软件,改为让用户先选
(默默替选会让反馈进错软件、通知发错人)
验证:首页 0 条问题卡片且未泄露任何标题、三个软件入口齐全;
未公开#4 无 token 404 / 错 token 404 / 正确 token 200 且显示完整详情
(不再卡在「等待审核」)、提示条与表单 token 都在;
已公开#2 无 token 可看;5 类邮件(回执/通过/回复/状态/关闭)链接全带 token;
两套回归各 30+ 项断言全过。
This commit is contained in:
@@ -8,7 +8,11 @@ $pdo = fb_db();
|
||||
$err = '';
|
||||
$atts = []; // 校验失败时保留已上传的附件
|
||||
|
||||
/* ---- 软件:URL 带 sw 就用它,否则落到默认软件 ---- */
|
||||
/* ---- 软件:URL 带 sw 就用它 ----
|
||||
* 🔴 不再「没带 sw 就默认落到第一个软件」:
|
||||
* 首页现在是介绍页,直接访问 new.php 没有软件上下文,
|
||||
* 默默替他选一个软件会让反馈进错地方、发错通知邮件。
|
||||
* 没有软件时给一句引导,让用户先选软件。 */
|
||||
$swList = fb_softwares(true);
|
||||
$sw = null;
|
||||
$swKey = isset($_GET['sw']) ? (string)$_GET['sw'] : '';
|
||||
@@ -16,8 +20,32 @@ 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;
|
||||
if ($sw === null) {
|
||||
fb_layout_head('请先选择软件', ['robots' => 'noindex,follow']);
|
||||
?>
|
||||
<div class="empty">
|
||||
<h2 style="margin:0 0 12px">请先选择要给哪个软件提反馈</h2>
|
||||
<p class="muted" style="margin:0 0 16px">不同软件的问题列表是分开的,请先选一个。</p>
|
||||
<div class="home-sw-list" style="max-width:420px;margin:0 auto 18px">
|
||||
<?php foreach ($swList as $s): ?>
|
||||
<?php
|
||||
list($c) = fb_software_colors($s);
|
||||
if ($c === '') { $c = '#0057B8'; }
|
||||
?>
|
||||
<a class="home-sw" href="new.php?sw=<?php echo e(urlencode((string)$s['slug'])); ?>"
|
||||
style="--swc:<?php echo e($c); ?>">
|
||||
<span class="home-sw-nm"><?php echo e((string)$s['name']); ?></span>
|
||||
<span class="home-sw-go">去反馈 →</span>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<p><a class="btn" href="index.php">返回首页</a></p>
|
||||
</div>
|
||||
<?php
|
||||
fb_layout_foot();
|
||||
exit;
|
||||
}
|
||||
$swId = (int)$sw['id'];
|
||||
|
||||
$cats = fb_categories($swId);
|
||||
$catKeys = [];
|
||||
@@ -97,7 +125,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
* 状态根本反映不出"还没公开"这个事实。 */
|
||||
$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,?,?,?)');
|
||||
/* track_token:提交人的私人追踪钥匙,只发到他的邮箱。
|
||||
* 有了它,即使这条还没审核通过,他也能凭链接看到进度。 */
|
||||
$trackToken = fb_track_new_token();
|
||||
$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, track_token) VALUES(?,?,?,?,?,?,?,?,?,?,0,?,?,?,?)');
|
||||
$ins->execute([
|
||||
$form['title'], $form['body'],
|
||||
$curCat ? (string)$curCat['slug'] : 'other', // 老列留个值,便于回退与检索
|
||||
@@ -105,7 +136,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$swId > 0 ? $swId : null,
|
||||
$form['name'], $form['email'],
|
||||
$form['phone'] !== '' ? $form['phone'] : null,
|
||||
$initStatus, $visible, $now, $now, fb_ip_hash(),
|
||||
$initStatus, $visible, $now, $now, fb_ip_hash(), $trackToken,
|
||||
]);
|
||||
$newId = (int)$pdo->lastInsertId();
|
||||
fb_attach_save($pdo, $newId, null, $vList);
|
||||
@@ -138,7 +169,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// 发信失败绝不能让用户提交失败 —— 反馈已经存库了
|
||||
}
|
||||
|
||||
fb_redirect('thread.php?id=' . $newId . '&submitted=1');
|
||||
/* 提交完成后直接带 token 跳到详情页:
|
||||
* 这样用户当场就能看到自己刚提交的那条(哪怕还没审核),
|
||||
* 而不是只看到一个「等待审核」的静态提示页。 */
|
||||
fb_redirect('thread.php?id=' . $newId
|
||||
. '&t=' . rawurlencode($trackToken)
|
||||
. '&submitted=1');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,7 +182,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
fb_layout_head('我要反馈', ['robots' => 'noindex,follow', 'software' => $sw]);
|
||||
?>
|
||||
|
||||
<div class="crumbs"><a href="index.php">← 返回问题列表</a></div>
|
||||
<div class="crumbs"><a href="<?php echo e(fb_software_list_url($sw)); ?>">← 返回问题列表</a></div>
|
||||
|
||||
<section class="narrow">
|
||||
<h1>我要反馈</h1>
|
||||
|
||||
Reference in New Issue
Block a user