fix(admin): 修复移动端后台侧栏错位与子菜单不收起

根因:此前为移动端手写的一段折叠逻辑直接给 body 加 pear-mini,
绕过了 admin.js 里唯一的同步入口 collapse(),导致三处状态错位——
布局层认为已折叠(侧栏宽 0、菜单文字被 CSS 隐藏),
菜单 DOM 仍是展开态(#side 没有 pear-nav-mini),于是"文字看不见、
但子菜单又在原地铺开"。

处理:
- templates/system/index.html 还原为框架原始版本,删除手写的
  foldSidebar() IIFE 与首屏强制加类逻辑
- 删除无引用的死文件 templates/system/common/{head,side}.html
- 新增插件 plugins/mobileUI,以运行时注入 mobile.js 的方式实现移动端增强:
  * 首屏折叠只通过框架的 li.collapse 点击完成,不手写 class
  * 轮询等待菜单异步渲染就绪后再折叠
  * 补齐 framework 内部状态 isCollapse(后端 /rights/configs 把键拼成了
    "collaspe",admin.js 读 collapse 恒为 undefined,窄屏 resize 会反向展开)
  * 触屏下点击菜单外区域收起 mini 浮层(触屏没有可靠的 mouseleave)
  * 展开态点击叶子菜单后自动收起侧栏
- applications/config.py 的 PLUGIN_ENABLE_FOLDERS 追加 cookieManager、mobileUI

framework 业务逻辑零改动,仅 config.py 一行配置。
This commit is contained in:
bwstudio
2026-09-09 19:20:03 +08:00
parent 3e8c490851
commit b0865ea18d
8 changed files with 283 additions and 135 deletions
-26
View File
@@ -1,26 +0,0 @@
<!-- 后台顶部导航条(顶栏) -->
<!-- 与 templates/system/index.html 主页的 .layui-header 部分等价;供所有子模块引用 -->
<div class="layui-header">
<div class="layui-logo">
<img class="logo">
<span class="title"></span>
</div>
<ul class="layui-nav layui-layout-left">
<li class="collapse layui-nav-item"><a href="#" class="layui-icon layui-icon-shrink-right"></a></li>
<li class="refresh layui-nav-item"><a href="#" class="layui-icon layui-icon-refresh-1" loading=600></a></li>
</ul>
<div id="control" class="layui-layout-control"></div>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item layui-hide-xs"><a href="#" class="menuSearch layui-icon layui-icon-search"></a></li>
<li class="layui-nav-item layui-hide-xs message"></li>
<li class="layui-nav-item layui-hide-xs"><a href="#" class="fullScreen layui-icon layui-icon-screen-full"></a></li>
<li class="layui-nav-item user">
<a class="layui-icon layui-icon-username" href="javascript:;"></a>
<dl class="layui-nav-child">
<dd><a href="javascript:void(0);" user-menu-url="/system/user/center" user-menu-id="5555" user-menu-title="基本资料">基本资料</a></dd>
<dd><a href="javascript:void(0);" class="logout">注销登录</a></dd>
</dl>
</li>
<li class="layui-nav-item setting"><a href="#" class="layui-icon layui-icon-more-vertical"></a></li>
</ul>
</div>
-74
View File
@@ -1,74 +0,0 @@
<!-- 后台左侧菜单(侧栏) -->
<!-- 与 templates/system/index.html 主页的 .layui-side 部分等价;供所有子模块引用 -->
<div class="layui-side layui-bg-black">
<div class="layui-logo">
<img class="logo">
<span class="title"></span>
</div>
<div class="layui-side-scroll">
<div id="side"></div>
</div>
</div>
<!-- 依赖脚本 + 框架初始化 -->
<script src="{{ url_for('static', filename='system/component/layui/layui.js') }}"></script>
<script src="{{ url_for('static', filename='system/component/pear/pear.js') }}"></script>
<script>
layui.use(['admin', 'jquery', 'popup'], function () {
var admin = layui.admin;
var popup = layui.popup;
var $ = layui.jquery;
admin.setConfigurationPath("{{ url_for('system.rights.configs') }}");
admin._changeTheme = admin.changeTheme;
admin.changeTheme = function () {
admin._changeTheme();
const variableKey = "--global-primary-color";
const variableVal = localStorage.getItem("theme-color-color");
const iframes = document.querySelectorAll('iframe');
iframes.forEach(function (iframe) {
try {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.documentElement.style.setProperty(variableKey, variableVal);
} catch (e) {}
});
};
admin._switchTheme = admin.switchTheme;
admin.switchTheme = function (checked) {
admin.isdrak = checked;
admin._switchTheme(checked);
const iframes = document.querySelectorAll('iframe');
iframes.forEach(function (iframe) {
try {
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
if (checked === true || checked === "true") {
iframeDocument.body.classList.add("pear-admin-dark");
} else {
iframeDocument.body.classList.remove("pear-admin-dark");
}
} catch (e) {}
});
};
admin.render();
admin.logout(function () {
let loading = layer.load();
$.ajax({
url: '{{ url_for('system.passport.logout') }}',
dataType: 'json',
async: false,
type: 'post',
success: function (result) {
layer.close(loading);
if (result.success) {
popup.success(result.msg, function () { location.href = '/'; });
return true;
}
}
});
});
});
</script>