Files
FamilyBook/templates/settings/_modules.php
T

177 lines
8.2 KiB
PHP
Raw Normal View History

<?php
/**
* 个人设置里的两块「模块」设置(用户 2026-10-01 第 10、11 条):
*
* ① **导航条上显示哪些模块、什么顺序** —— 每人一份(App\Module::navFor 读的就是它)。
* 勾选 = 出现在导航条上;拖动 / ▲▼ = 排序。
* ② **每个模块的主题色** —— **家庭一份**(settings('module_colors')),
* 所以只有管理员能改:一个家认同一套配色,不然同一个"观影"在爸爸那屏是紫的、
* 妈妈那屏是绿的,反而记不住。非管理员在这里只看得到色板。
*
* 变量(require 前设好):
* $navKeys 我当前导航条上的顺序(只含显示的)
* $colors key => '#rrggbb'
*/
$allKeys = \App\Module::keys();
$onKeys = array_map('strval', (array)($navKeys ?? []));
// 显示顺序:已勾选的按现有顺序在前,未勾选的按 LIST 顺序在后(这样"关掉再打开"位置不跳)
$ordered = array_values(array_filter($allKeys, static fn($k) => in_array($k, $onKeys, true)));
foreach ($allKeys as $k) {
if (!in_array($k, $ordered, true)) {
$ordered[] = $k;
}
}
$isAdmin = \App\Auth::isAdmin();
?>
<!-- ==================== 导航条上的模块 ==================== -->
<div class="card card-pad" id="modules" style="margin-top:20px">
<h2 class="section-title">
导航条上的模块
<span class="hint">勾上才会出现在顶部,拖动可改顺序</span>
</h2>
<p class="small muted" style="margin:0 0 16px">
模块越来越多,但每个人关心的不一样 —— 这里只挑你常用的几个上导航条,其余的仍然能
从别处进(比如观影里还能进影院管理)。关掉的模块<b>不会丢数据</b>,只是从顶栏收起来。
</p>
<form method="post" action="<?= e(url('settings/nav_save')) ?>" id="navForm">
<?= csrf_field() ?>
<ol class="order-list mod-order" id="navOrderList">
<?php foreach ($ordered as $i => $k): ?>
<li class="order-row mod-row" draggable="true" data-key="<?= e($k) ?>">
<span class="drag-handle" title="拖我排序" aria-hidden="true">⋮⋮</span>
<?php /* ⚠️ 顺序就藏在 DOM 里:每个 <li> 自带一个 order[] 隐藏域,
拖动搬的是整个 <li>,所以提交上来的顺序天然就是屏幕上的顺序。
没有 JS 时 ▲▼ 按钮走同一份表单(服务端按 move 参数交换后再存)。 */ ?>
<input type="hidden" name="order[]" value="<?= e($k) ?>">
<label class="mod-pick">
<input type="checkbox" name="on[]" value="<?= e($k) ?>"
<?= in_array($k, $onKeys, true) ? 'checked' : '' ?>>
<span class="color-preview" style="background: <?= e((string)($colors[$k] ?? '#888')) ?>;"></span>
<span class="order-name"><?= e(\App\Module::name($k)) ?></span>
</label>
<span class="order-move">
<button class="btn btn-ghost btn-sm" type="submit" name="move" value="up:<?= e($k) ?>"
title="上移" <?= $i === 0 ? 'disabled' : '' ?>>▲</button>
<button class="btn btn-ghost btn-sm" type="submit" name="move" value="down:<?= e($k) ?>"
title="下移" <?= $i === count($ordered) - 1 ? 'disabled' : '' ?>>▼</button>
</span>
</li>
<?php endforeach; ?>
</ol>
<div class="btn-row">
<button class="btn" type="submit" name="save" value="1">保存导航条</button>
<a class="btn btn-ghost" href="<?= e(url('settings/me')) ?>">重来</a>
</div>
</form>
</div>
<!-- ==================== 模块主题色 ==================== -->
<div class="card card-pad" style="margin-top:20px">
<h2 class="section-title">
模块主题色
<span class="hint"><?= $isAdmin ? '全家共用一套' : '由管理员设置' ?></span>
</h2>
<p class="small muted" style="margin:0 0 16px">
进到哪个模块,顶栏高亮与按钮就换成那个模块的颜色 —— 一眼就知道自己在哪儿。
<?php if (!$isAdmin): ?>
<br>这是<b>全家共用</b>的一套配色(不然同一个「观影」在两个人屏幕上两种颜色,反而记不住),
所以只有管理员能改。
<?php endif; ?>
</p>
<?php if (!$isAdmin): ?>
<div class="mod-swatches">
<?php foreach ($allKeys as $k): ?>
<span class="mod-swatch">
<span class="color-preview" style="background: <?= e((string)($colors[$k] ?? '#888')) ?>;"></span>
<?= e(\App\Module::name($k)) ?>
</span>
<?php endforeach; ?>
</div>
<?php else: ?>
<form method="post" action="<?= e(url('settings/module_colors')) ?>">
<?= csrf_field() ?>
<div class="mod-colors">
<?php foreach ($allKeys as $k): ?>
<?php $cid = 'mc-' . $k; ?>
<div class="mod-color-row">
<span class="mod-color-name"><?= e(\App\Module::name($k)) ?></span>
<input type="color" class="color-picker" id="<?= e($cid) ?>" name="c[<?= e($k) ?>]"
value="<?= e((string)($colors[$k] ?? '#888888')) ?>">
<span class="mod-preset">
<?php foreach (\App\Module::PRESET_COLORS as $pc): ?>
<span class="preset-color" data-color="<?= $pc ?>" data-for="<?= e($cid) ?>"
style="background: <?= $pc ?>;" title="<?= $pc ?>"></span>
<?php endforeach; ?>
</span>
</div>
<?php endforeach; ?>
</div>
<div class="btn-row">
<button class="btn" type="submit">保存主题色</button>
<button class="btn btn-ghost" type="submit" name="reset" value="1"
onclick="return confirm('恢复成默认配色?')">恢复默认</button>
</div>
</form>
<?php endif; ?>
</div>
<script>
(function () {
/* ---- 拖动排序(▲▼ 是不用 JS 的兜底,两条路都能用)----
⚠️ 遍历**所有** `ol.order-list`,而不是只找 navOrderList:
本页现在有两块同构的清单(首页上的模块 / 导航条上的模块),
写死 id 的话第二块就没有拖动了 —— 而且看起来"功能好好的",
只是那一块拖不动,很难联想到是这里写死了 id。 */
function bindSort(list) {
if (!list) return;
var dragEl = null;
Array.prototype.forEach.call(list.querySelectorAll('.mod-row'), function (li) {
li.addEventListener('dragstart', function (ev) {
dragEl = li;
li.classList.add('is-dragged');
if (ev.dataTransfer) { ev.dataTransfer.effectAllowed = 'move'; }
});
li.addEventListener('dragend', function () {
li.classList.remove('is-dragged');
dragEl = null;
Array.prototype.forEach.call(list.querySelectorAll('.mod-row'), function (x) {
x.classList.remove('is-drop-before');
});
});
li.addEventListener('dragover', function (ev) {
if (!dragEl || dragEl === li) return;
ev.preventDefault();
var box = li.getBoundingClientRect();
var before = ev.clientY < box.top + box.height / 2;
li.classList.toggle('is-drop-before', before);
li.classList.toggle('is-drop-after', !before);
});
li.addEventListener('dragleave', function () {
li.classList.remove('is-drop-before', 'is-drop-after');
});
li.addEventListener('drop', function (ev) {
if (!dragEl || dragEl === li) return;
ev.preventDefault();
var box = li.getBoundingClientRect();
var before = ev.clientY < box.top + box.height / 2;
/* 搬的是整个 <li> —— 它自带的 order[] 隐藏域跟着走,
所以提交上来的顺序 = 屏幕上的顺序,不用再同步一遍。 */
if (before) { list.insertBefore(dragEl, li); } else { list.insertBefore(dragEl, li.nextSibling); }
li.classList.remove('is-drop-before', 'is-drop-after');
});
});
}
Array.prototype.forEach.call(document.querySelectorAll('ol.order-list'), bindSort);
/* ---- 色板点一下就换 ---- */
Array.prototype.forEach.call(document.querySelectorAll('.preset-color[data-for]'), function (el) {
el.addEventListener('click', function () {
var target = document.getElementById(el.getAttribute('data-for'));
if (target) { target.value = el.getAttribute('data-color'); }
});
});
})();
</script>