|
|
@@ -247,6 +247,11 @@
|
|
|
from { transform: translateX(100%); opacity: 0; }
|
|
|
to { transform: translateX(0); opacity: 1; }
|
|
|
}
|
|
|
+
|
|
|
+ @keyframes slideInMobile {
|
|
|
+ from { transform: translateY(120%); opacity: 0; }
|
|
|
+ to { transform: translateY(0); opacity: 1; }
|
|
|
+ }
|
|
|
.msg-success { background-color: #4caf50; }
|
|
|
.msg-error { background-color: #f44336; }
|
|
|
|
|
|
@@ -263,14 +268,177 @@
|
|
|
flex-direction: column;
|
|
|
}
|
|
|
|
|
|
+ /* —— 移动端顶栏与抽屉导航(默认隐藏,见媒体查询)—— */
|
|
|
+ .mobile-topbar {
|
|
|
+ display: none;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ padding: 10px 14px;
|
|
|
+ padding-left: max(14px, env(safe-area-inset-left, 0px));
|
|
|
+ padding-right: max(14px, env(safe-area-inset-right, 0px));
|
|
|
+ padding-top: max(10px, env(safe-area-inset-top, 0px));
|
|
|
+ background: #2c3e50;
|
|
|
+ color: #fff;
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ z-index: 998;
|
|
|
+ min-height: 48px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
|
|
+ }
|
|
|
+
|
|
|
+ .mobile-menu-btn {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
+ margin: -6px 0 -6px -8px;
|
|
|
+ padding: 0;
|
|
|
+ border: none;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: rgba(255,255,255,0.12);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 1.35rem;
|
|
|
+ line-height: 1;
|
|
|
+ cursor: pointer;
|
|
|
+ -webkit-tap-highlight-color: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mobile-menu-btn:active {
|
|
|
+ background: rgba(255,255,255,0.22);
|
|
|
+ }
|
|
|
+
|
|
|
+ .mobile-topbar-title {
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 1.05rem;
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sidebar-backdrop {
|
|
|
+ display: none;
|
|
|
+ position: fixed;
|
|
|
+ inset: 0;
|
|
|
+ background: rgba(0,0,0,0.45);
|
|
|
+ z-index: 999;
|
|
|
+ -webkit-tap-highlight-color: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sidebar-backdrop.is-visible {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ body.nav-open {
|
|
|
+ overflow: hidden;
|
|
|
+ touch-action: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (max-width: 768px) {
|
|
|
+ .mobile-topbar {
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sidebar {
|
|
|
+ transform: translateX(-100%);
|
|
|
+ transition: transform 0.25s ease;
|
|
|
+ box-shadow: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sidebar.sidebar-open {
|
|
|
+ transform: translateX(0);
|
|
|
+ box-shadow: 4px 0 24px rgba(0,0,0,0.25);
|
|
|
+ }
|
|
|
+
|
|
|
+ .main-content {
|
|
|
+ margin-left: 0;
|
|
|
+ width: 100%;
|
|
|
+ padding: 16px;
|
|
|
+ padding-bottom: max(16px, env(safe-area-inset-bottom, 0px));
|
|
|
+ padding-top: calc(56px + env(safe-area-inset-top, 0px));
|
|
|
+ }
|
|
|
+
|
|
|
+ .module-header {
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .module-header h2 {
|
|
|
+ font-size: 1.35rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-section {
|
|
|
+ padding: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .control-row {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ }
|
|
|
+
|
|
|
+ .control-group {
|
|
|
+ min-width: 100%;
|
|
|
+ flex: 1 1 auto !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ input[type="text"],
|
|
|
+ input[type="number"],
|
|
|
+ input[type="email"],
|
|
|
+ input[type="password"],
|
|
|
+ select,
|
|
|
+ textarea {
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn {
|
|
|
+ min-height: 44px;
|
|
|
+ padding: 12px 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .nav-item {
|
|
|
+ min-height: 48px;
|
|
|
+ padding: 14px 22px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .logout-btn {
|
|
|
+ min-height: 44px;
|
|
|
+ padding: 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .message-box {
|
|
|
+ left: 12px;
|
|
|
+ right: 12px;
|
|
|
+ top: auto;
|
|
|
+ bottom: max(16px, env(safe-area-inset-bottom, 0px));
|
|
|
+ max-width: none;
|
|
|
+ padding: 14px 18px;
|
|
|
+ text-align: center;
|
|
|
+ animation-name: slideInMobile;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* 模块特定样式 */
|
|
|
{% block extra_styles %}{% endblock %}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
|
|
|
+ <header class="mobile-topbar" id="mobileTopbar" aria-hidden="false">
|
|
|
+ <button type="button" class="mobile-menu-btn" id="mobileMenuBtn" aria-label="打开导航菜单" aria-expanded="false">☰</button>
|
|
|
+ <span class="mobile-topbar-title">展厅控制</span>
|
|
|
+ </header>
|
|
|
+
|
|
|
+ <div class="sidebar-backdrop" id="sidebarBackdrop" aria-hidden="true"></div>
|
|
|
+
|
|
|
<!-- 侧边栏 -->
|
|
|
- <div class="sidebar">
|
|
|
+ <div class="sidebar" id="sidebar">
|
|
|
<div class="sidebar-header">
|
|
|
<h1>展厅控制</h1>
|
|
|
<p>Admin Dashboard</p>
|
|
|
@@ -330,6 +498,68 @@
|
|
|
function showLoading(show = true) {
|
|
|
document.getElementById('loadingOverlay').style.display = show ? 'flex' : 'none';
|
|
|
}
|
|
|
+
|
|
|
+ (function () {
|
|
|
+ const mq = window.matchMedia('(max-width: 768px)');
|
|
|
+ const sidebar = document.getElementById('sidebar');
|
|
|
+ const backdrop = document.getElementById('sidebarBackdrop');
|
|
|
+ const menuBtn = document.getElementById('mobileMenuBtn');
|
|
|
+
|
|
|
+ function closeMobileNav() {
|
|
|
+ sidebar.classList.remove('sidebar-open');
|
|
|
+ backdrop.classList.remove('is-visible');
|
|
|
+ document.body.classList.remove('nav-open');
|
|
|
+ backdrop.setAttribute('aria-hidden', 'true');
|
|
|
+ if (menuBtn) {
|
|
|
+ menuBtn.setAttribute('aria-expanded', 'false');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function openMobileNav() {
|
|
|
+ sidebar.classList.add('sidebar-open');
|
|
|
+ backdrop.classList.add('is-visible');
|
|
|
+ document.body.classList.add('nav-open');
|
|
|
+ backdrop.setAttribute('aria-hidden', 'false');
|
|
|
+ if (menuBtn) {
|
|
|
+ menuBtn.setAttribute('aria-expanded', 'true');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function toggleMobileNav() {
|
|
|
+ if (sidebar.classList.contains('sidebar-open')) {
|
|
|
+ closeMobileNav();
|
|
|
+ } else {
|
|
|
+ openMobileNav();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (menuBtn) {
|
|
|
+ menuBtn.addEventListener('click', toggleMobileNav);
|
|
|
+ }
|
|
|
+ if (backdrop) {
|
|
|
+ backdrop.addEventListener('click', closeMobileNav);
|
|
|
+ }
|
|
|
+
|
|
|
+ document.querySelectorAll('#sidebar .nav-item, #sidebar .logout-btn').forEach(function (el) {
|
|
|
+ el.addEventListener('click', function () {
|
|
|
+ if (mq.matches) {
|
|
|
+ closeMobileNav();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ window.addEventListener('resize', function () {
|
|
|
+ if (!mq.matches) {
|
|
|
+ closeMobileNav();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ document.addEventListener('keydown', function (e) {
|
|
|
+ if (e.key === 'Escape' && mq.matches) {
|
|
|
+ closeMobileNav();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })();
|
|
|
</script>
|
|
|
|
|
|
{% block scripts %}
|