1.登录界面 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body{
background-color: #e9ecef;
}
main{
background-color:whitesmoke;
width: 25rem;
margin:auto;
/* 水平方向,左右同时占据一半空间;实现水平居中 */
margin-top:20vh;
/* vh:相对整个浏览器网页内容的显示框viewport的宽度和高度 ;100vh 就是 100% 的 viewport高度;它会随着窗口高度的调整,字体大小跟着变化 */
text-align: center;
/* 指定文本内容的对齐方式 */
}
</style>
</head>
<body>
<main>
<br>
<div style="display: flex; justify-content: center;">
<img src="/assets/images/logo.jpg" style="border-radius:50%;width:2.5rem;margin-right:1rem">
<!-- main属于block类型元素 ;block元素特征:垂直方向,占据的空间由其内容大小决定 -->
<!-- rem用来修饰 元素的 宽度、高度 ,同样也是相对于 根元素 html 的字体大小 -->
<!-- 相对的是 根元素 html 的字体大小 -->
<!-- margin:盒子模型,外边距,盒子与盒子间的距离 -->
<span style="font-size: 1.8rem">黑羽医疗</span>
</div>
<p>输入用户名、密码登录</p>
<div>
<input type="text" placeholder="用户名">
<!-- 提供可描述输入字段预期值的提示信息 -->
</div>
<br>
<div>
<!-- div 块级元素 ;特点独占一行 -->
<input type="password" placeholder="密码">
</div>
<br>
<div>
<button id="loginButton">登录</button>
</div>
<br>
<div>
<a href="/register.html">没有账号?请先注册</a>
</div>
<br>
</main>
</body>
</html>
登录功能的实现(head内的style上)
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<!-- 事件处理:1.DOM对象的addEventListener方法 2.DOM对象的事件属性指定事件处理函数;事件属性名以on开头后面跟事件名称 -->
<!-- 注意:放head里面的话会导致网页内容还没渲染完就先被执行,DOM里面的内容还没创建都还没有body节点 => 指定一个页面加载事件,等页面加载完之后再执行箭头函数 -->
<script>
// 先选择登录按钮
window.onload =() => {
document.querySelector('#loginButton').onclick = () => {
//1.获取用户名、密码
//alert('执行登录')
//value:input标签属性,对应的是输入框里面的文本
let username = document.querySelector('#username').value
let password = document.querySelector('#password').value
//2.把他们放到HTTP消息里发出去(使用jQuery) , 看请求消息的接口文档
//byhy 88888888
$.post(
'/api/mgr/signin',//请求网址
{
username:username,
password:password,
}
)
//3.当服务端返回ret=0时,跳转到真正的网址 /hyms.html
//jQuery解析响应消息
$.ajax({
url: '/api/mgr/signin',
type: 'POST',
data: 'username=byhy&password=88888888',
// 正确返回;回调函数被传入3个参数:data 从服务端返回的数据 ,textStatus 返回的状态文本描述,xhr XMLHttpRequest的扩展类型jqXHR的对象
success: function(data, textStatus, xhr) {
if(data.ret === 0){
//重定向网址
location.href = 'hyms.html'
}
else{
alert('登陆失败: ' + data.msg)
}
},
//错误
error:function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
}
};
</script>
2.主页各区域样式 hyms.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
grid-template-rows: auto 1fr auto;
/* 右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
align-items: center;
justify-content: center;
}
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
}
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
}
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
padding:1rem;
}
main{
background-color: #d0d0d1;
padding:1rem;
}
.footer-left{
border-left: 1px solid #e5eaef;
}
footer{
background-color: #e5eaef;
text-align: center;
padding:1rem;
}
</style>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li>产品</li>
<li>客户</li>
<li>渠道</li>
<li>订单</li>
<li>统计</li>
</ol>
<ol class="sub-nav-bar" style="margin-left: auto; margin-right: 1rem;">
<li>白月黑羽</li>
</ol>
</nav>
<div class="side-menu">
操作菜单
<pre>
2
2
2
2
2
2
2
</pre>
</div>
<main>正文</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
侧边栏菜单样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
grid-template-rows: auto 1fr auto;
/* 右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
align-items: center;
justify-content: center;
}
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
}
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
}
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
gap:1rem;
}
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
gap: .5rem;
font-size: .85rem;
padding:0 1rem;
}
.side-menu .menu-item{
padding-left: 1rem;
}
/* 交集选择器,是menu-item又是menu-open的 */
.side-menu .menu-item.menu-open{
border-left:1px solid gray;
}
main{
background-color: #d0d0d1;
padding:1rem;
}
.footer-left{
border-left: 1px solid #e5eaef;
}
footer{
background-color: #e5eaef;
text-align: center;
padding:1rem;
}
</style>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li>产品</li>
<li>客户</li>
<li>渠道</li>
<li>订单</li>
<li>统计</li>
</ol>
<ol class="sub-nav-bar" style="margin-left: auto; margin-right: 1rem;">
<li>白月黑羽</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item menu-open">渠道
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item menu-open">订单
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>正文</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
导航栏下拉菜单样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
grid-template-rows: auto 1fr auto;
/* 右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
align-items: center;
justify-content: center;
}
/* 导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
}
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
}
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f ;
/* 整体下移 */
margin-top: 1rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
.dropdown-menu .menu-item{
/* 上下居中 */
margin: .6rem;
}
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
gap:1rem;
}
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
gap: .5rem;
font-size: .85rem;
padding:0 1rem;
}
.side-menu .menu-item{
padding-left: 1rem;
}
/* 交集选择器,是menu-item又是menu-open的 */
.side-menu .menu-item.menu-open{
border-left:1px solid gray;
}
main{
background-color: #d0d0d1;
padding:1rem;
}
.footer-left{
border-left: 1px solid #e5eaef;
}
footer{
background-color: #e5eaef;
text-align: center;
padding:1rem;
}
.sub-nav-bar .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
}
/* 子绝父相 注意这个.sub-nav-bar .menu-item是相对定位;.dropdown-menu是绝对定位*/
/* 绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位 */
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
</style>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item menu-open">渠道
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item menu-open">订单
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>正文</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
菜单项悬停高亮显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
grid-template-rows: auto 1fr auto;
/* 右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
align-items: center;
justify-content: center;
}
/* 导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
}
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
margin: 0;
}
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f ;
/* 整体下移 */
margin-top: .8rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
/* 菜单项 */
/* 后代选择器:选中父元素 后代中 满足条件的元素 ;子代选择器:选择父元素 子代中 满足条件的元素*/
.sub-nav-bar > .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
/* 上下为0,左右为.8rem ;注意:这里我只想设一级的子菜单->用子代选择器*/
padding: .8rem;
}
/* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */
.sub-nav-bar .menu-item:hover{
color:green;
background-color: white;
}
.dropdown-menu .menu-item:hover{
background-color: #e8f5e9;
}
/* 所有菜单项,我希望光标变成手 */
.menu-item{
cursor: pointer;
}
.dropdown-menu .menu-item{
/* 上下居中 margin: .6rem; 换成padding */
/* 背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */
padding: .6rem;
}
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
/* flex布局列间距 */
/* gap:.2rem; */
}
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
/* gap: .5rem; */
font-size: .85rem;
padding:0 1rem;
}
.side-menu .menu-header{
color:#837b70;
}
.side-menu .menu-item{
color: #5e81a5;
/* padding-left: 1rem; */
/* 上 右 下 左 */
padding: .5rem 0 .5rem 1rem;
margin: .2rem 0;
}
.side-menu .menu-item:hover{
background-color: #e8f5e9;
}
.sub-menu .menu-item:hover{
background-color: #bce5bf;
}
/* 交集选择器,是menu-item又是menu-open的 */
.side-menu .menu-item.menu-open{
color:#6b6464;
border-left:1px solid green;
}
main{
background-color: #d0d0d1;
padding:1rem;
}
.footer-left{
border-left: 1px solid #e5eaef;
}
footer{
background-color: #e5eaef;
text-align: center;
padding:1rem;
}
/* 子绝父相 注意这个.sub-nav-bar .menu-item是相对定位;.dropdown-menu是绝对定位*/
/* 绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位 */
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
</style>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item menu-open">渠道
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item menu-open">订单
<ul class="sub-menu">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>正文</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
点击隐藏显示子菜单
点击菜单项实现显示/隐藏
思路:
首先我怎么知道这个菜单被点击了—— 对多个对象注册点击事件;但问题是如果后面产生动态元素,那还要单独对它写注册事件
我们可以对整个页面document注册click事件,然后看消息源是否是导航栏或侧边栏里的菜单项产生的,是的话再对它进行后续的处理。
-------------------------------------------------------------------------------------------------------------------------
元素是否显示,看display属性值是否为none
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
.hidden{
display:none !important;
}
/* 页面整体 */
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
/* 指定行的数量和高度 */
grid-template-rows: auto 1fr auto;
/* 指定列的数量和宽度;右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
/* 一行一列:管理员操作 */
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
/* flex布局,居中 */
align-items: center;
justify-content: center;
}
/* 整个导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
/* 去掉点击后出现的"选中状态"*/
user-select: none;
}
/* 导航栏包含所有菜单项的容器*/
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
margin: 0;
}
/* 导航栏菜单项里的下拉菜单 */
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f;
/* 整体下移 */
margin-top: .8rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
/* 导航栏里的所有单个菜单项 */
/* 后代选择器:选中父元素"后代中"满足条件的元素 ;子代选择器:选择父元素"子代中"满足条件的元素*/
.sub-nav-bar > .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
/* 上下为0,左右为.8rem ;但要注意:这里我只想设一级的子菜单产品那行,需要用子代选择器"->"*/
padding: .8rem;
}
/* 子代采用的是绝对定位,绝对定位相对于非静态定位(static)的父元素进行定位移动;
绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位;
希望子元素相对于父元素进行定位,又不希望父元素脱标 采用子绝父相(注意这个“.sub-nav-bar .menu-item”是相对定位;“.dropdown-menu”是绝对定位)*/
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
/* 悬停高亮 */
/* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */
.sub-nav-bar .menu-item:hover{
color:green;
background-color: white;
}
.dropdown-menu .menu-item:hover{
background-color: #e8f5e9;
}
/* 对于所有菜单项,希望光标变成手*/
.menu-item{
cursor: pointer;
}
/* 下拉菜单的每个菜单项 */
.dropdown-menu .menu-item{
/* 上下居中 margin: .6rem; 换成padding 因为背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */
padding: .6rem;
}
/* 下拉菜单每个菜单项的分界线 */
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
/* 文字不顶左角 */
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
/* gap:.2rem; flex布局列间距 */
user-select: none;
}
/* 侧边栏的下拉菜单 */
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
/* gap: .5rem; */
font-size: .85rem;
padding:0 1rem;
}
/* 左侧菜单 菜单头 */
.side-menu .menu-header{
color:#837b70;
}
/* 左侧菜单 菜单项 */
.side-menu .menu-item{
color: #5e81a5;
/* padding-left: 1rem; */
/* 上 右 下 左 */
padding: .5rem 0 .5rem 1rem;
/* 上下.2rem 左右无 */
margin: .2rem 0;
}
/* 悬停高亮 */
.side-menu .menu-item:hover{
background-color: #e8f5e9;
}
.sub-menu .menu-item:hover{
background-color: #bce5bf;
}
/* 侧边栏展开的菜单项 */
/* .menu-item.has-sub-menu交集选择器,是menu-item又是has-sub-menu的 */
.side-menu .menu-item.has-sub-menu{
color:#6b6464;
border-left:1px solid green;
}
/* 界面主体元素 */
main{
background-color: #d0d0d1;
/* 防止文字顶左角 */
padding:1rem;
}
/* 第三行一列;页脚左侧容器 */
.footer-left{
border-left: 1px solid #e5eaef;
}
/* 页脚元素 */
footer{
background-color: #e5eaef;
text-align: center;
padding:1rem;
}
</style>
<script>
window.onload = function(){
document.addEventListener('click',function(e){
//思路:首先我们先判断直接触发事件的对象(e.target)是否为导航栏“带有下拉菜单”的菜单项,怎么判断呢?—— 看这个元素对象里的class属性是否包含hidden
//对于这个触发对象有个问题:如果点的是li标签,可以判断class属性是否有hidden;但如果点的是span标签,也就是产品,他没有class属性,点了也没用不显示,如何解决这个问题呢?—— 我们可以采用closest()方法获取符合条件的最接近的上级元素(包括自身),那么这样无论点里点外都能追溯到<li class="menu-item">这个元素, 如果没有匹配的元素返回的就是null
//导航栏菜单点击处理
let NavMenuItem = e.target.closest('.sub-nav-bar > .menu-item')
//点击的是导航栏菜单项
if (NavMenuItem){
//<li class="menu-item">里面有hidden把hidden去掉;没有加上
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = NavMenuItem.querySelector('.dropdown-menu')
//如果有下拉子菜单
if(subMenu){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
//侧边栏菜单点击处理
let sideMenuItem = e.target.closest('.side-menu > .menu-item')
//这里有个问题:点导航栏的下拉菜单我们可以接受点击子菜单然后缩起来;但对于侧边栏我们并不希望这样(子菜单往上找也会追溯到<li class="menu-item">)—— 那么我们需要加一个判断条件:如果当前点击的这个元素祖先中有sub-menu就不执行下面内容
//点击的是侧边栏菜单项,并且不是点击子菜单
if (sideMenuItem){
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = sideMenuItem.querySelector('.sub-menu')
//如果有下拉子菜单
if(subMenu && !e.target.closest('.sub-menu')){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
})
}
</script>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item has-sub-menu">渠道
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item has-sub-menu">订单
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>正文</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
列出系统中的客户
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<style>
.hidden{
display:none !important;
}
/* 页面整体 */
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
/* 指定行的数量和高度 */
grid-template-rows: auto 1fr auto;
/* 指定列的数量和宽度;右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
/* 一行一列:管理员操作 */
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
/* flex布局,居中 */
align-items: center;
justify-content: center;
}
/* 整个导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
/* 去掉点击后出现的"选中状态"*/
user-select: none;
}
/* 导航栏包含所有菜单项的容器*/
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
margin: 0;
}
/* 导航栏菜单项里的下拉菜单 */
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f;
/* 整体下移 */
margin-top: .8rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
/* 导航栏里的所有单个菜单项 */
/* 后代选择器:选中父元素"后代中"满足条件的元素 ;子代选择器:选择父元素"子代中"满足条件的元素*/
.sub-nav-bar > .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
/* 上下为0,左右为.8rem ;但要注意:这里我只想设一级的子菜单产品那行,需要用子代选择器"->"*/
padding: .8rem;
}
/* 子代采用的是绝对定位,绝对定位相对于非静态定位(static)的父元素进行定位移动;
绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位;
希望子元素相对于父元素进行定位,又不希望父元素脱标 采用子绝父相(注意这个“.sub-nav-bar .menu-item”是相对定位;“.dropdown-menu”是绝对定位)*/
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
/* 悬停高亮 */
/* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */
.sub-nav-bar .menu-item:hover{
color:green;
background-color: white;
}
.dropdown-menu .menu-item:hover{
background-color: #e8f5e9;
}
/* 对于所有菜单项,希望光标变成手*/
.menu-item{
cursor: pointer;
}
/* 下拉菜单的每个菜单项 */
.dropdown-menu .menu-item{
/* 上下居中 margin: .6rem; 换成padding 因为背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */
padding: .6rem;
}
/* 下拉菜单每个菜单项的分界线 */
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
/* 文字不顶左角 */
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
/* gap:.2rem; flex布局列间距 */
user-select: none;
}
/* 侧边栏的下拉菜单 */
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
/* gap: .5rem; */
font-size: .85rem;
padding:0 1rem;
}
/* 左侧菜单 菜单头 */
.side-menu .menu-header{
color:#837b70;
}
/* 左侧菜单 菜单项 */
.side-menu .menu-item{
color: #5e81a5;
/* padding-left: 1rem; */
/* 上 右 下 左 */
padding: .5rem 0 .5rem 1rem;
/* 上下.2rem 左右无 */
margin: .2rem 0;
}
/* 悬停高亮 */
.side-menu .menu-item:hover{
background-color: #e8f5e9;
}
.sub-menu .menu-item:hover{
background-color: #bce5bf;
}
/* 侧边栏展开的菜单项 */
/* .menu-item.has-sub-menu交集选择器,是menu-item又是has-sub-menu的 */
.side-menu .menu-item.has-sub-menu{
color:#6b6464;
border-left:1px solid green;
}
/* 界面主体元素 */
main{
background-color: #fafafa;
/* 防止文字顶左角 */
padding:1rem;
}
/* 第三行一列;页脚左侧容器 */
.footer-left{
border-left: 1px solid #e5eaef;
}
/* 页脚元素 */
footer{
background-color: #e6e6e6;
text-align: center;
padding:1rem;
}
/* 正文 */
.result-list{
display:flex;
flex-direction: column;
gap:1rem;
/* 主轴对齐 */
justify-content: center;
/* 从轴对齐 */
align-items: center;
}
.result-list-item{
border:1px solid rgb(170, 177, 170);
padding: 0 1rem;
width: 90%;
}
.field-name{
width: 5rem;
/* 由于它是个<span>标签,行内元素,宽高不生效;把它转成行内块元素“一行显示多个,宽高生效” */
display: inline-block;
color: darkgreen;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<script>
//注册初始事件处理
function registerEventListeners(){
document.addEventListener('click',function(e){
//思路:首先我们先判断直接触发事件的对象(e.target)是否为导航栏“带有下拉菜单”的菜单项,怎么判断呢?—— 看这个元素对象里的class属性是否包含hidden
//对于这个触发对象有个问题:如果点的是li标签,可以判断class属性是否有hidden;但如果点的是span标签,也就是产品,他没有class属性,点了也没用不显示,如何解决这个问题呢?—— 我们可以采用closest()方法获取符合条件的最接近的上级元素(包括自身),那么这样无论点里点外都能追溯到<li class="menu-item">这个元素, 如果没有匹配的元素返回的就是null
//导航栏菜单点击处理
let NavMenuItem = e.target.closest('.sub-nav-bar > .menu-item')
//点击的是导航栏菜单项
if (NavMenuItem){
//<li class="menu-item">里面有hidden把hidden去掉;没有加上
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = NavMenuItem.querySelector('.dropdown-menu')
//如果有下拉子菜单
if(subMenu){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
//侧边栏菜单点击处理
let sideMenuItem = e.target.closest('.side-menu > .menu-item')
//这里有个问题:点导航栏的下拉菜单我们可以接受点击子菜单然后缩起来;但对于侧边栏我们并不希望这样(子菜单往上找也会追溯到<li class="menu-item">)—— 那么我们需要加一个判断条件:如果当前点击的这个元素祖先中有sub-menu就不执行下面内容
//点击的是侧边栏菜单项,并且不是点击子菜单
if (sideMenuItem){
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = sideMenuItem.querySelector('.sub-menu')
//如果有下拉子菜单
if(subMenu && !e.target.closest('.sub-menu')){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
})
}
//看接口文档,列出所有客户 请求参数http请求消息url中需要携带的参数4个
function getCustomerList(pagenum=1,pagesize=5,keywords=''){
//在发出请求之前,先把结果清空(点击下一页)
document.querySelector('.result-list').innerHTML=''
//获取响应内容
$.ajax({
type: 'GET',
// http协议中,url参数格式都是urlencode格式
url: `/api/mgr/customers?action=list_customer&pagenum=${pagenum}&pagesize=${pagesize}&keywords=${keywords}`,
//jQuery解析响应消息体
success: function(data, textStatus, xhr) {
if(data.ret !== 0){
alert('操作失败: ' + data.msg)
return;
}
for(let item of data.retlist){
// 每一项 ,加<p>是为了换行,让它独占一行 ; 前面加一个说明,还要在一行显示,用<span>;还需要指定样式,加个class
let pEle = `<div class='result-list-item'>
<p><span class='field-name'>客户名</span><span>${item.name}</span></p>
<p><span class='field-name'>地址</span><span>${item.address}</span></p>
<p><span class='field-name'>电话</span><span>${item.phonenumber}</span></p></div>`
document.querySelector('.result-list').insertAdjacentHTML("beforeend",pEle)
}
},
//错误
error:function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
}
window.onload = function(){
registerEventListeners();
getCustomerList();//获取客户列表
}
</script>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item has-sub-menu">渠道
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item has-sub-menu">订单
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>
<!-- 正文 -->
<div class="result-list"></div>
</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
分隔代码:
hyms.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>药品销管</title> <!-- 外联式 --> <link rel="stylesheet" href="endhyms.css"> <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script> <script src="endhyms.js"></script> </head> <body> <div class="nav-logo">管理员操作</div> <nav> <ol class="sub-nav-bar"> <li class="menu-item"> <!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 --> <span>产品</span> <ul class="dropdown-menu hidden"> <li class="menu-item">子菜单1</li> <div class="dropdown-divider"></div> <li class="menu-item">子菜单2</li> </ul> </li> <li class="menu-item"><span>客户</span></li> <li class="menu-item"><span>渠道</span></li> <li class="menu-item"><span>订单</span></li> <li class="menu-item"><span>统计</span></li> </ol> <ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;"> <li class="menu-item"> <span>白月黑羽</span> <ul class="dropdown-menu hidden"> <li class="menu-item">子菜单1</li> <div class="dropdown-divider"></div> <li class="menu-item">子菜单2</li> <div class="dropdown-divider"></div> <li class="menu-item">子菜单3</li> </ul> </li> </ol> </nav> <ul class="side-menu"> <!-- 菜单头部 --> <li class="menu-header">操作菜单</li> <li class="menu-item">产品</li> <li class="menu-item">客户</li> <li class="menu-item has-sub-menu">渠道 <ul class="sub-menu hidden"> <li class="menu-item">子菜单1</li> <li class="menu-item">子菜单2</li> </ul> </li> <li class="menu-item has-sub-menu">订单 <ul class="sub-menu hidden"> <li class="menu-item">子菜单1</li> <li class="menu-item">子菜单2</li> </ul> </li> <li class="menu-item">统计</li> </ul> <main> <!-- 正文 --> <div class="result-list"></div> </main> <div class="footer-left"></div> <footer> 白月黑羽版权所有 <br> <!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子--> <small>2020-2022 @copy rights reserved</small> </footer> </body> </html>
hyms.css
.hidden{ display:none !important; } /* 页面整体 */ body{ height: 100vh; max-width: 1250px; /* 上下设成0;左右均分 */ margin: 0 auto; display: grid; /* 指定行的数量和高度 */ grid-template-rows: auto 1fr auto; /* 指定列的数量和宽度;右边占据所有剩余宽度 */ grid-template-columns: minmax(15rem,20rem) 1fr; } /* 一行一列:管理员操作 */ .nav-logo{ border-left: 1px solid #e5eaef; color:rgb(8, 96, 8); display:flex; /* flex布局,居中 */ align-items: center; justify-content: center; } /* 整个导航栏 */ nav{ background-color: rgb(4, 115, 155); color: white; display: flex; flex-flow: row wrap; /* 保证不会挤到一起去,再小出现滚动条 */ min-width: 30rem; /* 去掉点击后出现的"选中状态"*/ user-select: none; } /* 导航栏包含所有菜单项的容器*/ .sub-nav-bar{ list-style-type: none; display:flex; flex-flow: row wrap; gap:2rem; align-items: center; justify-content: center; margin: 0; } /* 导航栏菜单项里的下拉菜单 */ .dropdown-menu{ position:absolute; list-style-type: none; background-color: white; color: #2e669f; /* 整体下移 */ margin-top: .8rem; font-size: .85rem; padding-left: 0; width:10rem; } /* 导航栏里的所有单个菜单项 */ /* 后代选择器:选中父元素"后代中"满足条件的元素 ;子代选择器:选择父元素"子代中"满足条件的元素*/ .sub-nav-bar > .menu-item{ /* 相对于该元素在文档流中的正常位置进行偏移定位 */ position: relative; /* 上下为0,左右为.8rem ;但要注意:这里我只想设一级的子菜单产品那行,需要用子代选择器"->"*/ padding: .8rem; } /* 子代采用的是绝对定位,绝对定位相对于非静态定位(static)的父元素进行定位移动; 绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位; 希望子元素相对于父元素进行定位,又不希望父元素脱标 采用子绝父相(注意这个“.sub-nav-bar .menu-item”是相对定位;“.dropdown-menu”是绝对定位)*/ .sub-nav-bar-right .dropdown-menu{ /* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/ right:0; } /* 悬停高亮 */ /* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */ .sub-nav-bar .menu-item:hover{ color:green; background-color: white; } .dropdown-menu .menu-item:hover{ background-color: #e8f5e9; } /* 对于所有菜单项,希望光标变成手*/ .menu-item{ cursor: pointer; } /* 下拉菜单的每个菜单项 */ .dropdown-menu .menu-item{ /* 上下居中 margin: .6rem; 换成padding 因为背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */ padding: .6rem; } /* 下拉菜单每个菜单项的分界线 */ .dropdown-divider{ height:0; /* 一条边 */ border-top:1px solid #e8dcdc; } /* 侧边栏 */ .side-menu{ border-left: 1px solid #e5eaef; border-top: 1px solid #e5eaef; margin: 0; /* 文字不顶左角 */ padding:1rem; list-style-type: none; /* 根字体的90% */ font-size:.9rem; display:flex; /* 列排 */ flex-direction: column; /* gap:.2rem; flex布局列间距 */ user-select: none; } /* 侧边栏的下拉菜单 */ .sub-menu{ list-style-type: none; display:flex; /* 列排 */ flex-direction: column; /* gap: .5rem; */ font-size: .85rem; padding:0 1rem; } /* 左侧菜单 菜单头 */ .side-menu .menu-header{ color:#837b70; } /* 左侧菜单 菜单项 */ .side-menu .menu-item{ color: #5e81a5; /* padding-left: 1rem; */ /* 上 右 下 左 */ padding: .5rem 0 .5rem 1rem; /* 上下.2rem 左右无 */ margin: .2rem 0; } /* 悬停高亮 */ .side-menu .menu-item:hover{ background-color: #e8f5e9; } .sub-menu .menu-item:hover{ background-color: #bce5bf; } /* 侧边栏展开的菜单项 */ /* .menu-item.has-sub-menu交集选择器,是menu-item又是has-sub-menu的 */ .side-menu .menu-item.has-sub-menu{ color:#6b6464; border-left:1px solid green; } /* 界面主体元素 */ main{ background-color: #fafafa; /* 防止文字顶左角 */ padding:1rem; } /* 第三行一列;页脚左侧容器 */ .footer-left{ border-left: 1px solid #e5eaef; } /* 页脚元素 */ footer{ background-color: #e6e6e6; text-align: center; padding:1rem; } /* 正文 */ .result-list{ display:flex; flex-direction: column; gap:1rem; /* 主轴对齐 */ justify-content: center; /* 从轴对齐 */ align-items: center; } .result-list-item{ border:1px solid rgb(170, 177, 170); padding: 0 1rem; width: 90%; } .field-name{ width: 5rem; /* 由于它是个<span>标签,行内元素,宽高不生效;把它转成行内块元素“一行显示多个,宽高生效” */ display: inline-block; color: darkgreen; }
hyms.js
//注册初始事件处理 function registerEventListeners(){ document.addEventListener('click',function(e){ //思路:首先我们先判断直接触发事件的对象(e.target)是否为导航栏“带有下拉菜单”的菜单项,怎么判断呢?—— 看这个元素对象里的class属性是否包含hidden //对于这个触发对象有个问题:如果点的是li标签,可以判断class属性是否有hidden;但如果点的是span标签,也就是产品,他没有class属性,点了也没用不显示,如何解决这个问题呢?—— 我们可以采用closest()方法获取符合条件的最接近的上级元素(包括自身),那么这样无论点里点外都能追溯到<li class="menu-item">这个元素, 如果没有匹配的元素返回的就是null //导航栏菜单点击处理 let NavMenuItem = e.target.closest('.sub-nav-bar > .menu-item') //点击的是导航栏菜单项 if (NavMenuItem){ //<li class="menu-item">里面有hidden把hidden去掉;没有加上 //有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null let subMenu = NavMenuItem.querySelector('.dropdown-menu') //如果有下拉子菜单 if(subMenu){ if (subMenu.classList.contains('hidden')){ subMenu.classList.remove("hidden"); } else{ subMenu.classList.add("hidden"); } } } //侧边栏菜单点击处理 let sideMenuItem = e.target.closest('.side-menu > .menu-item') //这里有个问题:点导航栏的下拉菜单我们可以接受点击子菜单然后缩起来;但对于侧边栏我们并不希望这样(子菜单往上找也会追溯到<li class="menu-item">)—— 那么我们需要加一个判断条件:如果当前点击的这个元素祖先中有sub-menu就不执行下面内容 //点击的是侧边栏菜单项,并且不是点击子菜单 if (sideMenuItem){ //有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null let subMenu = sideMenuItem.querySelector('.sub-menu') //如果有下拉子菜单 if(subMenu && !e.target.closest('.sub-menu')){ if (subMenu.classList.contains('hidden')){ subMenu.classList.remove("hidden"); } else{ subMenu.classList.add("hidden"); } } } }) } //看接口文档,列出所有客户 请求参数http请求消息url中需要携带的参数4个 function getCustomerList(pagenum=1,pagesize=5,keywords=''){ //在发出请求之前,先把结果清空(点击下一页) document.querySelector('.result-list').innerHTML='' //获取响应内容 $.ajax({ type: 'GET', // http协议中,url参数格式都是urlencode格式 url: `/api/mgr/customers?action=list_customer&pagenum=${pagenum}&pagesize=${pagesize}&keywords=${keywords}`, //jQuery解析响应消息体 success: function(data, textStatus, xhr) { if(data.ret !== 0){ alert('操作失败: ' + data.msg) return; } for(let item of data.retlist){ // 每一项 ,加<p>是为了换行,让它独占一行 ; 前面加一个说明,还要在一行显示,用<span>;还需要指定样式,加个class let pEle = `<div class='result-list-item'> <p><span class='field-name'>客户名</span><span>${item.name}</span></p> <p><span class='field-name'>地址</span><span>${item.address}</span></p> <p><span class='field-name'>电话</span><span>${item.phonenumber}</span></p></div>` document.querySelector('.result-list').insertAdjacentHTML("beforeend",pEle) } }, //错误 error:function (xhr, textStatus, errorThrown ){ console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`) } }) } window.onload = function(){ registerEventListeners(); getCustomerList();//获取客户列表 }
添加客户
hyms.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<!-- 外联式 -->
<link rel="stylesheet" href="endhyms.css">
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<script src="endhyms.js"></script>
</head>
<body>
<div class="nav-logo">管理员操作</div>
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item has-sub-menu">渠道
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item has-sub-menu">订单
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<main>
<!-- 正文 -->
<div class="add-one-area">
<button id='add-one-btn'>添加</button>
<div class="add-one-form hidden">
<p>
<span class='field-name'>客户名</span>
<input type="text" id="customer-name" class="input-l"></input>
</p>
<p>
<span class='field-name'>电话</span>
<input type="text" id="customer-phone" class="input-l"></input>
</p>
<p>
<span class='field-name'>地址</span>
<input type="text" id="customer-addr" class="input-xl"></input>
</p>
<div class="add-one-submit-btn-div">
<button id='add-one-submit-btn'>确定</button>
</div>
</div>
</div>
<div class="result-list"></div>
</main>
<div class="footer-left"></div>
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
hyms.css
.hidden{
display:none !important;
}
/* 页面整体 */
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
/* 指定行的数量和高度 */
grid-template-rows: auto 1fr auto;
/* 指定列的数量和宽度;右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
/* 一行一列:管理员操作 */
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
/* flex布局,居中 */
align-items: center;
justify-content: center;
}
/* 整个导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
/* 去掉点击后出现的"选中状态"*/
user-select: none;
}
/* 导航栏包含所有菜单项的容器*/
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
margin: 0;
}
/* 导航栏菜单项里的下拉菜单 */
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f;
/* 整体下移 */
margin-top: .8rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
/* 导航栏里的所有单个菜单项 */
/* 后代选择器:选中父元素"后代中"满足条件的元素 ;子代选择器:选择父元素"子代中"满足条件的元素*/
.sub-nav-bar > .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
/* 上下为0,左右为.8rem ;但要注意:这里我只想设一级的子菜单产品那行,需要用子代选择器"->"*/
padding: .8rem;
}
/* 子代采用的是绝对定位,绝对定位相对于非静态定位(static)的父元素进行定位移动;
绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位;
希望子元素相对于父元素进行定位,又不希望父元素脱标 采用子绝父相(注意这个“.sub-nav-bar .menu-item”是相对定位;“.dropdown-menu”是绝对定位)*/
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
/* 悬停高亮 */
/* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */
.sub-nav-bar .menu-item:hover{
color:green;
background-color: white;
}
.dropdown-menu .menu-item:hover{
background-color: #e8f5e9;
}
/* 对于所有菜单项,希望光标变成手*/
.menu-item{
cursor: pointer;
}
/* 下拉菜单的每个菜单项 */
.dropdown-menu .menu-item{
/* 上下居中 margin: .6rem; 换成padding 因为背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */
padding: .6rem;
}
/* 下拉菜单每个菜单项的分界线 */
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
/* 文字不顶左角 */
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
/* gap:.2rem; flex布局列间距 */
user-select: none;
}
/* 侧边栏的下拉菜单 */
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
/* gap: .5rem; */
font-size: .85rem;
padding:0 1rem;
}
/* 左侧菜单 菜单头 */
.side-menu .menu-header{
color:#837b70;
}
/* 左侧菜单 菜单项 */
.side-menu .menu-item{
color: #5e81a5;
/* padding-left: 1rem; */
/* 上 右 下 左 */
padding: .5rem 0 .5rem 1rem;
/* 上下.2rem 左右无 */
margin: .2rem 0;
}
/* 悬停高亮 */
.side-menu .menu-item:hover{
background-color: #e8f5e9;
}
.sub-menu .menu-item:hover{
background-color: #bce5bf;
}
/* 侧边栏展开的菜单项 */
/* .menu-item.has-sub-menu交集选择器,是menu-item又是has-sub-menu的 */
.side-menu .menu-item.has-sub-menu{
color:#6b6464;
border-left:1px solid green;
}
/* 界面主体元素 */
main{
background-color: #fafafa;
/* 防止文字顶左角 */
padding:1rem;
}
/* 第三行一列;页脚左侧容器 */
.footer-left{
border-left: 1px solid #e5eaef;
}
/* 添加客户 */
.add-one-area{
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
/* 上 右 下 左 */
margin: 0 0 1rem 0;
}
.input-l{
width: 10rem;
}
.input-xl{
width: 20rem;
}
input{
height:1.3rem;
border:1px solid grey;
}
.add-one-submit-btn-div{
display:flex;
justify-content: center;
align-items: center;
}
/* 正文 */
.result-list{
display:flex;
flex-direction: column;
gap:1rem;
/* 主轴对齐 */
justify-content: center;
/* 从轴对齐 */
align-items: center;
}
.result-list-item{
border:1px solid rgb(170, 177, 170);
padding: 0 1rem;
width: 90%;
}
.field-name{
width: 5rem;
/* 由于它是个<span>标签,行内元素,宽高不生效;把它转成行内块元素“一行显示多个,宽高生效” */
display: inline-block;
color: darkgreen;
}
/* 页脚元素 */
footer{
background-color: #e6e6e6;
text-align: center;
padding:1rem;
}
hyms.js
//注册全局点击事件
function registerGlobalEvents(){
document.addEventListener('click',function(e){
//思路:首先我们先判断直接触发事件的对象(e.target)是否为导航栏“带有下拉菜单”的菜单项,怎么判断呢?—— 看这个元素对象里的class属性是否包含hidden
//对于这个触发对象有个问题:如果点的是li标签,可以判断class属性是否有hidden;但如果点的是span标签,也就是产品,他没有class属性,点了也没用不显示,如何解决这个问题呢?—— 我们可以采用closest()方法获取符合条件的最接近的上级元素(包括自身),那么这样无论点里点外都能追溯到<li class="menu-item">这个元素, 如果没有匹配的元素返回的就是null
//导航栏菜单点击处理
let NavMenuItem = e.target.closest('.sub-nav-bar > .menu-item')
//点击的是导航栏菜单项
if (NavMenuItem){
//<li class="menu-item">里面有hidden把hidden去掉;没有加上
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = NavMenuItem.querySelector('.dropdown-menu')
//如果有下拉子菜单
if(subMenu){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
//侧边栏菜单点击处理
let sideMenuItem = e.target.closest('.side-menu > .menu-item')
//这里有个问题:点导航栏的下拉菜单我们可以接受点击子菜单然后缩起来;但对于侧边栏我们并不希望这样(子菜单往上找也会追溯到<li class="menu-item">)—— 那么我们需要加一个判断条件:如果当前点击的这个元素祖先中有sub-menu就不执行下面内容
//点击的是侧边栏菜单项,并且不是点击子菜单
if (sideMenuItem){
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = sideMenuItem.querySelector('.sub-menu')
//如果有下拉子菜单
if(subMenu && !e.target.closest('.sub-menu')){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
})
}
//添加按钮点击处理
function registerClickAddOne(){
let addOneBtn = document.querySelector('#add-one-btn')
addOneBtn.addEventListener('click',function(){
let addOneForm = document.querySelector('.add-one-form')
if(addOneForm.classList.contains('hidden')){
addOneForm.classList.remove('hidden')
addOneBtn.innerText='隐藏'
}
else{
addOneForm.classList.add('hidden')
addOneBtn.innerText='添加'
}
})
}
//提交按钮点击处理
function registerClickAddOneSubmit(){
//先获取
let addOneSubmitBtn = document.querySelector('#add-one-submit-btn')
//监听
addOneSubmitBtn.addEventListener('click',function(){
//取出数据;获取已有的网页界面上的内容
let customer_name = document.querySelector('#customer-name').value
let customer_phone = document.querySelector('#customer-phone').value
let customer_addr = document.querySelector('#customer-addr').value
//发送到后端
$.ajax({
url: '/api/mgr/customers',
type: 'POST',
//指明消息体为json格式
contentType : 'application/json',
//浏览器js的内置对象JSON的stringify方法,可将js对象转化为JSON格式的字符串(序列化)
data: JSON.stringify({
action:'add_customer',
data:{
name:customer_name,
phonenumber:customer_phone,
address:customer_addr
}
}),
// data: JSON.stringify({
// "action":"add_customer",
// "data":{
// "name":customer_name,
// "phonenumber":customer_phone,
// "address":customer_addr
// }
// }),
// success 接收到响应
success: function(data, textStatus, xhr) {
if(data.ret === 0)
getCustomerList();//重新刷新列表
else
alert('操作失败:'+data.msg)
},
error: function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
})
}
//看接口文档,列出所有客户 请求参数http请求消息url中需要携带的参数4个
function getCustomerList(pagenum=1,pagesize=5,keywords=''){
//在发出请求之前,先把结果清空(点击下一页)
document.querySelector('.result-list').innerHTML=''
//获取响应内容
$.ajax({
type: 'GET',
// http协议中,url参数格式都是urlencode格式
url: `/api/mgr/customers?action=list_customer&pagenum=${pagenum}&pagesize=${pagesize}&keywords=${keywords}`,
//jQuery解析响应消息体
success: function(data, textStatus, xhr) {
if(data.ret !== 0){
alert('操作失败: ' + data.msg)
return;
}
for(let item of data.retlist){
// 每一项 ,加<p>是为了换行,让它独占一行 ; 前面加一个说明,还要在一行显示,用<span>;还需要指定样式,加个class
let pEle = `<div class='result-list-item'>
<p><span class='field-name'>客户名</span><span>${item.name}</span></p>
<p><span class='field-name'>地址</span><span>${item.address}</span></p>
<p><span class='field-name'>电话</span><span>${item.phonenumber}</span></p></div>`
document.querySelector('.result-list').insertAdjacentHTML("beforeend",pEle)
}
},
//错误
error:function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
}
window.onload = function(){
registerGlobalEvents();//全局事件
registerClickAddOne();
registerClickAddOneSubmit();
getCustomerList();//获取客户列表
}
分页
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body{
background-color: #e9ecef;
}
main{
background-color:whitesmoke;
width: 25rem;
margin:auto;
/* 水平方向,左右同时占据一半空间;实现水平居中 */
margin-top:20vh;
/* vh:相对整个浏览器网页内容的显示框viewport的高度 ;100vh 就是 100% 的 viewport高度;它会随着窗口高度的调整,字体大小跟着变化 */
text-align: center;
/* 指定文本内容的对齐方式 */
}
</style>
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<!-- 事件处理:1.DOM对象的addEventListener方法 2.DOM对象的事件属性指定事件处理函数;事件属性名以on开头后面跟事件名称 -->
<!-- 注意:放head里面的话会导致网页内容还没渲染完就先被执行,DOM里面的内容还没创建都还没有body节点 => 指定一个页面加载事件,等页面加载完之后再执行箭头函数 -->
<script>
// 先选择登录按钮
window.onload =() => {
document.querySelector('#loginButton').onclick = () => {
//1.获取用户名、密码
//alert('执行登录')
//value:input标签属性,对应的是输入框里面的文本
let username = document.querySelector('#username').value
let password = document.querySelector('#password').value
//2.把他们放到HTTP消息里发出去(使用jQuery) , 看请求消息的接口文档
//byhy 88888888
$.post(
'/api/mgr/signin',//请求网址
{
username:username,
password:password,
}
)
//3.当服务端返回ret=0时,跳转到真正的网址 /hyms.html
//jQuery解析响应消息
$.ajax({
url: '/api/mgr/signin',
type: 'POST',
data: 'username=byhy&password=88888888',
// 正确返回;回调函数被传入3个参数:data 从服务端返回的数据 ,textStatus 返回的状态文本描述,xhr XMLHttpRequest的扩展类型jqXHR的对象
success: function(data, textStatus, xhr) {
if(data.ret === 0){
//重定向网址
location.href = 'hyms.html'
}
else{
alert('登陆失败: ' + data.msg)
}
},
//错误
error:function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
}
};
</script>
</head>
<body>
<main>
<br>
<div style="display: flex; justify-content: center;">
<img src="/assets/images/logo.jpg" style="border-radius:50%;width:2.5rem;margin-right:1rem">
<!-- main属于block类型元素 ;block元素特征:垂直方向,占据的空间由其内容大小决定 -->
<!-- rem用来修饰 元素的 宽度、高度 ,同样也是相对于 根元素 html 的字体大小 -->
<!-- 相对的是 根元素 html 的字体大小 -->
<!-- margin:盒子模型,外边距,盒子与盒子间的距离 -->
<span style="font-size: 1.8rem">黑羽医疗</span>
</div>
<p>输入用户名、密码登录</p>
<div>
<input type="text" placeholder="用户名" id="username">
<!-- 提供可描述输入字段预期值的提示信息 -->
</div>
<br>
<div>
<!-- div 块级元素 ;特点独占一行 -->
<input type="password" placeholder="密码" id="password">
</div>
<br>
<div>
<button id="loginButton">登录</button>
</div>
<br>
<div>
<a href="/register.html">没有账号?请先注册</a>
</div>
<br>
</main>
</body>
</html>
hyms.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>药品销管</title>
<!-- 外联式 -->
<link rel="stylesheet" href="hyms.css">
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
<script src="hyms.js"></script>
</head>
<body>
<!-- 导航logo -->
<div class="nav-logo">管理员操作</div>
<!-- 导航栏 -->
<nav>
<ol class="sub-nav-bar">
<li class="menu-item">
<!-- div ——块级,新开一行,水平方向占满父级 ;span ——行内,一行显示 -->
<span>产品</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item"><span>客户</span></li>
<li class="menu-item"><span>渠道</span></li>
<li class="menu-item"><span>订单</span></li>
<li class="menu-item"><span>统计</span></li>
</ol>
<ol class="sub-nav-bar sub-nav-bar-right" style="margin-left: auto; margin-right: 1rem;">
<li class="menu-item">
<span>白月黑羽</span>
<ul class="dropdown-menu hidden">
<li class="menu-item">子菜单1</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单2</li>
<div class="dropdown-divider"></div>
<li class="menu-item">子菜单3</li>
</ul>
</li>
</ol>
</nav>
<!-- 侧边菜单栏 -->
<ul class="side-menu">
<!-- 菜单头部 -->
<li class="menu-header">操作菜单</li>
<li class="menu-item">产品</li>
<li class="menu-item">客户</li>
<li class="menu-item has-sub-menu">渠道
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item has-sub-menu">订单
<ul class="sub-menu hidden">
<li class="menu-item">子菜单1</li>
<li class="menu-item">子菜单2</li>
</ul>
</li>
<li class="menu-item">统计</li>
</ul>
<!-- 主体 -->
<main>
<!-- addone 界面 -->
<div class="add-one-area">
<span class='btn' id='add-one-btn'>添加</span>
<div class="add-one-form hidden">
<p>
<span class='field-name'>客户名</span>
<input type="text" id="customer-name" class="input-l"></input>
</p>
<p>
<span class='field-name'>电话</span>
<input type="text" id="customer-phone" class="input-l"></input>
</p>
<p>
<span class='field-name'>地址</span>
<input type="text" id="customer-addr" class="input-xl"></input>
</p>
<div class="add-one-submit-btn-div">
<span class='btn' id='add-one-submit-btn'>确定</span>
</div>
</div>
</div>
<!-- 分页器 -->
<div class="paginator">
<span class="curpage" id="curpage-totalpage"></span>
<span class="btn-no-border" id="prevPage">上一页</span>
<span class="btn-no-border" id="nextPage">下一页</span>
<input type="number" id="gotoPageInput" style="width:3rem">
<span class="btn-no-border" id="gotoPage">跳转</span>
</div>
<!-- 列出条目区 -->
<div class="result-list"></div>
</main>
<!-- 页脚左边 -->
<div class="footer-left"></div>
<!-- 页脚 -->
<footer>
白月黑羽版权所有
<br>
<!-- 自己试在style里加style="padding:1rem;",注意一点:白月黑羽版权所有 是content,不是盒子-->
<small>2020-2022 @copy rights reserved</small>
</footer>
</body>
</html>
hyms.css
/* 通用样式 */
.hidden{
display:none !important;
}
.input-l{
width: 10rem;
}
.input-xl{
width: 20rem;
}
input{
height:1.3rem;
border:1px solid grey;
}
.btn{
background-color: rgb(4, 115, 155);
color:white;
font: size .8rem;
text-align:center;
/* 上下 左右 */
padding: .2rem .4rem;
/* 鼠标指针变小手 */
cursor:pointer;
width:3rem;
/* 禁止用户选择文本内容 */
user-select: none;
}
.btn-no-border{
cursor:pointer;
color:#296cff;
font-size: .8rem;
padding: .2rem .4rem;
border:1px solid whitesmoke;
user-select: none;
}
.btn-no-border:hover{
border:1px solid rgb(4, 115, 155);
}
/* .disable在原来基础上又设一值 */
.btn-no-border.disable{
/* 恢复默认值:正常鼠标 */
cursor:auto;
color:grey;
}
.btn-no-border.disable:hover{
color:grey;
border:1px solid whitesmoke;
}
/* 消除input、textarea和select元素在被选中时的默认外边框样式,使其没有边框 */
input:focus,textarea:focus{
outline:none;
}
/* 功能区设置 */
/* 页面整体 */
body{
height: 100vh;
max-width: 1250px;
/* 上下设成0;左右均分 */
margin: 0 auto;
display: grid;
/* 指定行的数量和高度 */
grid-template-rows: auto 1fr auto;
/* 指定列的数量和宽度;右边占据所有剩余宽度 */
grid-template-columns: minmax(15rem,20rem) 1fr;
}
/* 一行一列:管理员操作 */
.nav-logo{
border-left: 1px solid #e5eaef;
color:rgb(8, 96, 8);
display:flex;
/* flex布局,居中 */
align-items: center;
justify-content: center;
}
/* 整个导航栏 */
nav{
background-color: rgb(4, 115, 155);
color: white;
display: flex;
flex-flow: row wrap;
/* 保证不会挤到一起去,再小出现滚动条 */
min-width: 30rem;
/* 去掉点击后出现的"选中状态"*/
user-select: none;
}
/* 导航栏包含所有菜单项的容器*/
.sub-nav-bar{
list-style-type: none;
display:flex;
flex-flow: row wrap;
gap:2rem;
align-items: center;
justify-content: center;
margin: 0;
}
/* 导航栏菜单项里的下拉菜单 */
.dropdown-menu{
position:absolute;
list-style-type: none;
background-color: white;
color: #2e669f;
/* 整体下移 */
margin-top: .8rem;
font-size: .85rem;
padding-left: 0;
width:10rem;
}
/* 导航栏里的所有单个菜单项 */
/* 后代选择器:选中父元素"后代中"满足条件的元素 ;子代选择器:选择父元素"子代中"满足条件的元素*/
.sub-nav-bar > .menu-item{
/* 相对于该元素在文档流中的正常位置进行偏移定位 */
position: relative;
/* 上下为0,左右为.8rem ;但要注意:这里我只想设一级的子菜单产品那行,需要用子代选择器"->"*/
padding: .8rem;
}
/* 子代采用的是绝对定位,绝对定位相对于非静态定位(static)的父元素进行定位移动;
绝对定位查找父级的方式:就近找定位的父级,如果逐层查找不到这样的父级,就以浏览器窗口为参照进行定位;
希望子元素相对于父元素进行定位,又不希望父元素脱标 采用子绝父相(注意这个“.sub-nav-bar .menu-item”是相对定位;“.dropdown-menu”是绝对定位)*/
.sub-nav-bar-right .dropdown-menu{
/* 最终选择的元素是元素2 ,并且要求这个元素2是元素1的后代元素 ; 右对齐*/
right:0;
}
/* 悬停高亮 */
/* hover伪类选择器语法: 选择器:hover {css};选中鼠标悬停在元素上的状态,设置样式 */
.sub-nav-bar .menu-item:hover{
color:green;
background-color: white;
}
.dropdown-menu .menu-item:hover{
background-color: #e8f5e9;
}
/* 对于所有菜单项,希望光标变成手*/
.menu-item{
cursor: pointer;
}
/* 下拉菜单的每个菜单项 */
.dropdown-menu .menu-item{
/* 上下居中 margin: .6rem; 换成padding 因为背景色设置范围:有效区域包括这个元素的 内容区、padding部分、border部分。也就是包含块除了margin部分 */
padding: .6rem;
}
/* 下拉菜单每个菜单项的分界线 */
.dropdown-divider{
height:0;
/* 一条边 */
border-top:1px solid #e8dcdc;
}
/* 侧边栏 */
.side-menu{
border-left: 1px solid #e5eaef;
border-top: 1px solid #e5eaef;
margin: 0;
/* 文字不顶左角 */
padding:1rem;
list-style-type: none;
/* 根字体的90% */
font-size:.9rem;
display:flex;
/* 列排 */
flex-direction: column;
/* gap:.2rem; flex布局列间距 */
user-select: none;
}
/* 侧边栏的下拉菜单 */
.sub-menu{
list-style-type: none;
display:flex;
/* 列排 */
flex-direction: column;
/* gap: .5rem; */
font-size: .85rem;
padding:0 1rem;
}
/* 左侧菜单 菜单头 */
.side-menu .menu-header{
color:#837b70;
}
/* 左侧菜单 菜单项 */
.side-menu .menu-item{
color: #5e81a5;
/* padding-left: 1rem; */
/* 上 右 下 左 */
padding: .5rem 0 .5rem 1rem;
/* 上下.2rem 左右无 */
margin: .2rem 0;
}
/* 悬停高亮 */
.side-menu .menu-item:hover{
background-color: #e8f5e9;
}
.sub-menu .menu-item:hover{
background-color: #bce5bf;
}
/* 侧边栏展开的菜单项 */
/* .menu-item.has-sub-menu交集选择器,是menu-item又是has-sub-menu的 */
.side-menu .menu-item.has-sub-menu{
color:#6b6464;
border-left:1px solid green;
}
/* 界面主体元素 */
main{
background-color: #fafafa;
/* 防止文字顶左角 */
padding:1rem;
}
/* 第三行一列;页脚左侧容器 */
.footer-left{
border-left: 1px solid #e5eaef;
}
/* 添加客户 */
.add-one-area{
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
/* 上 右 下 左 */
margin: 0 0 1rem 0;
}
.add-one-submit-btn-div{
display:flex;
justify-content: center;
align-items: center;
}
.paginator{
display: flex;
justify-content: center;
align-items: center;
gap:1rem;
margin-bottom: .5rem;
}
/* 正文 */
.result-list{
display:flex;
flex-direction: column;
gap:1rem;
/* 主轴对齐 */
justify-content: center;
/* 从轴对齐 */
align-items: center;
}
.result-list-item{
border:1px solid rgb(170, 177, 170);
padding: 0 1rem;
width: 90%;
}
.field-name{
/* 由于它是个<span>标签,行内元素,宽高不生效;把它转成行内块元素“一行显示多个,宽高生效” */
display: inline-block;
width: 5rem;
color: darkgreen;
}
/* 页脚元素 */
footer{
background-color: #e6e6e6;
text-align: center;
padding:1rem;
}
hyms.js
//全局数据对象
const GDATA = {
curPageNum:1,//当前页码
pagecount:0,//总共页数
}
//注册全局点击事件
function registerGlobalEvents(){
document.addEventListener('click',function(e){
//思路:首先我们先判断直接触发事件的对象(e.target)是否为导航栏“带有下拉菜单”的菜单项,怎么判断呢?—— 看这个元素对象里的class属性是否包含hidden
//对于这个触发对象有个问题:如果点的是li标签,可以判断class属性是否有hidden;
//但如果点的是span标签,也就是产品,他没有class属性,点了也没用不显示,如何解决这个问题呢?
//我们可以采用closest()方法获取符合条件的最接近的上级元素(包括自身),那么这样无论点里点外都能追溯到<li class="menu-item">这个元素, 如果没有匹配的元素返回的就是null
//导航栏菜单点击处理
let NavMenuItem = e.target.closest('.sub-nav-bar > .menu-item')
//点击的是导航栏菜单项
if (NavMenuItem){
//<li class="menu-item">里面有hidden把hidden去掉;没有加上
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = NavMenuItem.querySelector('.dropdown-menu')
//如果有下拉子菜单
if(subMenu){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
//侧边栏菜单点击处理
//问题:点子菜单1,往上追溯,渠道收缩
let sideMenuItem = e.target.closest('.side-menu > .menu-item')
//这里有个问题:点导航栏的下拉菜单我们可以接受点击子菜单然后缩起来;但对于侧边栏我们并不希望这样(子菜单往上找也会追溯到<li class="menu-item">)
//那么我们需要加一个判断条件:如果当前点击的这个元素祖先中有sub-menu就不执行下面内容
//点击的是侧边栏菜单项,并且不是点击子菜单
if (sideMenuItem){
//有的话选出来的是 <ul class="dropdown-menu hidden"> ; 同样的没找到符合条件的元素返回null
let subMenu = sideMenuItem.querySelector('.sub-menu')
//如果有下拉子菜单
//!e.target.closest('.sub-menu')祖先中没有sub-menu;点的不是子菜单
if(subMenu && !e.target.closest('.sub-menu')){
if (subMenu.classList.contains('hidden')){
subMenu.classList.remove("hidden");
}
else{
subMenu.classList.add("hidden");
}
}
}
})
}
//添加按钮点击处理
function registerClickAddOne(){
let addOneBtn = document.querySelector('#add-one-btn')
addOneBtn.addEventListener('click',function(){
let addOneForm = document.querySelector('.add-one-form')
if(addOneForm.classList.contains('hidden')){
addOneForm.classList.remove('hidden')
addOneBtn.innerText='隐藏'
}
else{
addOneForm.classList.add('hidden')
addOneBtn.innerText='添加'
}
})
}
//提交分页器按钮
function registerClickPaginatorBtns(){
let prevPageEle=document.querySelector('#prevPage')
let nextPageEle=document.querySelector('#nextPage')
prevPageEle.addEventListener('click',function(){
if(GDATA.curPageNum === 1)//为1,不做任何处理
return
getCustomerList(GDATA.curPageNum-1)
})
nextPageEle.addEventListener('click',function(){
if(GDATA.curPageNum === GDATA.pagecount)
return
getCustomerList(GDATA.curPageNum+1)
})
document.querySelector('#gotoPage').addEventListener("click",function(e){
let goToPageNum = parseInt(document.querySelector('#gotoPageInput').value.trim())//trim()移除字符串两端的空格
getCustomerList(goToPageNum);
})
document.querySelector('#gotoPageInput').addEventListener("keydown",function(e){
if(e.key === 'Enter'){
let goToPageNum = parseInt(document.querySelector('#gotoPageInput').value.trim())
getCustomerList(goToPageNum);
}
})
}
//提交按钮点击处理
function registerClickAddOneSubmit(){
//先获取
let addOneSubmitBtn = document.querySelector('#add-one-submit-btn')
//监听
addOneSubmitBtn.addEventListener('click',function(){
//取出数据;获取已有的网页界面上的内容
let customer_name = document.querySelector('#customer-name').value
let customer_phone = document.querySelector('#customer-phone').value
let customer_addr = document.querySelector('#customer-addr').value
//发送到后端
$.ajax({
url: '/api/mgr/customers',
type: 'POST',
//消息体的格式是json——指明消息体为json格式
contentType : 'application/json',
//浏览器js的内置对象JSON的stringify方法,可将js对象转化为JSON格式的字符串(序列化)
data: JSON.stringify({
"action":"add_customer",
"data":{
"name":customer_name,
"phonenumber":customer_phone,
"address":customer_addr
}
}),
// success 接收到响应
success: function(data, textStatus, xhr) {
if(data.ret === 0)
getCustomerList();//重新刷新列表
else
alert('操作失败:'+data.msg)
},
error: function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
})
}
//看接口文档,列出所有客户 请求参数http请求消息url中需要携带的参数4个
function getCustomerList(pagenum=1,pagesize=4,keywords=''){
//在发出请求之前,先把结果清空(点击下一页)
document.querySelector('.result-list').innerHTML=''
//获取响应内容
$.ajax({
type: 'GET',
// http协议中,url参数格式都是urlencode格式
url: `/api/mgr/customers?action=list_customer&pagenum=${pagenum}&pagesize=${pagesize}&keywords=${keywords}`,
//jQuery解析响应消息体
success: function(data, textStatus, xhr) {
if(data.ret !== 0){
alert('操作失败: ' + data.msg)
return;
}
//更新分页信息
let pagecount = Math.ceil(data.total/pagesize)//上限整数
document.getElementById('curpage-totalpage').innerText=`第${pagenum}页,共${pagecount}页`
GDATA.curPageNum = pagenum;
GDATA.pagecount = pagecount;
let prevPageEle=document.querySelector('#prevPage')
let nextPageEle=document.querySelector('#nextPage')
if(pagenum===1)
prevPageEle.classList.add('disable')
else
prevPageEle.classList.remove('disable')
if(pagenum===pagecount)
nextPageEle.classList.add('disable')
else
nextPageEle.classList.remove('disable')
//更新结果列表
for(let item of data.retlist){
// 每一项 ,加<p>是为了换行,让它独占一行 ; 前面加一个说明,还要在一行显示,用<span>;还需要指定样式,加个class
let pEle = `<div class='result-list-item'>
<p><span class='field-name'>客户名</span><span>${item.name}</span></p>
<p><span class='field-name'>地址</span><span>${item.address}</span></p>
<p><span class='field-name'>电话</span><span>${item.phonenumber}</span></p>
</div>`
document.querySelector('.result-list').insertAdjacentHTML("beforeend",pEle)
}
},
//错误
error:function (xhr, textStatus, errorThrown ){
console.error(`${xhr.status} \n${textStatus} \n${errorThrown }`)
}
})
}
// 注册事件
window.onload = function(){
registerGlobalEvents()//全局事件
registerClickAddOne()//添加按钮点击处理
registerClickAddOneSubmit()//提交按钮点击处理
registerClickPaginatorBtns()//提交分页器按钮
getCustomerList();//获取客户列表
}