用户:「输入框、按钮、下拉框特别丑,一点设计感都没有,高度太随意,
全面检查一下。还有那个下载链接要它干什么?」
一、表单控件(这是主要工作量)
原来样式散在 6 处(.field / .filter-row / .filters / .mail-test / .admin 各一套),
padding 有 8/9/12px 三种,select 与 input 高度不等,并排放参差不齐。
改成一套体系:
- CSS 变量统一尺度:--ctl-h 38px / --ctl-h-sm 32px / --ctl-h-lg 42px,
统一圆角 9px、统一左右内边距 12px、统一边框与阴影
- 高度用「固定 height + line-height 居中」而不是 padding 撑
- 🔴 选择器必须**宽松**(按 type 通吃,不用 .field 之类限定)。
第一版限制了容器,导致后台零散布局里的裸 select/input 只有 19/21px,
和旁边 38px 按钮并排,正是用户说的高度随意。
放开后实测:19px → 38px,全部一致
- 下拉框自绘箭头(内联 SVG),不再用各平台不一的原生箭头,右侧留 34px
- 搜索框加左侧放大镜图标,并去掉 Chrome 自带清除按钮
- 聚焦统一 brand 光晕,悬停边框加深
- 按钮也改固定 height(原来 padding 撑出 38.3px,与输入框差 0.3px)
- .btn.sm 必须显式改 height,否则 padding 被 height 吃掉、小按钮还是 38px
文件选择按钮:原生控件重做成真按钮
<label class=file-btn> 包住 input[type=file]
input 用 clip 视觉隐藏(不能用 display:none,那样点不到也聚焦不了)
按钮内显示「选择图片」+ 图标 + 选中后的文件名
二、删除「下载地址」字段
它唯一用途:状态改为「已解决」时把邮件按钮换成「下载最新版本」。
收益小、维护成本高(每个软件都要填一条 URL)。
- 后台表单项删除
- mailer 里对应的判断分支也删掉,按钮统一「查看详情」
- ⚠️ 数据库 download_url 列**保留不删**:删列不可逆,万一要恢复还得迁一次
验证(用控件总览测试页 + 真实页面实测):
10 类控件高度全部 38px(文本/数字/下拉/搜索/文件按钮/主按钮/小按钮…),
文本域 110px,同一行垂直中心完全一致(935.3)
裸 select/input 从 19/21px 修正到 38px
下拉箭头 SVG 生效、右内边距 34px;搜索框放大镜生效、左内边距 36px
真实三个页面(提交页/列表页/详情页)逐一检查:
没有 checkbox/radio/file 被误改,所有可见控件高度收敛为 38(文本域 110)
下载地址字段:admin.php 输出与源码中均无 download_url 表单项
5 个路由 200
146 lines
6.4 KiB
PHP
146 lines
6.4 KiB
PHP
<?php
|
||
/**
|
||
* 启动引导:加载配置、注册自动加载、开启会话、初始化数据库。
|
||
* 所有页面(index/thread/new/api)都以此为入口。
|
||
*/
|
||
|
||
if (!defined('FB_ROOT')) {
|
||
define('FB_ROOT', dirname(__DIR__));
|
||
// 静态资源版本号:改 assets/ 下的 css/js 后把这个数字 +1,
|
||
// 让浏览器与 CDN 缓存失效。全站只此一处,别再往页面里写死数字。
|
||
if (!defined('FB_ASSET_V')) { define('FB_ASSET_V', 47); }
|
||
}
|
||
|
||
/* ------------------------------------------------------------------
|
||
* 错误显示策略必须最先设置:
|
||
* 任何被打印到页面的 Warning/Deprecated 都会让响应头提前发出,
|
||
* 从而令随后的 session_start() 失败(表现为「会话已过期」、CSRF 全部失效)。
|
||
* 所以这里在 require 任何库文件之前就把 display_errors 关掉。
|
||
* ------------------------------------------------------------------ */
|
||
@ini_set('display_errors', '0');
|
||
@ini_set('log_errors', '1');
|
||
error_reporting(E_ALL);
|
||
|
||
// 兜底:捕获致命错误时也不要向页面输出堆栈(生产环境)
|
||
if (!defined('FB_BOOTSTRAPPED')) {
|
||
define('FB_BOOTSTRAPPED', 1);
|
||
}
|
||
|
||
// 后台改设置后自增,用来让 fb_cfg 的进程内缓存失效
|
||
if (!isset($GLOBALS['__fb_cfg_stamp'])) {
|
||
$GLOBALS['__fb_cfg_stamp'] = 0;
|
||
}
|
||
|
||
if (!function_exists('fb_cfg')) {
|
||
/**
|
||
* 只读【配置文件】的值(config.php → config.example.php),
|
||
* **不叠加 settings 表、绝不触达数据库**。
|
||
*
|
||
* 为什么必须单独有这么一条通道:正常的 fb_cfg() 会去读 settings 表,
|
||
* 而读表要先 fb_db() —— 那一步会就地建出一个空数据库文件。
|
||
* 「是否已安装」的判定恰恰以「数据库文件在不在」为依据,
|
||
* 所以判定必须走这条不碰库的路径,否则第一秒就把安装态自己造出来了。
|
||
*/
|
||
function fb_cfg_file() {
|
||
static $file = null;
|
||
static $stamp = -1;
|
||
$now = isset($GLOBALS['__fb_cfg_stamp']) ? (int)$GLOBALS['__fb_cfg_stamp'] : 0;
|
||
if ($file === null || $stamp !== $now) {
|
||
$local = FB_ROOT . '/config.php';
|
||
$example = FB_ROOT . '/config.example.php';
|
||
if (is_file($local)) { $file = (array)(require $local); }
|
||
elseif (is_file($example)) { $file = (array)(require $example); }
|
||
else { $file = []; }
|
||
$stamp = $now;
|
||
}
|
||
return $file;
|
||
}
|
||
|
||
/**
|
||
* 读取配置(点分路径,如 fb_cfg('smtp.host'))
|
||
* 取值顺序:settings 表(后台改过的)> config.php(本地配置)> config.example.php(出厂默认)> $default
|
||
*
|
||
* config.php 不参与版本管理(见 .gitignore),新部署时可从 config.example.php 复制一份;
|
||
* 若不存在则直接以 config.example.php 为默认值运行,保证 clone 下来即可跑。
|
||
*/
|
||
function fb_cfg($path = null, $default = null) {
|
||
static $merged = null;
|
||
static $stamp = -1;
|
||
$now = isset($GLOBALS['__fb_cfg_stamp']) ? (int)$GLOBALS['__fb_cfg_stamp'] : 0;
|
||
if ($merged === null || $stamp !== $now) {
|
||
$cfg = fb_cfg_file();
|
||
// 后台设置以嵌套数组形式叠加在文件配置之上(只覆盖同名键)
|
||
$tree = function_exists('fb_setting_tree') ? fb_setting_tree() : [];
|
||
$merged = is_array($tree) && $tree ? array_replace_recursive($cfg, $tree) : $cfg;
|
||
$stamp = $now;
|
||
}
|
||
if ($path === null || $path === '') { return $merged; }
|
||
$cur = $merged;
|
||
foreach (explode('.', (string)$path) as $k) {
|
||
if (is_array($cur) && array_key_exists($k, $cur)) {
|
||
$cur = $cur[$k];
|
||
} else {
|
||
return $default;
|
||
}
|
||
}
|
||
return $cur;
|
||
}
|
||
}
|
||
|
||
/** 让 fb_cfg() 的进程内缓存失效(改了磁盘上的 config.php 后必须调用) */
|
||
function fb_cfg_flush() {
|
||
$GLOBALS['__fb_cfg_stamp'] = ((int)$GLOBALS['__fb_cfg_stamp']) + 1;
|
||
}
|
||
|
||
require_once FB_ROOT . '/lib/util.php';
|
||
require_once FB_ROOT . '/lib/db.php';
|
||
require_once FB_ROOT . '/lib/oss.php';
|
||
require_once FB_ROOT . '/lib/attach.php';
|
||
require_once FB_ROOT . '/lib/captcha.php';
|
||
require_once FB_ROOT . '/lib/mailer.php';
|
||
require_once FB_ROOT . '/lib/layout.php';
|
||
|
||
/* ------------------------------------------------------------------
|
||
* 安装引导:数据库还没生成(data/ 下没数据)就说明是全新部署,
|
||
* 一律先送去 install.php 填配置、建库、设口令,装完才进系统。
|
||
* 判据只看「数据库文件在不在」——绝不能在这里调 fb_db(),
|
||
* 因为那会就地建出一个空库、把安装态自己"装"出来,之后就再也进不了向导。
|
||
* ------------------------------------------------------------------ */
|
||
if (!defined('FB_SKIP_INSTALL_REDIRECT') && !fb_installed()) {
|
||
if (PHP_SAPI === 'cli') {
|
||
fwrite(STDERR, "FeedLite 尚未安装:请先在浏览器中打开本目录下的 install.php 完成安装。\n");
|
||
exit(1);
|
||
}
|
||
fb_redirect('install.php');
|
||
}
|
||
|
||
// 会话(CLI 下不启用)
|
||
if (PHP_SAPI !== 'cli' && session_status() !== PHP_SESSION_ACTIVE) {
|
||
$p = session_get_cookie_params();
|
||
$https = (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off');
|
||
@session_set_cookie_params([
|
||
'lifetime' => 0,
|
||
'path' => !empty($p['path']) ? $p['path'] : '/',
|
||
'domain' => '',
|
||
'secure' => $https,
|
||
'httponly' => true,
|
||
'samesite' => 'Lax',
|
||
]);
|
||
@session_start();
|
||
}
|
||
|
||
// 初始化数据库(建表)。
|
||
// ★ 只在【已安装】时做:未安装就建库,等于第一秒把这个状态自己抹掉,
|
||
// 安装向导(install.php)随后就会被判定成「已经装好了」而拒绝工作。
|
||
// install.php 在真正提交安装时会自己显式调用 fb_db()。
|
||
if (fb_installed()) {
|
||
fb_db();
|
||
// 顺手确保 uploads/ 目录与「禁止直读」规则在位且为最新版(local / oss 都需要)。
|
||
// ⚠️ 为什么放在这里:老站点上早已存在的旧版 .htaccess(曾允许直读)不会自己更新,
|
||
// 而部署账号通常对 uploads/ 无写权限 —— 只有 PHP(目录属主)能改。
|
||
// 函数内部只在「文件缺失或版本标记过期」时才写盘,命中后每次请求几乎零开销。
|
||
if (function_exists('fb_local_ensure_dir')) {
|
||
fb_local_ensure_dir();
|
||
}
|
||
}
|