主题色改为自绘取色面板(任意取色);图标上传加即时预览与状态提示
一、颜色不够丰富 → 点击弹取色面板
用户:「还是不行,颜色还是不够丰富。让用户选择吧:点击之后弹出一个颜色选择器。」
原来只有一个原生 <input type=color> 小方块,用户不知道能点,
而且系统面板各浏览器样式不一、只能取纯色。
改成自绘面板:
色相/饱和度渐变板(Canvas)+ 明度滑块 + 十六进制输入 + 确定
12 个预设圆点降级为快捷方式,真正的能力是任意取色
交互:点色块弹出(下方空间不够自动翻上方)、板内拖动实时更新、
十六进制可手输、点确定或面板外关闭、Esc 关闭
⚠️ 光标定位踩了两个坑,都写进注释了:
① 不能用 canvas.offsetLeft(相对 offsetParent,受父级 padding 影响,
实测算出 236px 超出画布宽度 226px);要用两个 getBoundingClientRect 相减
② canvas 显示尺寸受 CSS width:100% 影响,≠ 内部像素 220×150,
必须用 rect.width 而不是 canvas.width
二、图标上传没反馈
用户:「上传的图标没有显示,也没有上传成功、失败之类的提示信息。」
后端逻辑完整(格式/大小/尺寸/存储模式都校验了),问题在**前端零反馈**:
裸 <input type=file>,选完文件什么都不发生,而提示条在页面顶部容易被错过。
加了 bindIconUpload():
① 选中文件立刻 FileReader 本地预览,不等提交
② 显示文件名 + 尺寸 + 大小,让用户确认选对了
③ 选之前就拦掉明显不合格的(格式/超 2MB/小于 32×32/空文件)
④ 非正方形给出警告(显示时会被裁切)
⚠️ 前端校验只是体验优化,绝不能当安全边界 ——
真正的校验仍在 PHP 的 fb_icon_store_upload() 里。
验证(用独立测试页 + 浏览器实测,不登录后台、不动数据):
面板初始隐藏 → 点击后 248×246 出现
Canvas 四角像素分别为灰白/蓝/黑 → 渐变确实画出来了
板上取色 → 隐藏字段 #2178d9 同步到按钮文字/十六进制框/预览色
点预设 → #2B822E;手输 → #a020f0;色相滑条 120° → #20f020
光标中心 (238,54) 落在画布区域 (11..237, 11..161) 内
4 个路由 200
This commit is contained in:
+29
-5
@@ -540,13 +540,25 @@ function fb_admin_taxonomy_page($pdo, $editSw, $editCat) {
|
||||
$sugColor = $curColor !== '' ? $curColor : fb_color_default_for($esw ? (int)$esw['id'] : 0);
|
||||
/* 🔴 必须用 fb_color_palette(),不要再在这里写死一份数组。
|
||||
* 以前这里硬编码了另外 8 个色值,和 util.php 的调色板完全不同步 ——
|
||||
* 结果后台只能选那 8 个,用户在后台挑不到新颜色,
|
||||
* 而他从没配置过的软件却会被分到「调色板里另一批」颜色。 */
|
||||
* 结果后台只能选那 8 个,用户在后台挑不到新颜色。 */
|
||||
$presets = fb_color_palette();
|
||||
/* 颜色选择:**点色块弹出取色面板**(色相/饱和度渐变 + 明度条 + 十六进制),
|
||||
* 而不是只给一排预设圆点。
|
||||
* 用户 2026-11-04:「还是不够丰富,让用户自己选:点击之后弹出一个颜色选择器。」
|
||||
* ⇒ 预设只是快捷方式,真正要给的是**任意取色**能力。
|
||||
* 原生 <input type="color"> 只有一个小方块,用户不知道能点,
|
||||
* 而且它的系统面板不在我们控制内(各浏览器样式不一)。
|
||||
* 这里自带一个面板:Canvas 渐变 + 拖动,谁都看得懂怎么用。 */
|
||||
echo ' <div class="field"><span>主题色<i class="hint">前台进这个软件时整体配色跟着变,用来区分不同软件</i></span>';
|
||||
echo ' <div class="color-row">';
|
||||
echo ' <input type="color" name="color" value="' . e($sugColor) . '" class="color-input">';
|
||||
echo ' <div class="color-presets">';
|
||||
echo ' <div class="color-row" data-colorpicker>';
|
||||
echo ' <button type="button" class="color-trigger" data-color-trigger'
|
||||
. ' style="--cur:' . e($sugColor) . '" title="点击选择颜色">'
|
||||
. ' <span class="color-trigger-chip"></span>'
|
||||
. ' <span class="color-trigger-hex">' . e(strtoupper($sugColor)) . '</span>'
|
||||
. ' </button>';
|
||||
echo ' <input type="hidden" name="color" value="' . e($sugColor) . '" data-color-value>';
|
||||
// 预设作为快捷色(点了就直接生效),保留但不占主位
|
||||
echo ' <div class="color-presets" aria-label="常用颜色">';
|
||||
foreach ($presets as $pc) {
|
||||
$on = strcasecmp($pc, $sugColor) === 0 ? ' on' : '';
|
||||
echo '<button type="button" class="color-preset' . $on . '" data-color="' . e($pc)
|
||||
@@ -554,6 +566,18 @@ function fb_admin_taxonomy_page($pdo, $editSw, $editCat) {
|
||||
}
|
||||
echo ' </div>';
|
||||
echo ' <button type="button" class="btn sm color-reset">用默认</button>';
|
||||
|
||||
/* 取色面板:默认隐藏,点色块才出现。位置由 JS 定位到触发按钮下方。 */
|
||||
echo ' <div class="cp" data-color-panel hidden>';
|
||||
echo ' <canvas class="cp-sv" width="220" height="150" data-cp-sv></canvas>';
|
||||
echo ' <div class="cp-cursor" data-cp-cursor></div>';
|
||||
echo ' <div class="cp-hue"><input type="range" min="0" max="360" value="0" data-cp-hue aria-label="色相"></div>';
|
||||
echo ' <div class="cp-foot">';
|
||||
echo ' <span class="cp-preview" data-cp-prev></span>';
|
||||
echo ' <input type="text" class="cp-hex" maxlength="7" value="' . e(strtoupper($sugColor)) . '" data-cp-hex aria-label="十六进制颜色值">';
|
||||
echo ' <button type="button" class="btn sm cp-ok" data-cp-ok>确定</button>';
|
||||
echo ' </div>';
|
||||
echo ' </div>';
|
||||
echo ' </div>';
|
||||
echo ' </div>';
|
||||
if ($esw) {
|
||||
|
||||
+1
-1
@@ -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', 39); }
|
||||
if (!defined('FB_ASSET_V')) { define('FB_ASSET_V', 41); }
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user