,不能让 javascript:/data: 混进来
if ($curl !== '' && !preg_match('~^https?://~i', $curl)) {
return '页脚链接地址需以 http:// 或 https:// 开头。';
}
if ($curl === '' || $curl === fb_credit_url_default()) { fb_unset_setting('footer.credit_url'); }
else { fb_set_setting('footer.credit_url', $curl); }
$ints = [
'upload.image_max_per_post' => [0, 20],
'upload.video_max_per_post' => [0, 10],
'upload.retention_days' => [1, 3650],
'upload.upload_per_hour' => [1, 2000],
'upload.image_max_side' => [480, 4096],
];
foreach ($ints as $k => $range) {
$v = (int)$post($k, 0);
$v = max($range[0], min($range[1], $v));
fb_set_setting($k, $v);
}
// MB → 字节
$mbs = [
'upload.image_max_bytes' => [0.2, 50],
'upload.video_max_bytes' => [1, 500],
'upload.total_cap_bytes' => [10, 100000],
];
foreach ($mbs as $k => $range) {
$mb = (float)$post($k, 0);
$mb = max($range[0], min($range[1], $mb));
fb_set_setting($k, (int)round($mb * 1048576));
}
$storage = (string)$post('attachment.storage', 'off');
if (!in_array($storage, ['off', 'local', 'oss'], true)) { $storage = 'off'; }
fb_set_setting('attachment.storage', $storage);
// OSS 模式下 oss.enabled 必须跟着开;其它模式关掉,避免误判
fb_set_setting('oss.enabled', $storage === 'oss' ? 1 : 0);
$texts = ['oss.endpoint', 'oss.bucket', 'oss.instance_role', 'oss.domain', 'oss.prefix', 'moderation.close_mail_subject'];
foreach ($texts as $k) {
$v = trim((string)$post($k, ''));
// 对象键前缀留空会让对象键变成 "/2026/...",回落到出厂默认 'fb'
if ($k === 'oss.prefix' && $v === '') { fb_unset_setting($k); continue; }
fb_set_setting($k, $v);
}
$src = (string)$post('oss.credential_source', 'instance_role');
fb_set_setting('oss.credential_source', $src === 'static' ? 'static' : 'instance_role');
fb_set_setting('oss.access_key', trim((string)$post('oss.access_key', '')));
$sk = trim((string)$post('oss.secret_key', ''));
if ($sk !== '') { fb_set_setting('oss.secret_key', $sk); }
fb_set_setting('oss.visibility', ((string)$post('oss.visibility', 'public')) === 'private' ? 'private' : 'public');
fb_set_setting('oss.url_scheme', ((string)$post('oss.url_scheme', 'https')) === 'http' ? 'http' : 'https');
fb_set_setting('oss.verify', $post('oss.verify') ? 1 : 0);
fb_set_setting('oss.image_process', $post('oss.image_process') ? 1 : 0);
fb_set_setting('oss.use_internal_endpoint', $post('oss.use_internal_endpoint') ? 1 : 0);
fb_set_setting('moderation.enabled', $post('moderation.enabled') ? 1 : 0);
fb_mod_log('settings', null, '保存站点设置:存储=' . $storage);
return '设置已保存。';
}
/* ==================================================================
* 页面
* ================================================================== */
$tab = (string)(isset($_GET['tab']) ? $_GET['tab'] : 'pending');
if (!in_array($tab, ['pending', 'all', 'thread', 'settings', 'log'], true)) { $tab = 'pending'; }
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"
)->fetchAll();
?>
待审核 ()
prepare('SELECT COUNT(*) FROM threads ' . $wSql);
$cntSt->execute($args);
$total = (int)$cntSt->fetchColumn();
$pageSize = max(5, (int)fb_cfg('page_size', 20));
$pages = max(1, (int)ceil($total / $pageSize));
$page = min(max(1, (int)(isset($_GET['page']) ? $_GET['page'] : 1)), $pages);
$offset = ($page - 1) * $pageSize;
$lst = $pdo->prepare('SELECT * FROM threads ' . $wSql . ' ORDER BY updated_at DESC LIMIT ' . (int)$pageSize . ' OFFSET ' . (int)$offset);
$lst->execute($args);
$rows = $lst->fetchAll();
?>
全部问题 ( 条,第 / 页)
1): ?>
prepare('SELECT * FROM replies WHERE thread_id = ? ORDER BY created_at ASC, id ASC');
$rs->execute([$id]);
$replies = $rs->fetchAll();
$atts = fb_attach_for_thread($pdo, $id);
?>
以官方身份回复
状态与可见性
处理状态
$label): ?>
>
公开显示
> 在公开列表中显示
保存
通过并公开
撤下
关闭(判定不是应用问题,会发邮件给提问人)
关闭说明 * 会作为邮件正文发给
关闭并邮件告知
删除这条问题
站点信息
站点标题
显示在浏览器标签、页面顶栏与页脚。用它说明「本系统为哪个软件提供反馈服务」,如「XX 软件 · 问题反馈」。
站点描述
显示在首页标题下方,一句话说明这里可以反馈什么。两项都留空则恢复为出厂默认。
页脚
> 在页脚显示「由 FeedLite 驱动」
取消勾选后,这句话连同链接都不再出现在页脚,只保留「管理后台」入口。
FeedLite 链接地址
页脚「FeedLite」二字指向的地址,默认是本项目开源仓库。只接受 http:// 或 https:// 开头的网址;填回默认值即恢复。
附件存储
附件保存在哪
>关闭(不开放上传)
>本机硬盘(站点 uploads/ 目录)
>阿里云 OSS(私有桶 · 服务器代理)
本机:文件落在站点 uploads/ 目录;OSS:文件经服务器代理写入私有桶(走内网 Endpoint),公网无法直连桶。两种方式都需要服务器磁盘能放下单个上传文件。
每个问题最多几张图片
单张图片上限(MB)
每个问题最多几个视频
单个视频上限(MB)
全站附件总量上限(MB)
附件保留天数
每 IP 每小时最多上传几次
图片压缩后的最长边(像素)
阿里云 OSS(选「OSS」时才需要填)
私有桶 + 服务器代理:浏览器不直连桶,附件读写都经本站 upload.php / media.php 中转。Endpoint 填公网或内网形式都可以,程序按下方开关自动转换。
Endpoint
Bucket 名
鉴权方式
>ECS 实例 RAM 角色(推荐)
>静态 AccessKey
ECS 实例 RAM 角色名
AccessKeyId(静态鉴权用)
AccessKeySecret(留空=不修改)
对象键前缀
公网访问协议(走公网 Endpoint 时)
>https
>http
> 使用内网 Endpoint(*-internal.aliyuncs.com,免公网流量费、延迟低)
⚠️ 仅当【桶与本机 ECS 同地域】时可用;跨地域内网不可达,请取消勾选回落公网,或改用同地域的桶。保存后可在下方「存储体检」查看连通性。
> 提交时回源复核附件(防伪造)
> 缩略图使用 OSS 图片处理(服务端缩放后再转发,省下行流量)
审核
> 先审后显(新提交的问题默认不公开,需你通过后才显示)
关闭通知邮件标题
%s 会替换成问题标题。
保存设置
存储体检
登录口令
query('SELECT * FROM mod_log ORDER BY created_at DESC, id DESC LIMIT 100')->fetchAll();
?>
最近操作 ( 条)