用vscode及人工智能插件磨合的一个后台管理页面(完成就分享,多少有点粗糙,不喜欢可以疯狂抽我)
1、预览
![image]()
2、资源介绍和运行环境
# 1、总共有4个文件:index.html、script.js、style.css、package.json,新建一个项目目录放入这4个文件,目录不能有中文,node要求不能有中文
# 2、然后新建pages文件夹,里面自己新建4个页面:about.html,dictionary.html,menu.html,users.html (根据自己的项目加减)
# 3、首先确保安装了node,去报npm能用
# 4、在项目根目录也就是有package.json的目录,打开终端(cmd)执行npm install ,安装依赖,我配置的vite构建工具(知道的不用解释,不知道的就直接安装就行,会多出来node_modules文件夹和package-lock.json文件,反正我前端也不熟😄)
# 5、好了以后,运行起来项目,终端中执行 npm run dev 提示 http://localhost:5173 大概就成功了,浏览器可以输入网址运行
# (vite支持热更新之类的,就是你javascript 和 html css修改完马上见效果,vite自带http服务器,所以选择vite,其他工具也行 webpack啥的,反正我也不熟)
3、功能说明
# 1、项目分一级导航菜单和左侧菜单栏
# 2、一级导航菜单位于“xx企业管理系统”后面,比如你看到的“系统管理”,后续也可以增加一些“业务管理”、“流程管理”,总之它是比较大的块,让你可以分块管理
# 3、一级导航菜单尽量少一点吧,毕竟它在系统名称后面,也没多少空间
# 4、script.js有一个变量记载了菜单的json数据结构:
const MENU_PERMISSIONS = {
"系统管理": {
"url": "#",
"icon": "fa fa-folder",
"target": "expand",
"is_menu": "1",
"children": {
"系统信息管理": {
"url": "#",
"icon": "fa fa-desktop",
"target": "expand",
"is_menu": "1",
"children": {
"菜单管理": {
"url": "/pages/menu.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
},
"字典管理": {
"url": "/pages/dictionary.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
},
"用户管理": {
"url": "/pages/users.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
}
}
}
}
}
};
# 5、你可以自己按照规则扩展一些菜单,上面的例子可以看到第一个键值对的key=“系统管理”,就是一级菜单,
# 6、每个菜单都是一个键值对,键就是菜单的名称,url是菜单路径,只有target=iframe的时候它才是具体的路径,否则设置成“#”
# 7、icon是图标,应该跟你的引入的font-awesome版本强相关,必须是里面有的选项
# 8、target是菜单打开方式,如果是expand其实就是展开和关闭的菜单,iframe是可以打开新的页面的,我们当前项目打开到iframe标签中
# 9、is_menu:1代表菜单,0代表不是菜单
# 10、所以你用这个项目,就需要整理出这个菜单的json数据,你的数据库菜单表必须至少包含这些字段才行
# 11、首页在页面加载的时候默认打开的,左侧菜单栏点击菜单,都会在首页后面增加新的标签页,并自动增加一个iframe标签
# 12、其他自己演示一下就知道了
4、index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统管理界面</title>
<!-- Bootstrap 5.3.0 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- 主界面 -->
<div class="container-fluid p-0">
<!-- 侧边栏 -->
<div class="sidebar col-md-3 col-lg-2 d-md-block">
<div class="sidebar-header">
<!-- <h6>菜单栏</h6> -->
</div>
<div class="position-sticky">
<ul class="nav flex-column">
</ul>
</div>
</div>
<!-- 主内容区域 -->
<main class="main-content">
<!-- 系统名称 -->
<div class="system-header">
<div class="header-left">
<i id="menu-toggle" class="fas fa-bars me-3"></i>
<h4 class="system-title"><strong>xx企业管理系统</strong></h4>
<!-- 一级菜单导航,添加特定类名 -->
<div class="nav primary-nav">
<ul class="nav flex-column primary-nav-list">
<!-- 菜单项会通过 JS 动态生成 -->
</ul>
</div>
</div>
<div class="header-right">
<div class="search-box">
<input type="text" class="form-control" placeholder="搜索">
<i class="fas fa-search search-icon"></i>
</div>
<!-- 添加徽章 -->
<span class="position-relative">
<i class="fas fa-bell header-icon" title="消息"></i>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
3
</span>
</span>
<!-- 将用户图标、用户信息和箭头图标放在一个 div 中 -->
<div class="user-dropdown-trigger dropdown-toggle" id="user-dropdown-trigger">
<i class="fas fa-user header-icon" title="用户"></i>
<span class="user-info">admin-管理员</span>
</div>
<div class="dropdown">
<ul class="dropdown-menu dropdown-menu-end" id="user-dropdown-menu">
<li><a class="dropdown-item" href="#">修改密码</a></li>
<li><a class="dropdown-item" href="#">安全退出</a></li>
</ul>
</div>
</div>
</div>
<!-- 标签头信息 -->
<div class="tag-header">
<!-- 左箭头 -->
<div class="tag-arrow">
<i id="tag-arrow-prev" class="fas fa-backward"></i>
</div>
<!-- 标签导航 -->
<ul class="nav nav-tabs" id="tag-tabs">
<!-- <li class="nav-item">
<a class="nav-link active" data-url="pages/about.html" href="#">
首页
</a>
</li> -->
</ul>
<!-- 右箭头 -->
<div class="tag-arrow">
<i id="tag-arrow-next" class="fas fa-forward"></i>
</div>
</div>
<!-- 内容区域 -->
<div class="content-area" id="content-container">
<!-- 内容将通过JS动态加载 -->
</div>
<!-- 新增页脚 -->
<footer class="custom-footer">
<p>© 2025 后台管理. All rights reserved.</p>
</footer>
</main>
</div>
<!-- 修改密码模态框 -->
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="changePasswordModalLabel">修改密码</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="changePasswordForm">
<div class="mb-3">
<label for="oldPassword" class="form-label">原始密码</label>
<input type="password" class="form-control" id="oldPassword" required>
</div>
<div class="mb-3">
<label for="newPassword" class="form-label">新密码</label>
<input type="password" class="form-control" id="newPassword" required>
</div>
<div class="mb-3">
<label for="confirmPassword" class="form-label">确认密码</label>
<input type="password" class="form-control" id="confirmPassword" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="submitPasswordChange">提交</button>
</div>
</div>
</div>
</div>
<!-- 消息弹框(重写alert) -->
<div class="modal fade" id="infoModal" tabindex="-1" aria-labelledby="infoModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="alert alert-primary" role="alert">
A simple primary alert—check it out!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</div>
</div>
<!-- jQuery 3.6.0 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Bootstrap 5.3.0 Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="script.js"></script>
</body>
</html>
5、script.js
document.addEventListener('DOMContentLoaded', function () { // 页面加载完成后执行
const menuToggle = document.getElementById('menu-toggle'); // 隐藏菜单栏的图标
const sidebar = document.querySelector('.sidebar'); // 菜单栏
const tagTabs = document.getElementById('tag-tabs'); // 标签栏
const contentContainer = document.getElementById('content-container'); // 内容容器
const tagArrowPrev = document.getElementById('tag-arrow-prev'); // 标签栏左箭头
const tagArrowNext = document.getElementById('tag-arrow-next'); // 标签栏右箭头
const userDropdownTrigger = document.getElementById('user-dropdown-trigger'); // 用户下拉菜单触发器
const userDropdownMenu = document.getElementById('user-dropdown-menu'); // 用户下拉菜单
const changePasswordLink = document.querySelector('#user-dropdown-menu a[href="#"]:nth-child(1)'); // 修改密码链接
const changePasswordModalElement = document.getElementById('changePasswordModal'); // 修改密码模态框
const changePasswordModal = new bootstrap.Modal(changePasswordModalElement); // 修改密码模态框实例
const submitButton = document.getElementById('submitPasswordChange'); // 密码修改 提交按钮
const primaryNavList = document.querySelector('.primary-nav-list'); // 顶部一级菜单
const sidebarNav = document.querySelector('.sidebar .nav'); // 侧边菜单栏的nav
// 菜单权限配置(如果是Django项目,下面菜单里的url应该是类似于"/menu/"这种)
const MENU_PERMISSIONS = {
"系统管理": {
"url": "#",
"icon": "fa fa-folder",
"target": "expand",
"is_menu": "1",
"children": {
"系统信息管理": {
"url": "#",
"icon": "fa fa-desktop",
"target": "expand",
"is_menu": "1",
"children": {
"菜单管理": {
"url": "/pages/menu.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
},
"字典管理": {
"url": "/pages/dictionary.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
},
"用户管理": {
"url": "/pages/users.html",
"icon": "fa fa-sitemap",
"target": "iframe",
"is_menu": "1"
}
}
}
}
}
};
// 重写 alert 方法
window.alert = function (message) {
const infoModal = document.getElementById('infoModal');
const alertElement = infoModal.querySelector('.alert');
const hideTimeout = message.includes("错误") || message.includes("失败") || message.includes("异常") ||
message.includes("fail") || message.includes("error") || message.includes("exception")
? 3000 : 2000;
// 先移除之前可能添加的类
alertElement.classList.remove('alert-danger', 'alert-success', 'alert-primary');
if (message.includes("错误") || message.includes("失败") || message.includes("异常") ||
message.includes("fail") || message.includes("error") || message.includes("exception")) {
alertElement.classList.add('alert-danger');
} else {
alertElement.classList.add('alert-success');
}
// 设置弹窗内容
alertElement.textContent = message;
// 显示模态框
const infoModalInstance = new bootstrap.Modal(infoModal);
infoModalInstance.show();
// 自动隐藏模态框
setTimeout(() => {
infoModalInstance.hide();
}, hideTimeout);
};
// 1、生成顶部一级菜单
function generatePrimaryMenu() {
primaryNavList.innerHTML = '';
for (const menuName in MENU_PERMISSIONS) {
if (MENU_PERMISSIONS.hasOwnProperty(menuName)) {
const listItem = document.createElement('li');
listItem.className = 'nav-item';
const link = document.createElement('a');
link.className = 'nav-link';
link.href = '#';
link.textContent = menuName;
// 为每个一级菜单添加点击事件(点击的时候生成菜单栏)
link.addEventListener('click', function (e) {
e.preventDefault();
// 生成对应子菜单
generateSidebarMenu(MENU_PERMISSIONS[menuName].children);
});
listItem.appendChild(link);
primaryNavList.appendChild(listItem);
}
}
// 初始选中第一个一级菜单并生成对应子菜单
if (primaryNavList.firstElementChild) {
primaryNavList.firstElementChild.querySelector('.nav-link').click();
}
}
// 2、生成侧边菜单栏
function generateSidebarMenu(menuItems, parentElement = sidebarNav) {
// 清空父元素内容
parentElement.innerHTML = '';
for (const menuName in menuItems) {
if (menuItems.hasOwnProperty(menuName)) {
const menuItem = menuItems[menuName];
const listItem = document.createElement('li');
listItem.className = 'nav-item';
const link = document.createElement('a');
link.className = 'nav-link';
link.innerHTML = `<i class="${menuItem.icon} me-2"></i>${menuName}`;
if (menuItem.target === 'expand') {
// 生成箭头图标,默认向左箭头,追加在link的后面
const arrowIcon = document.createElement('i');
arrowIcon.className = 'fas fa-angle-left ms-auto';
link.appendChild(arrowIcon);
link.href = '#';
link.addEventListener('click', function (e) { // 点击事件,展开和折叠
e.preventDefault();
const subMenu = this.nextElementSibling; // 获取下一个兄弟元素,即子菜单
if (subMenu) {
subMenu.classList.toggle('d-none');
// 切换箭头方向
arrowIcon.classList.toggle('fa-angle-left');
arrowIcon.classList.toggle('fa-angle-down');
}
this.classList.toggle('active');
});
listItem.appendChild(link);
// 生成子菜单
const subMenu = document.createElement('ul');
subMenu.className = 'nav flex-column d-none';
generateSidebarMenu(menuItem.children, subMenu);
listItem.appendChild(subMenu);
} else if (menuItem.target === 'iframe') {
// 添加占位图标以保持对齐
const placeholderIcon = document.createElement('i');
placeholderIcon.className = 'fas fa-angle-left ms-auto opacity-0'; // 透明图标
link.appendChild(placeholderIcon);
link.href = '#';
link.setAttribute('data-url', menuItem.url);
link.addEventListener('click', function (e) {
e.preventDefault();
const pagePath = this.getAttribute('data-url'); // 获取页面路径
const pageName = this.textContent.trim(); // 获取页面名称
handleTabClick(pagePath, pageName);
// 移除其他侧边栏菜单项的 active 类
document.querySelectorAll('.sidebar .nav-link').forEach(item => {
if (item !== this) {
item.classList.remove('active');
}
});
this.classList.add('active');
});
listItem.appendChild(link);
}
parentElement.appendChild(listItem);
}
}
}
// 3、菜单栏点击事件(创建标签,传入一个“是否允许关闭”参数,默认是允许的true)
function handleTabClick(pagePath, pageName, allowClose = true) {
// 判断是否已经存在该标签页,如果存在则激活并加载内容
const existingTab = document.querySelector(`#tag-tabs .nav-link[data-url="${pagePath}"]`);
if (existingTab) {
document.querySelectorAll('.nav-link').forEach(tab => tab.classList.remove('active'));
existingTab.classList.add('active');
const iframe = contentContainer.querySelector(`iframe[src="${pagePath}"]`);
if (iframe) {
// 隐藏所有 iframe
contentContainer.querySelectorAll('.iframe-content').forEach(iframe => {
iframe.style.display = 'none';
});
// 显示当前选中的 iframe
iframe.style.display = 'block';
}
existingTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'end' });
return;
}
// 创建新标签页(不存在)
const newTab = document.createElement('li');
newTab.className = 'nav-item';
if (allowClose) { // 允许关闭的话,添加关闭按钮
newTab.innerHTML = `<a class="nav-link active" data-url="${pagePath}" href="#">
${pageName}
<button type="button" class="btn-close btn-close-sm" aria-label="Close"></button>
</a>`;
} else {
newTab.innerHTML = `<a class="nav-link active" data-url="${pagePath}" href="#">
${pageName}
</a>` ;
}
document.querySelectorAll('.nav-link').forEach(tab => tab.classList.remove('active')); // 移除其他标签页的 active 类
tagTabs.appendChild(newTab); // 添加新标签页到标签栏
loadPageContent(pagePath, pageName); // 1、加载页面内容
newTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'end' }); // 滚动到新标签页
setupTabEvents(newTab); // 2、为新标签页设置事件
}
// 4、加载iframe页面内容的函数
async function loadPageContent(pagePath, pageName) {
let iframe = contentContainer.querySelector(`iframe[src = "${pagePath}"]`);
try {
// 先使用 fetch 检查状态码
const response = await fetch(pagePath, { method: 'HEAD' });
if (!response.ok) {
const statusCode = response.status;
let errorMessage;
switch (statusCode) {
case 401:
errorMessage = '错误:会话失效,请重新登录!';
alert(errorMessage);
break;
case 403:
errorMessage = '错误:您没有权限访问该页面。';
break;
case 404:
errorMessage = '错误:页面未找到。';
break;
case 500:
errorMessage = '错误:服务器内部错误,请稍后再试。';
break;
default:
errorMessage = `错误:加载页面失败,错误码:${statusCode} `;
}
alert(errorMessage);
}
// 如果 iframe 不存在则创建新的
if (!iframe) {
// 创建 iframe 元素
iframe = document.createElement('iframe');
iframe.className = 'iframe-content';
iframe.src = pagePath;
// iframe.name = pagePath;
iframe.title = pageName;
iframe.style.display = 'none'; // 初始隐藏
// 宽度100%,高度100%
iframe.style.width = '100%';
iframe.style.height = '100%';
// 监听 iframe 的 load 事件
iframe.addEventListener('load', () => {
console.log('页面加载成功:', pagePath);
});
// 监听 iframe 的 error 事件
iframe.addEventListener('error', () => {
console.error('错误:加载页面时出错:', pagePath);
// 显示错误信息
contentContainer.innerHTML = `< div class="alert alert-danger" > 错误:加载页面失败:${pagePath}</div > `;
});
contentContainer.appendChild(iframe);
}
// 隐藏所有其他 iframe,然后显示当前iframe
contentContainer.querySelectorAll('.iframe-content').forEach(iframe => {
iframe.style.display = 'none';
});
iframe.style.display = 'block';
} catch (error) {
console.error('请求页面时出错:', error);
contentContainer.innerHTML = `< div class="alert alert-danger" > 错误:请求页面时出错,请检查网络连接。</div > `;
}
}
// 5、标签点击事件、标签关闭事件
function setupTabEvents(tabElement) {
const tabLink = tabElement.querySelector('.nav-link');
const closeButton = tabElement.querySelector('.btn-close'); // 查找当前标签的关闭按钮
// 标签点击事件
tabLink.addEventListener('click', function (e) {
e.preventDefault();
document.querySelectorAll('.nav-link').forEach(tab => tab.classList.remove('active'));
this.classList.add('active');
const pagePath = this.getAttribute('data-url');
const iframe = contentContainer.querySelector(`iframe[src = "${pagePath}"]`);
if (iframe) {
// 隐藏所有 iframe
contentContainer.querySelectorAll('.iframe-content').forEach(iframe => {
iframe.style.display = 'none';
});
// 显示当前选中的 iframe
iframe.style.display = 'block';
}
this.closest('.nav-item').scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'end' });
});
// 标签关闭事件(首页没有关闭标签)
if (closeButton) {
closeButton.addEventListener('click', function (e) {
e.stopPropagation();
const tabElement = this.closest('.nav-item');
const isActive = tabLink.classList.contains('active');
const pagePath = tabLink.getAttribute('data-url');
const iframeToRemove = contentContainer.querySelector(`iframe[src = "${pagePath}"]`);
if (iframeToRemove) {
iframeToRemove.remove();
}
tabElement.remove();
if (isActive && tagTabs.children.length > 0) {
const lastTab = tagTabs.lastElementChild.querySelector('.nav-link');
lastTab.classList.add('active');
const lastPagePath = lastTab.getAttribute('data-url');
const lastIframe = contentContainer.querySelector(`iframe[src = "${lastPagePath}"]`);
if (lastIframe) {
// 隐藏所有 iframe
contentContainer.querySelectorAll('.iframe-content').forEach(iframe => {
iframe.style.display = 'none';
});
// 显示最后一个标签页对应的 iframe
lastIframe.style.display = 'block';
}
lastTab.closest('.nav-item').scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'end' });
} else if (tagTabs.children.length === 0) {
contentContainer.innerHTML = '<div class="alert alert-info">请选择左侧菜单打开页面</div>';
}
});
}
}
// 侧边栏折叠功能
menuToggle.addEventListener('click', function () {
sidebar.classList.toggle('collapsed');
});
// 标签行,左箭头点击事件
tagArrowPrev.addEventListener('click', function () {
const tabWidth = tagTabs.clientWidth;
const scrollLeft = tagTabs.scrollLeft;
const newScrollLeft = Math.max(0, scrollLeft - tabWidth);
tagTabs.scrollTo({
left: newScrollLeft,
behavior: 'smooth'
});
});
// 标签行,右箭头点击事件
tagArrowNext.addEventListener('click', function () {
const tabWidth = tagTabs.clientWidth;
const scrollLeft = tagTabs.scrollLeft;
const scrollWidth = tagTabs.scrollWidth;
const newScrollLeft = Math.min(scrollWidth - tabWidth, scrollLeft + tabWidth);
tagTabs.scrollTo({
left: newScrollLeft,
behavior: 'smooth'
});
});
// 用户下拉菜单点击事件
userDropdownTrigger.addEventListener('click', function (e) {
e.stopPropagation();
userDropdownMenu.classList.toggle('show');
});
// 点击页面其他地方隐藏菜单,
document.addEventListener('click', function (e) {
if (!userDropdownTrigger.contains(e.target) && !userDropdownMenu.contains(e.target)) {
userDropdownMenu.classList.remove('show');
}
});
// 修改密码链接点击事件
changePasswordLink.addEventListener('click', function (e) {
e.preventDefault();
changePasswordModal.show();
});
// 修改密码提交
submitButton.addEventListener('click', function () {
const oldPassword = document.getElementById('oldPassword').value;
const newPassword = document.getElementById('newPassword').value;
const confirmPassword = document.getElementById('confirmPassword').value;
// 旧密码不能为空
if (oldPassword.trim() === '') {
alert('错误:旧密码不能为空,请输入旧密码。');
return;
}
// 验证新密码和确认密码一致
if (newPassword !== confirmPassword) {
alert('错误:新密码和确认密码不一致,请重新输入。');
return;
}
// 新密码和旧密码不能一致
if (newPassword === oldPassword) {
alert('错误:新密码和旧密码不能一致,请重新输入。');
return;
}
// 可以增加实际的密码修改逻辑,这里只是模拟提交
changePasswordModal.hide(); // 关闭模态框
});
// 加载首页内容
handleTabClick('/pages/about.html', '首页', false);
// 生成一级菜单
generatePrimaryMenu();
});
6、style.css
body {
height: 100vh;
overflow: hidden;
}
/* 左侧滚动条 */
.sidebar {
width: 250px;
background-color: #2d3436;
color: white;
height: 100vh;
/* padding-top: 20px; */
position: fixed;
overflow-y: auto;
/* 滚动条隐藏 */
scrollbar-width: none;
transition: width 0.3s ease;
/* padding-top: 60px; */
/* border-top: 2px solid white; */
}
.sidebar .sidebar-header {
height: 60px;
width: 100%;
margin: 0;
}
/* .sidebar .sidebar-header:hover {
background-color: #337ab7;
} */
.sidebar .position-sticky {
border-top: 1px solid #337ab7;
}
.sidebar.collapsed {
/* 折叠状态 */
width: 0;
overflow-x: hidden;
}
.sidebar.collapsed~.main-content {
margin-left: 0;
}
.sidebar .nav-link {
color: #dfe6e9;
padding: 10px 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
/* 菜单层级缩进 */
.sidebar .nav .nav {
padding-left: 20px;
background-color: #434849;
}
.sidebar .nav .nav .nav {
padding-left: 40px;
background-color: #5a5c5c;
}
.sidebar .nav .nav .nav .nav {
padding-left: 60px;
background-color: #989999;
}
.sidebar .nav-link:hover {
background-color: #636e72;
color: white;
}
.sidebar .nav-link.active {
/* background-color: #636e72; */
color: #61b4fc;
}
/* 右侧内容主区域 */
.main-content {
transition: margin-left 0.3s ease;
/* 平滑过渡 */
margin: 0;
margin-left: 250px;
padding: 0;
height: 100vh;
overflow-y: auto;
}
/* system-header 系统信息 */
.system-header {
height: 60px;
padding-left: 15px;
margin: 0;
background-color: #337ab7;
color: white;
display: flex;
align-items: center;
justify-content: space-between;
/* 让左侧内容和右侧内容分居两端 */
border-bottom: none;
/* 取消下边框线 */
}
.header-left {
display: flex;
align-items: center;
gap: 15px;
/* 设置左侧元素之间的间距 */
}
.header-right {
display: flex;
align-items: center;
gap: 15px;
/* 设置右侧元素之间的间距 */
padding-right: 15px;
}
/* 调整搜索框样式 */
.header-right .search-box {
width: 150px;
/* 适当减小搜索框宽度 */
}
.header-right .search-box input {
padding: 0.3em 0.6em;
/* 减小输入框内边距 */
font-size: 1em;
/* 基于父元素的字号 */
}
.header-right .search-icon {
font-size: 1em;
/* 调整放大镜图标字号 */
}
/* 调整图标样式 */
.header-right .header-icon {
font-size: 1.2em;
/* 调整消息图标和用户图标的字号 */
}
/* 调整用户信息文本字号 */
.header-right .user-info {
font-size: 1em;
/* 调整用户信息文本字号 */
}
/* 调整下拉箭头按钮样式 */
.header-right .dropdown-toggle {
font-size: 1em;
/* 调整下拉箭头按钮字号 */
}
/* 调整下拉菜单项字号 */
.header-right .dropdown-menu .dropdown-item {
font-size: 1em;
/* 调整下拉菜单项字号 */
}
.search-box {
position: relative;
width: 200px;
/* 设置搜索框宽度 */
}
.search-box input {
padding-right: 30px;
/* 为放大镜图标留出空间 */
}
.search-icon {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
color: #666;
}
.header-icon {
font-size: 20px;
cursor: pointer;
transition: color 0.3s;
}
.header-icon:hover {
color: #e0e0e0;
/* 鼠标悬停时改变图标颜色 */
}
.user-info {
font-size: 14px;
}
.dropdown {
margin-top: 40px;
}
.dropdown-toggle {
background: none;
border: none;
color: white;
padding: 0;
}
.dropdown-menu {
min-width: 150px;
}
/* system-header里的i标签样式 */
.system-header i {
cursor: pointer;
}
.system-title {
font-size: 24px;
line-height: 60px;
margin: 0;
text-shadow: 3px 3px 7px #000;
/* 水平偏移、垂直偏移、模糊半径、颜色 */
}
/* tag-header */
.tag-header {
border-bottom: 2px solid #2d3436;
display: flex;
/* 使用 Flexbox 布局 */
align-items: center;
/* 垂直居中 */
position: relative;
/* 相对定位 */
height: 40px;
}
/* 标签页左右箭头样式 */
.tag-header .tag-arrow {
padding: 0 10px;
cursor: pointer;
color: #a6abad;
border: 1px solid #a6abad;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
/* 标签页左右箭头鼠标悬浮样式 */
.tag-header .tag-arrow:hover {
color: #000;
}
.tag-header .nav-tabs {
flex: 1;
/* 允许标签项自动扩展 */
min-width: calc(100% - 80px);
/* 减去左右边距 */
overflow-x: auto;
/* 允许水平滚动 */
scrollbar-width: none;
/* 隐藏滚动条 */
white-space: nowrap;
/* 防止标签项换行 */
/* 标签容器禁止换行 */
scroll-behavior: smooth;
/* 平滑滚动效果 */
flex-wrap: nowrap;
/* 标签项保持行内布局 */
/* 标签项保持行内布局 */
/* 左右边距 */
padding: 0;
}
/* 标签项保持行内布局 */
.tag-header .nav-tabs .nav-link {
display: inline-block;
}
/* 标签页中的关闭按钮样式 */
.tag-header .btn-close {
font-size: 9px;
}
/* 去掉标签页的圆角 */
.tag-header .nav-link {
border-radius: 0;
color: #646363;
}
.tag-header .nav-item {
padding: 0;
margin: 0;
}
/* 活跃的标签页样式 */
.tag-header .nav-link.active {
background-color: #2d3436;
/* border-radius: 0; */
border: 1px solid #2d3436;
color: white;
}
/* 标签页的边框清空 */
.tag-header ul,
.tag-header li {
border: 0;
}
.tag-header .nav-link:hover {
/* background-color: #e8edee; */
color: #0a58ca;
}
.tag-header .nav-link.active .btn-close {
filter: invert(1) !important;
opacity: 1 !important;
}
.content-area {
padding: 15px;
width: 100%;
height: calc(100% - 145px);
}
/* 调整侧边栏导航链接字号 */
.sidebar .nav-link {
font-size: 14px;
}
/* 调整标签页导航链接字号 */
.tag-header .nav-tabs .nav-link {
font-size: 14px;
}
.user-dropdown-trigger {
display: flex;
align-items: center;
cursor: pointer;
gap: 5px;
}
.dropdown-menu {
position: absolute;
top: 100%;
right: 0;
display: none;
}
.dropdown-menu.show {
display: block;
}
/* 调整一级菜单导航容器 */
.primary-nav {
display: flex;
align-items: center;
}
/* 调整一级菜单导航列表 */
.primary-nav-list {
flex-direction: row !important;
}
/* 调整一级菜单导航链接 */
.primary-nav-list .nav-link {
color: white;
font-size: 14px;
}
.primary-nav-list .nav-link:hover {
color: #dfe6e9;
/* 鼠标悬停时颜色变化 */
}
.custom-footer {
height: 40px;
/* 设置页脚宽度为 40px */
margin: 0 auto;
/* 水平居中 */
text-align: center;
/* 文字居中 */
padding: 10px 0;
/* 上下内边距 */
border-top: 1px solid #ccc;
/* 添加顶部边框 */
background-color: #f7f7f7;
}
7、package.json
{
"name": "admin-dashboard",
"version": "1.0.0",
"description": "后台管理系统",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"bootstrap": "^5.3.0",
"jquery": "^3.6.0"
},
"devDependencies": {
"vite": "^4.4.0"
}
}