Files
c-api/src/main/resources/static/views/demo.html
2025-08-29 00:56:22 +08:00

408 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>智能化管理系统</title>
<!-- 引入Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入Font Awesome图标库 -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 配置Tailwind自定义颜色 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#165DFF',
secondary: '#0FC6C2',
neutral: '#F5F7FA',
dark: '#1D2129',
light: '#F2F3F5'
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.card-hover {
@apply transition-all duration-300 hover:shadow-lg hover:-translate-y-1;
}
.menu-item {
@apply flex items-center gap-2 px-4 py-3 rounded-lg cursor-pointer transition-all duration-200;
}
.menu-item-active {
@apply bg-primary/10 text-primary font-medium;
}
.menu-item-inactive {
@apply hover:bg-light;
}
.modal-enter {
animation: fadeIn 0.3s ease-out forwards;
}
.modal-exit {
animation: fadeOut 0.3s ease-in forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes fadeOut {
from {
opacity: 1;
transform: translateY(0) scale(1);
}
to {
opacity: 0;
transform: translateY(-10px) scale(0.98);
}
}
}
</style>
</head>
<body class="bg-neutral min-h-screen font-sans text-dark overflow-x-hidden">
<!-- 顶部导航栏 - 优化Flex布局确保Logo左、用户右、菜单居中 -->
<!-- 顶部导航栏 -->
<header class="bg-white shadow-sm sticky top-0 z-40 h-16">
<div class="flex items-center h-full px-6">
<!-- 1. 系统 Logo + 名称:最左侧固定 -->
<div class="flex items-center space-x-3 flex-shrink-0">
<div class="w-10 h-10 rounded-lg bg-primary flex items-center justify-center">
<i class="fa fa-cubes text-white text-xl"></i>
</div>
<h1 class="text-xl font-bold whitespace-nowrap">智能管理平台</h1>
</div>
<!-- 2. 模块导航:中间自适应 -->
<nav class="flex-1 flex justify-center items-center space-x-1"
id="moduleContainer">
<!-- 动态加载的模块 -->
<div class="menu-item menu-item-inactive" id="loadingModules">
<i class="fa fa-spinner fa-spin text-lg"></i>
<span>加载模块中...</span>
</div>
</nav>
<!-- 3. 用户信息:最右侧固定 -->
<div class="relative flex-shrink-0" id="adminContainer">
<div class="menu-item menu-item-inactive flex items-center cursor-pointer">
<i class="fa fa-user-circle text-xl"></i>
<span class="ml-2">加载用户中...</span>
<i class="fa fa-angle-down ml-1"></i>
</div>
<!-- 下拉菜单内容 -->
<div class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg py-2 hidden z-50 border border-gray-100"
id="adminMenu">
<a href="#"
class="flex items-center gap-2 px-4 py-2 text-sm hover:bg-light transition-colors duration-200">
<i class="fa fa-sign-out text-gray-500"></i>
<span>退出系统</span>
</a>
</div>
</div>
</div>
</header>
<!-- 主内容区 - 保持不变 -->
<main class="container mx-auto px-6 py-8">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
</div>
</main>
<!-- 弹窗背景遮罩 - 保持不变 -->
<div id="modalOverlay"
class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden opacity-0 transition-opacity duration-300"></div>
<!-- 动态菜单弹窗 - 保持不变 -->
<div id="dynamicModal" class="fixed w-[600px] bg-white rounded-xl shadow-xl z-50 hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-center">
<h3 class="text-lg font-semibold flex items-center" id="modalTitle">
<i class="modal-icon fa text-primary mr-2"></i>
<span id="modalModuleName"></span>
</h3>
<button class="modal-close text-gray-400 hover:text-gray-600">
<i class="fa fa-times"></i>
</button>
</div>
</div>
<div class="p-6" id="menuContainer">
<!-- 菜单将在这里动态加载 -->
<div class="flex justify-center items-center h-40">
<i class="fa fa-spinner fa-spin text-2xl text-gray-400"></i>
</div>
</div>
</div>
<script>
// 模拟API请求函数 - 保持不变
const api = {
getModules: () =>
fetch('Sys/login/modules').then(res => res.json()),
getMenusByModuleCode: (moduleCode) =>
fetch(`Sys/login/menus?moduleCode=${moduleCode}`).then(res => res.json()),
getCurrentUser: () =>
fetch('Sys/login/me').then(res => res.json())
};
// 页面逻辑 - 仅优化管理员区域渲染时的对齐方式
document.addEventListener('DOMContentLoaded', function () {
const moduleContainer = document.getElementById('moduleContainer');
const adminContainer = document.getElementById('adminContainer');
const menuContainer = document.getElementById('menuContainer');
const modalTitle = document.getElementById('modalTitle');
const modalModuleName = document.getElementById('modalModuleName');
const modalIcon = document.querySelector('.modal-icon');
const dynamicModal = document.getElementById('dynamicModal');
const modalOverlay = document.getElementById('modalOverlay');
const modalCloseButtons = document.querySelectorAll('.modal-close');
// 加载模块列表 - 保持不变
loadModules();
// 加载当前用户信息 - 优化用户区域对齐(右对齐)
loadCurrentUser();
async function loadModules() {
try {
const modules = await api.getModules();
moduleContainer.innerHTML = '';
modules.forEach(module => {
const moduleElement = document.createElement('div');
moduleElement.className = 'menu-item menu-item-inactive';
moduleElement.setAttribute('data-module-code', module.moduleCode);
moduleElement.setAttribute('data-module-name', module.moduleName);
moduleElement.setAttribute('data-module-icon', module.cicon);
moduleElement.innerHTML = `
<i class="fa ${module.cicon} text-lg"></i>
<span>${module.moduleName}</span>
`;
moduleElement.addEventListener('click', function () {
const moduleCode = this.getAttribute('data-module-code');
const moduleName = this.getAttribute('data-module-name');
const moduleIcon = this.getAttribute('data-module-icon');
showModuleMenus(moduleCode, moduleName, moduleIcon, this);
});
moduleContainer.appendChild(moduleElement);
});
} catch (error) {
moduleContainer.innerHTML = `
<div class="menu-item menu-item-inactive text-red-500">
<i class="fa fa-exclamation-circle text-lg"></i>
<span>模块加载失败</span>
</div>
`;
console.error('加载模块失败:', error);
}
}
// 优化点:管理员区域渲染时保持右对齐
async function loadCurrentUser() {
try {
const user = await api.getCurrentUser();
// 关键优化用户信息区域采用justify-end右对齐
adminContainer.innerHTML = `
<div class="menu-item menu-item-inactive flex items-center justify-end cursor-pointer" id="adminUser">
<i class="fa fa-user-circle text-xl"></i>
<span class="ml-2">${user.uname}</span>
<i class="fa fa-angle-down ml-1"></i>
</div>
<div class="absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg py-2 hidden z-50 border border-gray-100" id="adminMenu">
<a href="#" class="flex items-center gap-2 px-4 py-2 text-sm hover:bg-light transition-colors duration-200">
<i class="fa fa-sign-out text-gray-300"></i>
<span>退出系统</span>
</a>
</div>
`;
// 重新绑定管理员下拉菜单事件
const adminUser = document.getElementById('adminUser');
const adminMenu = document.getElementById('adminMenu');
adminUser.addEventListener('click', function (e) {
e.stopPropagation();
adminMenu.classList.toggle('hidden');
});
} catch (error) {
adminContainer.innerHTML = `
<div class="menu-item menu-item-inactive flex items-center justify-end text-red-500">
<i class="fa fa-user-circle text-xl"></i>
<span class="ml-2">用户信息加载失败</span>
<i class="fa fa-angle-down ml-1"></i>
</div>
`;
console.error('加载用户信息失败:', error);
}
}
// 显示模块菜单 - 保持不变
async function showModuleMenus(moduleCode, moduleName, moduleIcon, menuItemElement) {
try {
modalModuleName.textContent = `${moduleName}菜单`;
modalIcon.className = `modal-icon fa ${moduleIcon} text-primary mr-2`;
menuContainer.innerHTML = `
<div class="flex justify-center items-center h-40">
<i class="fa fa-spinner fa-spin text-2xl text-gray-400"></i>
</div>
`;
const menus = await api.getMenusByModuleCode(moduleCode);
if (menus.length > 0) {
let menuHtml = '<div class="grid grid-cols-3 gap-4">';
menus.forEach(menu => {
menuHtml += `
<button class="flex flex-col items-center justify-center p-4 border border-gray-100 rounded-lg hover:border-primary hover:bg-primary/5 transition-colors"
onclick="window.location.href='${menu.chref}'">
<i class="fa ${menu.cicon} text-primary text-2xl mb-2"></i>
<span>${menu.menuName}</span>
</button>
`;
});
menuHtml += '</div>';
menuContainer.innerHTML = menuHtml;
} else {
menuContainer.innerHTML = `
<div class="flex flex-col justify-center items-center h-40 text-gray-500">
<i class="fa fa-folder-open-o text-3xl mb-2"></i>
<p>该模块暂无菜单</p>
</div>
`;
}
document.querySelectorAll('.menu-item').forEach(item => {
item.classList.remove('menu-item-active');
item.classList.add('menu-item-inactive');
});
menuItemElement.classList.remove('menu-item-inactive');
menuItemElement.classList.add('menu-item-active');
const rect = menuItemElement.getBoundingClientRect();
const windowWidth = window.innerWidth;
let leftPos = rect.left + window.scrollX;
if (leftPos + 600 > windowWidth) {
leftPos = windowWidth - 620;
}
dynamicModal.style.top = (rect.bottom + window.scrollY + 10) + 'px';
dynamicModal.style.left = leftPos + 'px';
dynamicModal.classList.remove('hidden');
dynamicModal.classList.add('modal-enter');
modalOverlay.classList.remove('hidden');
setTimeout(() => {
modalOverlay.style.opacity = '1';
}, 10);
document.body.style.overflow = 'hidden';
} catch (error) {
menuContainer.innerHTML = `
<div class="flex flex-col justify-center items-center h-40 text-red-500">
<i class="fa fa-exclamation-circle text-3xl mb-2"></i>
<p>菜单加载失败</p>
</div>
`;
console.error('加载菜单失败:', error);
}
}
// 关闭弹窗 - 保持不变
function closeModal() {
const activeModal = document.querySelector('.modal-enter');
if (activeModal) {
activeModal.classList.remove('modal-enter');
activeModal.classList.add('modal-exit');
modalOverlay.style.opacity = '0';
setTimeout(() => {
activeModal.classList.add('hidden');
activeModal.classList.remove('modal-exit');
modalOverlay.classList.add('hidden');
document.body.style.overflow = '';
document.querySelectorAll('.menu-item').forEach(menu => {
menu.classList.remove('menu-item-active');
menu.classList.add('menu-item-inactive');
});
}, 300);
}
}
// 弹窗关闭事件 - 保持不变
modalCloseButtons.forEach(button => {
button.addEventListener('click', closeModal);
});
modalOverlay.addEventListener('click', closeModal);
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
closeModal();
}
});
// 下拉菜单关闭事件 - 保持不变
document.addEventListener('click', function () {
const adminMenu = document.getElementById('adminMenu');
if (adminMenu) {
adminMenu.classList.add('hidden');
}
});
// 窗口 resize 事件 - 保持不变
window.addEventListener('resize', function () {
const activeModal = document.querySelector('.modal-enter');
if (activeModal) {
const activeMenuItem = document.querySelector('.menu-item-active');
if (activeMenuItem) {
const rect = activeMenuItem.getBoundingClientRect();
const windowWidth = window.innerWidth;
let leftPos = rect.left + window.scrollX;
if (leftPos + 600 > windowWidth) {
leftPos = windowWidth - 620;
}
activeModal.style.top = (rect.bottom + window.scrollY + 10) + 'px';
activeModal.style.left = leftPos + 'px';
}
}
});
});
</script>
</body>
</html>