下拉框改为自绘列表;修复新建软件缺排序字段

用户两个反馈:
① 「排序那个怎么删了?排序还得留着呀」
② 「所有下拉框拉下来之后全是灰色,不好看,重新设计」

一、排序字段(是误解,但确实有缺陷)

排序字段没有被删,一直在 if ($esw) 分支里渲染。
用户看到"没有",是因为他打开的是「添加软件」——
新建时 $esw 为空,整块不渲染,所以确实没有这一项。
这是真实缺陷:新建软件时无法指定排序。

修法:
- 把排序字段移出 if ($esw),新建/编辑都显示
- 新建时默认值 = 当前最大 sort_order + 1(排到最后)
- 后端 sw_add 改为优先用表单值(用 isset 判断,
  用户明确填 0 是合法值——排最前面,不能被当成"没填")

与「下载地址」不同:排序是真实会被用到的字段
(前台软件列表、顶栏三横线菜单都按它排),不能删。

二、下拉框重设计

为什么必须自绘:原生 select 的展开列表由浏览器绘制,
CSS 只能改 option 的底色,改不了圆角/行高/hover 高亮,
各平台样式还不一样(Windows 是灰方框)。用户说的"全是灰色"就是这个。

但不重写 HTML:全站 16 个 select,逐个改容易漏,
也会破坏 onchange 提交这类内联逻辑。

做法:原生 select 保留(视觉隐藏,仍参与提交与 change 事件),
JS 在旁生成按钮 + 浮层列表。
- 浮层用 position:fixed 挂 body,避免被 overflow:hidden 裁(踩过)
- 位置自动避让视口,下方不够翻上方
- 支持键盘:上下键 Home End Enter Esc
- 选中项带对勾
- 无 JS 时原生 select 仍可用

配色踩坑:选中项最初用 var(--brand-soft),而该变量会被软件主题色覆盖 ——
同步日历主题色 #ff3f44 时 --brand-soft 成了 #ffe8e9(粉红),
下拉里一片粉很难看。下拉是工具性控件,不该跟软件换色,
改用中性色:#eef1f5 选中 / #f1f3f6 hover,四个软件下完全一致。

验证(真实页面实测):
- 2 个 select 均被增强,原生已隐藏
- 面板白底 rgb(255,255,255)、圆角 11px、双层柔和阴影、7 个列表项
- 选中项 rgb(238,241,245)、hover rgb(241,243,246)、带对勾
- 四个软件(#0057b8/#ff3f44/#a556f7/#3571fb)下选中项底色完全相同,
  不再随主题色变粉
- 键盘下方向键三次 → 高亮「处理中」,底色正确
- 选择后 selectedIndex/value 同步、面板自动关闭、change 事件已触发
- 浮层 fixed 定位、完整可见、不被裁切
- 排序字段 3 处(软件/分类/状态)齐全;5 个路由 200
This commit is contained in:
2026-11-04 19:27:01 +08:00
parent 27614d8ca8
commit 9b971a5b92
4 changed files with 343 additions and 6 deletions
+21 -5
View File
@@ -150,7 +150,12 @@ function fb_admin_taxonomy_action($pdo, $act, $post) {
$slug = fb_sw_slugify($name, 'sw', $next);
}
if (fb_software($slug)) { return ['英文标识「' . $slug . '」已被占用,换一个。', 'error']; }
$sort = (int)$pdo->query('SELECT COALESCE(MAX(sort_order),0)+1 FROM software')->fetchColumn();
/* 排序:优先用表单里填的值(新建表单现在也有这一项了),
* 没填才算「排到最后」。用 isset 判断而不是空判断 ——
* 用户明确填 0 也是合法值(排最前面),不能被当成"没填"。 */
$sort = isset($post['sort_order']) && $post['sort_order'] !== ''
? (int)$post['sort_order']
: (int)$pdo->query('SELECT COALESCE(MAX(sort_order),0)+1 FROM software')->fetchColumn();
$color = fb_color_norm(isset($post['color']) ? $post['color'] : '');
$icon = fb_sw_icon_norm(isset($post['icon']) ? $post['icon'] : '');
$dl = fb_sw_url_norm(isset($post['download_url']) ? $post['download_url'] : '');
@@ -591,11 +596,22 @@ function fb_admin_taxonomy_page($pdo, $editSw, $editCat) {
echo ' </div>';
echo ' </div>';
echo ' </div>';
/* 排序字段:新建和编辑**都要有**。
* 之前只在 if ($esw) 分支里渲染,导致「添加软件」时根本没有这一项,
* 用户以为排序被删了。新建时给个默认值 = 当前最大排序+1(排到最后)。
*
* ⚠️ 与「下载地址」不同:排序是**真实会被用到**的字段
* (前台软件列表、顶栏三横线菜单都按它排),不能删。 */
$sortVal = 0;
if ($esw) {
$sortVal = (int)$esw['sort_order'];
} else {
$sortVal = (int)fb_db()->query('SELECT COALESCE(MAX(sort_order),0)+1 FROM software')->fetchColumn();
}
echo ' <label class="field field-narrow"><span>排序<i class="hint">数字小的排前面,同级按名称排</i></span>'
. '<input type="number" name="sort_order" min="0" max="999" value="' . $sortVal . '"></label>';
if ($esw) {
/* 排序是 1-2 位的小整数,占满整行很难看 —— 收窄成定宽。
* 用 .field-narrow 限制宽度,而不是让它跟着 .field 铺满。 */
echo ' <label class="field field-narrow"><span>排序<i class="hint">数字小的排前面,同级按名称排</i></span>'
. '<input type="number" name="sort_order" min="0" max="999" value="' . (int)$esw['sort_order'] . '"></label>';
echo ' <button class="btn primary" name="act" value="sw_edit" type="submit">保存</button> '
. '<a class="btn" href="admin.php?tab=taxonomy">取消</a>';
} else {
+1 -1
View File
@@ -8,7 +8,7 @@ if (!defined('FB_ROOT')) {
define('FB_ROOT', dirname(__DIR__));
// 静态资源版本号:改 assets/ 下的 css/js 后把这个数字 +1,
// 让浏览器与 CDN 缓存失效。全站只此一处,别再往页面里写死数字。
if (!defined('FB_ASSET_V')) { define('FB_ASSET_V', 47); }
if (!defined('FB_ASSET_V')) { define('FB_ASSET_V', 49); }
}
/* ------------------------------------------------------------------