Commit Graph
10 Commits
Author SHA1 Message Date
laoyang 8bcee46b8a 首页改介绍页;列表只服务当前软件;新增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+ 项断言全过。
2026-11-03 09:54:12 +08:00
laoyang 28d28ad51c 软件徽标带图标+主题色;标题用软件色;删冗余欢迎语;抽屉改竖排覆盖
用户四点要求:
1. 待审核标题前的软件名要带图标
2. 每个软件配了颜色,徽标与标题都应显示该颜色
3. 「欢迎在这里反馈使用问题、提出功能建议」这类话没意义,全部删掉
4. 右上角三横线抽屉:不要宽屏横排/窄屏竖排两套,
   统一竖排并把下面内容盖住,简单一点

改动:
- 新增 fb_software_chip():软件徽标带图标 + 该软件主题色
  (原来一律固定蓝色 #eef2f8/#2b4a74,等于白配了颜色)
  配 fb_color_soft()/fb_color_line() 由主色推导同色系浅底与描边
  替换 admin.php 两处、thread.php 一处(原来是 badge 套 badge,双重边框)
- 顶栏标题与内容区标识都用软件主题色(PHP 内联 --swc 变量)
- index.php 不再渲染 site_desc(配置项保留,后台仍可编辑)
- 抽屉改为统一竖排 absolute 浮层 + 遮罩盖住正文,删掉宽屏横排分支
  打开时锁背景滚动,点遮罩/Esc/再点按钮都能关
  .topbar 作为定位参照(sticky 即可)

顺手修:fb_hex_to_rgb 的三位简写展开前要先校验字符,
否则 zzz 这类非法值可能被误展开(本次测试用例选错才发现校验不够严)

验证:3 个软件 chip 的图标/名字/主色/浅底/描边全部正确,
无图标退回字符、XSS 转义通过、颜色工具函数 6 项通过;
CDP 真实浏览器在 390px 与 1280px 两种宽度下各 13 项断言全过
(绝对定位、在顶栏下方、铺满宽度、条目纵排同x、y递增、
层级高于正文、遮罩同步显隐、可关);
三个软件标题色分别 #b4553c / #6a4c93 / #0057b8;全部路由 200。
2026-11-03 09:20:14 +08:00
laoyang 2ef119f7cb 标题字号折中;软件选择移入右上角汉堡菜单
用户反馈三点:
1. 顶栏图标太大(56px)
2. 顶栏文字反而比内容区还小 —— 主次颠倒
3. 不要再整页显示「选择软件:」,改成右上角三横线按钮,点开下拉选

字号标准(用户给的基准):
  「选择软件」标签 13.5px,比它大两号 ≈ 17px。
  → 顶栏 17px 字 / 30px 图标;内容区 15px 字 / 24px 图标。
  这样 17 > 15,层级正确。

   之前两轮都搞错了:
   - 先给顶栏 46px 图标 + 22px 字:图标过大
   - 再给 56px + 26px:更大
   - 而且内容区当时是 30px,比顶栏还大,视觉上「上面比下面小」

软件选择改造:
- 顶栏右侧新增汉堡按钮(三横线,展开变×)
- 抽屉面板放在 header 内、正文之上,默认 hidden
- 列出软件:图标 + 名字 + 当前项标记
- index.php 删除整行「选择软件:」+ chips
- new.php 表单内也删除那排 chip(同一选择不该出现两次)
- 交互:点击展开/再点收起/点外部关闭/Esc 关闭
- 宽屏抽屉横向排列,窄屏纵向

验证(CDP 驱动真实浏览器):
汉堡按钮存在、初始收起、点击展开、aria 同步、软件条目与当前标记齐全、
再点收起、点外部关闭 —— 全部 PASS;
顶栏字号 17px > 内容区 15px,页面无裸露 ?>;
全部路由 200;窄屏 15px/13px 层级仍正确。
2026-11-03 08:51:20 +08:00
laoyang 82484298e4 标题位置修正:顶栏即「XX反馈系统」,内容区只留图标+软件名
用户指出三处问题:
1. 最上面标题应显示「同步日历反馈系统」,而不是光秃秃的「同步日历」
2. 内容区那个重复的「同步日历反馈系统」不要再要了,
   那里只要「图标 + 同步日历」
3. 内容区下面多了一个裸露的 ?> 字符
4. 图标和标题文字都要再大一点

改动:
- 顶栏改为 fb_software_badge(sw, brand, fb_software_site_title(sw))
  图标 56px、文字 26px,成为页面唯一主标题
- 删除内容区的 h1.page-h1-sw(重复标题)
- 内容区改为 badge(lg):图标 40px + 文字 30px
- 清除 index.php 里多余的 ?> (上次编辑留下的残渣)
- badge 新增 brand 尺寸档与  参数,可覆盖显示文字
- 顶栏高度 72->84px 容纳更大的图标;窄屏仍有降级

验证:顶栏 title/文字正确、已无 page-h1-sw、
无裸露 ?>、内容区只显示「同步日历」、5 处图标全走 media.php
且均为有效 PNG、三个软件页与全部路由 200。
2026-11-03 08:34:03 +08:00
laoyang 669ab9e43e 修复图标显示不出来;标题改XX反馈系统;图标去掉背景色
一、图标显示不出来(根因)
用户上传图标时用的是修复前的代码,数据库里 icon_key 存的是
icons/2026/11/xxx.png —— 没有 local/ 也没有 oss.prefix 前缀。
上一轮我把键校验收紧成「必须带存储前缀」,于是这些键被判非法,
fb_icon_url() 返回空字符串,图标自然显示不出来。
而三个文件其实都真实存在于 OSS 上(13KB / 391KB / 379KB)。

修法两层:
1. fb_icon_key_ok / fb_icon_is_key 兼容历史无前缀形态,
   这些是有效资产,不能因为键格式不规范就让图标消失
2. 数据迁移:把对象复制到 feedlite/icons/… 并把数据库键改成规范形态,
   已对三个软件全部执行并验证(新键 200,大小与源文件一致)

二、标题改为「XX 反馈系统」
- 页头大标题 = 同步日历反馈系统(之前只有「同步日历」)
- 浏览器标签同步改
- 软件名本身含「反馈」时不叠加,避免「轻反馈反馈系统」

三、图标不要背景色
- 去掉色块底衬与圆角投影,直接「图标 + 文字」并排
- 前端 badge、提交页上下文条、邮件头部三处同步
- md 尺寸调到 28px,与 26px 标题文字视觉匹配

验证:三个软件页标题正确、图标全部 200 image/png、
全部页面 200、迁移后新键可读且大小一致。
2026-11-03 08:27:03 +08:00
laoyang 738c6c09ff 多软件区分:邮件按软件换色+图标+软件名;补提交回执邮件
用户要求:多软件并存时,用「颜色 + 图标 + 名字」三重区分,
邮件也要跟着所属软件变,一眼能看出是哪款软件的来信。

1. software 表加 icon / download_url 字段(幂等迁移)
   - icon 存单个字符(emoji / 汉字 / 字母),不存图片路径:
     前端与邮件用同一个字符渲染,天然一致,不用再管一套上传与权限
   - 没配 icon 时取名首字兜底,任何地方都不出现空图标
   - 后台软件编辑加图标快选(12 个常用 emoji)

2. 邮件配色改为跟随软件(fb_mail_brand 取 fb_software_colors)
   - 头部色条、按钮、引用块色条、徽标全部跟着软件走
   - 邮件头部改为「图标色块 + 软件名」,下面再小字标站点名
   - 主题行统一加【软件名】前缀,不点开就能分辨

3. 新增 receipt 事件:提交后立即给提问人发「已收到、待审核、请耐心等待」
   - 独立开关 notify.receipt_enabled(与「回复通知」是两件事)
   - 新增 7 处调用前的静默 return 也一并写日志

4. reply 邮件补上下文:原提问摘要 + 本次回复,像博客评论通知
5. status=resolved 文案改为「已完成并上线」,配了下载地址时给下载按钮

验证:多软件配色/图标/前缀全部通过(含反向验证),XSS 转义通过,
空图标兜底通过;页面顶栏、页头、选择器图标渲染正确。
2026-11-03 08:00:50 +08:00
laoyang f1a81cbaa1 RAM 角色自动探测 + 邮件配置界面 + 每个软件独立主题色 (#1 #2)
## 1. ECS RAM 角色改为自动探测
原先要用户去阿里云控制台查「实例 RAM 角色名」再手填,纯属多余 ——
机器自己知道答案。

新增 fb_oss_detect_instance_role():读元数据
GET /latest/meta-data/ram/security-credentials/(末尾带斜杠)拿到角色名列表。
- 兼容单行 / 多行 / JSON 数组三种返回
- 未配置角色时 fb_oss_instance_creds() 自动探测,不再报「未配置」
- 后台改成只读展示「已绑定:xxx」,手填入口收进「高级」折叠里
- 保存时留空 = 自动探测后写入,不存空值
- 探测失败给出可操作原因(没绑角色 / 不在 ECS 上 / 元数据被禁用)

## 2. 邮件配置界面(原先完全缺失)
lib/mailer.php 有完整 SMTP 实现,但后台一个输入框都没有,
只能改 config.php —— 用户装完根本找不到地方配。

根因有两层:
- fb_setting_keys() 白名单里没有任何 smtp.* / notify.* 键,
  就算加了表单,fb_set_setting() 也会把值全部丢弃
- 设置页只有「站点信息」「附件存储」两个区块

补上:白名单 15 个键 + 后台「邮件通知」区块
- SMTP 服务器/端口/加密方式(SSL/STARTTLS/不加密)
- 登录账号/密码(留空不修改,避免每次重填)
- 发件地址/显示名、超时、SSL 校验
- 通知规则:回复通知、每次回复都通知、新反馈通知管理员、发信冷却
- 「发送测试邮件」按钮,AJAX 发完就地显示成功或失败原因,
  不用保存再靠猜

## 3. 每个软件一个主题色
需求:从短链接进不同软件,颜色不同,一眼区分。

- software 表加 color 字段(幂等迁移)
- 全站配色靠 --brand / --brand-600 / --brand-soft 三个变量,
  按软件覆写这三个即可,不用为每个软件写一套 CSS
- fb_color_variants() 由主色推出深一档(×0.85)与浅一档(往白混 88%)
- 未配色的软件按 id 从 8 色调色板取默认色,保证同站不撞色
- 后台:颜色选择器(原生取色 + 8 个预设 + 用默认)
- 前台:index / new / thread 都按当前软件注入主题色,
  meta theme-color 也跟着变

验证:三功能专项 30/30;新旧回归全过
(全新安装 33/33、老基线 25/25、附件 22/22、安装向导 60/60、约束检查 20/20)
2026-11-01 16:39:09 +08:00
laoyang 9b822d2d9a 安装向导:加管理员用户名,精简为填表即装、装完进首页 (#1 #2)
## 管理员账号(用户名 + 口令)
原先只有口令,没有用户名。现在两者都有:
- 用户名词入库 settings 的 admin.username(2~32 位,字母数字下划线点连字符)
- 口令仍是 bcrypt 哈希存 admin.password_hash,明文不落任何文件
- 登录校验 fb_admin_verify_login():用户名或口令任一不对都返回同一句
  「用户名或口令不正确」,且用户名错时也照常跑一次 password_verify,避免用耗时探测账号
- 向后兼容:老部署只设了口令没用户名时,仍可只填口令登录,
  并在登录页提示补一个用户名

## 安装向导精简
按用户要求「没数据就初始化,填完进主页」:
- 必填只剩 4 项:网站名称、管理员用户名、口令、确认口令
- 站点描述 / 官方邮箱 / 站点根地址改为 hidden(可留空自动探测)
- 密钥、令牌原本就自动生成
- 安装成功后展示网站名称与用户名,2 秒自动跳首页,也有按钮
- 按钮文案改为「完成安装,进入首页」

## 修掉一个真实 bug
首页把软件说明当成站点描述,导致「软件有 note 时站点描述被顶掉」。
两者是不同的东西:站点描述是全局设置必须始终显示,软件说明另起一行补充。
老基线 D6「首页描述变为新描述」就是被这个 bug 弄失败的。

## 另一个坑
admin.username 忘了加进 fb_setting_keys() 白名单,fb_set_setting() 会静默丢弃,
表现为「安装时填了用户名,装完却没有」。已补。

验证:
- 全新安装流程 32/32(真空站:无 config.php、无 data/*.db)
- 老基线 25/25、附件专项 22/22、安装向导 60/60
- PHP 8.5 全部入口 0 弃用
2026-11-01 12:39:20 +08:00
laoyang 59f7466ae4 多软件归属:软件→分类两级,配置全部入库 (#1)
原先分类写死在 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=<slug>&cat=<slug>;老链接 ?cat=xxx 解析不到时退回全部,200 不 404

## 界面一致性
按用户要求去掉「单软件时隐藏软件选择器」的逻辑:
所有界面一致,配一个就列一个,配多个就列多个。

## 兼容
fb_categories() 现在必须传软件 id;fb_statuses() 返回行数组,
另有 fb_status_keys() 取 key=>name 映射。

验证:WSL 内临时实例实测——单软件显示 1 个软件条;两软件各显示
自己的分类集合与帖子,互不串;无 PHP 警告/致命错误。
2026-11-01 11:35:55 +08:00
laoyang cede838b5e FeedLite 初始提交:通用轻量级反馈系统(PHP + SQLite,零依赖)
- 前台:问题列表 / 详情 / 发布与回复(趣味问答验证码、蜜罐、IP 限流)
- 后台:先审后显、站点设置(站点标题/描述、附件存储、OSS 参数)、操作日志
- 附件:关闭 / 本机硬盘 / 阿里云 OSS 浏览器直传(ECS 实例 RAM 角色)三种模式
- 品牌资源:全套图标(favicon.ico / SVG / PNG 各尺寸 / manifest)
- 安全:CSRF、session 加固、.htaccess 屏蔽敏感文件、口令仅存哈希
- 配置:config.example.php 为模板,config.php 不入库
2026-09-28 20:34:37 +08:00