一、login页
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CMDB登录</title>
<link rel="icon" href="{% static 'img/web_logo.png' %}" type="image/x-icon">
<link rel="stylesheet" href="{% static 'css/login.css'%}">
<script src="{% static 'js/login.js' %}"></script>
</head>
<body>
<div id="attention">
<img src="{% static 'img/网站设置.png'%}">
<b><i style="color: #1296db">欢迎来到CMDB管理中心</i></b>
<a href="/register/" id="register">申请账户</a>
</div>
<div style="height: 100vh" id="back"></div>
<p id="unLoginNotice">{{ unLogin }}</p>
<form method="post" id="loginBlock">
<img src="{% static 'img/管理员_角色管理.png' %}" alt="图片丢失">
<span id="loginTitle">
管理员登录
</span>
<input type="text" placeholder="请输入管理员账号" name="username">
<br>
<input type="password" placeholder="请输入密码" name="password">
<br>
<span style="font-size: 10px;color: red">{{ notice }}</span>
<br>
<input type="submit" id="sub" title="登录" value="登录">
</form>
</body>
</html>
*{
margin: 0;
padding: 0;
}
body{
background-image: url('../img/bgc.jpg');
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
}
#attention{
height: 40px;
line-height: 40px;
font-size: 20px;
align-items: center;
padding-left: 60px;
overflow: hidden;
}
#attention>img{
position: absolute;
top: 6px;
left: 20px;
height: 30px;
width: 30px;
}
#register{
font-size: 10px;
margin-left: 70%;
color: #B0BED2;
}
#unLoginNotice{
position: fixed;
top: 20%;
left: 45%;
color: red;
font-size: 30px;
}
form{
border-radius: 5px;
border: 1px solid grey;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
padding: 10px;
padding-right: 20px;
align-content: center;
background-color: white;
}
form>img{
display: inline-block;
height: 20px;
width: 20px;
}
#loginTitle{
display: inline-block;
color: #1296db;
position: relative;
top: -4px;
left: 5px;
}
input{
border-radius: 5px;
margin: 5px 0;
width: 100%;
height: 30px;
line-height: 30px;
padding-left: 5px;
border: 1px solid lightgrey;
}
#sub{
width: 405px;
}
#subImg{
height: 15px;
width: 15px;
}
window.onload = function (){
//获取非法跳转提示信息。
const unLoginNotice = document.getElementById('unLoginNotice');
//获取输入表单。
const loginBlock = document.getElementById('loginBlock');
//当鼠标点击表单时,提示信息消失。
loginBlock.addEventListener('click',function (){
unLoginNotice.style.display = 'none';
})
}
二、home页
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CMDB管理</title>
<link rel="icon" href="{% static 'img/web_logo.png' %}" type="image/x-icon">
<link rel="stylesheet" href="{% static 'css/home.css' %}">
<script src="{% static 'js/home.js' %}"></script>
</head>
<body>
<div id="attention">
<img src="{% static 'img/网站设置.png'%}">
<b><i style="color: #1296db">欢迎{{ username }}来到CMDB管理中心</i></b>
</div>
<div id="nav"><img src="{% static 'img/工作台.png' %}"></div>
<div id="dockersData">
<img src="{% static 'img/卫星.png' %}" class="leftImg">
<a href="#">容器状态中心</a>
</div>
<div id="processData">
<img src="{% static 'img/卫星.png' %}" class="rightImg">
<a href="#">进程状态中心</a>
</div>
<div id="verCodeCenter">
<img src="{% static 'img/卫星.png' %}" class="leftImg">
<a href="#">核验码管理中心</a>
</div>
<div id="accountCenter">
<img src="{% static 'img/卫星.png' %}" class="rightImg">
<a href="#">账户管理中心</a>
</div>
</body>
</html>
*{
margin: 0;
padding: 0;
}
body{
background-image: url('../img/bgc.jpg');
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
}
#attention{
height: 40px;
line-height: 40px;
font-size: 20px;
align-items: center;
padding-left: 60px;
overflow: hidden;
}
#attention>img{
position: absolute;
top: 6px;
left: 20px;
height: 30px;
width: 30px;
}
#nav{
display: block;
height: 400px;
width: 400px;
text-align: center;
border-radius: 400px;
border: 1px solid black;
position: relative;
left: 500px;
top: 130px;
background-image: url('../img/adminBgc.jpg');
background-position: center center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 1);
filter: brightness(0.9);
}
#nav>img{
margin-top: 100px;
width: 200px;
height: 200px;
}
a{
color: gold;
}
a:hover{
color: red;
}
#dockersData{
align-items: center;
font-size: 30px;
position: absolute;
display: none;
height: 200px;
line-height: 200px;
width: 300px;
border-radius: 20px;
top: 120px;
left: 60px;
}
#processData{
align-items: center;
font-size: 30px;
position: absolute;
display: none;
height: 200px;
line-height: 200px;
width: 500px;
border-radius: 20px;
top: 130px;
left: 870px;
}
#verCodeCenter{
align-items: center;
font-size: 30px;
position: absolute;
display: none;
height: 200px;
line-height: 200px;
width: 300px;
border-radius: 20px;
top: 400px;
left: 60px;
}
#accountCenter{
align-items: center;
font-size: 30px;
position: absolute;
display: none;
height: 200px;
line-height: 200px;
width: 500px;
border-radius: 20px;
top: 410px;
left: 870px;
}
.leftImg{
transform: scaleX(-1);
width: 30px;
}
.rightImg{
width: 30px;
}
window.onload = function (){
//获取导航球
const nav = document.getElementById('nav');
//获取子模块。
const dockersData = document.getElementById('dockersData');
const processData = document.getElementById('processData');
const verCodeCenter = document.getElementById('verCodeCenter');
const accountCenter = document.getElementById('accountCenter');
//定义休眠函数。
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
//设置导航球鼠标移入时向左移动,子模块显示。
nav.addEventListener("mouseover", async function (event) {
nav.style.transition = "transform 0.3s ease-in-out";
nav.style.transform = "translateX(-100px)";
await sleep(500); // 延迟 500 毫秒(0.5秒)
dockersData.style.display = 'block';
processData.style.display = 'block';
verCodeCenter.style.display = 'block';
accountCenter.style.display = 'block';
});
// 设置导航块鼠标移出时恢复原设置。
nav.addEventListener("mouseout", async function (event) {
await sleep(10000); // 延迟 10000 毫秒(10秒)
dockersData.style.display = 'none';
processData.style.display = 'none';
verCodeCenter.style.display = 'none';
accountCenter.style.display = 'none';
nav.style.transform = "translateX(0)";
});
}
三、register页
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>申请管理员账号</title>
<link rel="icon" href="{% static 'img/web_logo.png' %}" type="image/x-icon">
<link rel="stylesheet" href="{% static 'css/register.css' %}">
</head>
<body>
<div id="attention">
<img src="{% static 'img/网站设置.png'%}">
<b><i style="color: #1296db">欢迎来到CMDB管理中心</i></b>
<a href="/" id="login">登录</a>
</div>
<form method="post">
<img src="{% static 'img/管理员_角色管理.png' %}" alt="图片丢失">
<span id="registerTitle">申请账户</span>
<input type="text" placeholder="请输入姓名" class="inputBlock" name="name">
<input type="text" placeholder="请输入用户名" class="inputBlock" name="username">
<span class="notices">{{ user_notice }}</span>
<input type="password" placeholder="请输入密码" class="inputBlock" name="password">
<span class="notices">{{ psw_notice }}</span>
<input type="password" placeholder="再次输入密码" class="inputBlock" name="verpwd">
<span class="notices">{{ psw_notice }}</span>
<input type="text" placeholder="请输入邮箱" class="inputBlock" name="email">
<span class="notices">{{ email_notice }}</span>
<input type="text" placeholder="请输入核验码" class="inputBlock" name="vercode">
<span class="notices">{{ ver_notice }}</span>
<br>
<input type="submit" value="注册" class="inputBlock" name="reg">
</form>
</body>
</html>
*{
padding: 0;
margin: 0;
}
body{
background-image: url('../img/bgc.jpg');
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
}
#attention{
height: 40px;
line-height: 40px;
font-size: 20px;
align-items: center;
padding-left: 60px;
overflow: hidden;
}
#attention>img{
position: absolute;
top: 6px;
left: 20px;
height: 30px;
width: 30px;
}
#login{
font-size: 10px;
margin-left: 80%;
}
form{
background-color: white;
border: 1px lightgrey solid;
width: 300px;
margin: 200px auto;
padding: 5px 8px 5px 5px;
}
form>img{
display: inline-block;
height: 20px;
width: 20px;
}
#registerTitle{
display: inline-block;
color: #1296db;
position: relative;
top: -4px;
left: 5px;
}
.notices{
font-size: 10px;
color: red;
}
.inputBlock{
display: block;
height: 20px;
line-height: 20px;
width: 100%;
margin: 5px 0;
}
四、view.py
from django.shortcuts import render, redirect
from web.tools import searchData
import os
import django
import re
import ast
# 环境配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CMDB.settings')
django.setup()
# Create your views here.
def login(request):
"""
登录页面
:param request:
:return: 账号验证无误则进入管理首页,有误则包含警告信息返回当前页
"""
unLogin = ''
# 调用数据库查询方法
rows = searchData.searchContents('users')
# 将数据库中获取的元组转为字典
users = {}
for row in rows:
users[row[0]] = row[1]
# 根据页面的访问方式进行响应
if request.method == 'GET':
if 'unLogin' in request.session:
unLogin = request.session['unLogin']
return render(request, 'login.html', {'unLogin': unLogin})
else:
username = request.POST.get('username')
password = request.POST.get('password')
if username in users and password == users[username]:
# 使用会话传递用户名
request.session['username'] = username
return redirect('/home')
return render(request, 'login.html', {'notice': '管理员账号或密码输入错误', 'unLogin': unLogin})
def home(request):
"""
:param request:
:return: 首页
"""
# 获取users表中所有信息,判断跳转时携带的用户名是否正确。
# 调用数据库查询方法
rows = searchData.searchContents('users')
# 将数据库中获取的元组转为字典
users = {}
for row in rows:
users[row[0]] = row[1]
# 获取session中存放的用户名
username = request.session.get('username')
if username not in users:
request.session['unLogin'] = '您还未登录!'
return redirect('/login')
# 清除session防止影响其他功能
# request.session.flush()
# 获取最新文件内容
os.system(r"C:\Users\12269\PycharmProjects\CMDB\web\tools\getClientData.py")
# 获取'web/clientData/dockerStatus.txt'内容,并进行过滤操作。
dockerStatus = []
try:
with open('web/clientData/dockerStatus.txt', 'r') as file:
# 将文件中内容转化成列表
for line in file:
data = ast.literal_eval(line)
dockerStatus.append(data)
# 删除每个子列表的第一个元素
for sublist in dockerStatus:
del sublist[0]
except FileNotFoundError:
print('文件 web/clientData/dockerStatus.txt 不存在!')
# 将dockerStatus列表中存储的信息传输至数据表
from web.models import DockerStatus
# 清空数据表
DockerStatus.objects.all().delete()
# 插入数据
for i in range(0, len(dockerStatus)):
obj = DockerStatus.objects.create(**{'name': dockerStatus[i][0], 'status': dockerStatus[i][1]})
obj.save()
# 从数据库中获取web_dockerstatus表的数据
rows = searchData.searchContents('web_dockerstatus')
dockerStatus = {}
for row in rows:
dockerStatus[row[1]] = row[2]
# 获取'web/clientData/allDockerStatus.txt'内容
servicesStatus = ''
try:
with open('web/clientData/allServicesStatus.txt', 'r') as file:
content = file.readlines()
servicesStatus = [line.replace('\n', '') for line in content] # 去除\n
except FileNotFoundError:
print('文件 web/clientData/allDockerStatus.txt 不存在!')
# 筛选allServicesStatus.txt中的有效数据,并存入web_allServicesStatus表中
from web.models import AllServicesStatus
# 清空数据表
AllServicesStatus.objects.all().delete()
did = ''
name = ''
for row in servicesStatus:
user = ''
pid = ''
ppid = ''
cpu = ''
elapsed = ''
tty = ''
if 'Container ID' in row:
did = row[-12:] # 获取容器ID
if 'Container Name' in row:
name = row[15:] # 获取容器名称
if 'USER' in row:
continue # 当遍历到表头行时跳过该行
if 'has no running processes' in row: # 当容器中不存在进程,则状态字段置空
obj = AllServicesStatus.objects.create(**{'did': did,
'name': name,
'user': user,
'pid': pid,
'ppid': ppid,
'cpu': cpu,
'elapsed': elapsed,
'tty': tty})
obj.save()
if 'pts' in row or '?' in row:
tempStatusList = re.split(r"\s+", row.strip()) # 按空格拆分行
print(tempStatusList)
user = tempStatusList[1] # 获取服务用户
pid = tempStatusList[2] # 获取服务pid
ppid = tempStatusList[3] # 获取服务ppid
cpu = tempStatusList[4] # 获取服务cpu使用率
elapsed = tempStatusList[5] # 获取服务运行时间
tty = tempStatusList[6] # 获取服务tty
# 填入数据
obj = AllServicesStatus.objects.create(**{'did': did,
'name': name,
'user': user,
'pid': pid,
'ppid': ppid,
'cpu': cpu,
'elapsed': elapsed,
'tty': tty})
obj.save()
# 从数据库获取数据。
servicesStatus = searchData.searchContents('web_allServicesStatus')
return render(request, 'home.html',
{'username': username, 'dockerStatus': dockerStatus, 'servicesStatus': servicesStatus})
def register(request):
"""
注册页面
:param request:
:return: 注册信息无误返回登录界面,有误则包含警告信息返回当前页
"""
if request.method == 'GET':
return render(request, 'register.html')
else:
# 获取注册信息
name = request.POST.get('name')
username = request.POST.get('username')
password = request.POST.get('password')
verpwd = request.POST.get('verpwd')
email = request.POST.get('email')
vercode = request.POST.get('vercode')
# 警告信息
user_notice = ''
psw_notice = ''
ver_notice = ''
email_notice = ''
# 正则表达式
user_pattern = r'^[a-zA-Z0-9_]+$'
psw_pattern = r'^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[@#$%^&+=])(?!.*\s).{8,}$'
email_pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
# 核验用户名
if not re.match(user_pattern, username):
user_notice = '用户名仅可由数字字母下划线组成'
# 从数据库中获取所有用户名,当前用户名存在时提示重复并重新输入
rows = searchData.searchContents('users')
if username in rows:
user_notice = '用户名不可重复'
# 核验密码,当两次密码输入相同且不为空时通过密码核验
if not (password == verpwd and password and re.match(psw_pattern, password)):
psw_notice = '请重新输入密码'
# 核验邮箱
if not re.match(email_pattern, email):
email_notice = '邮箱格式有误'
# 验证核验码,从数据库中查询核验码是否存在且未被使用
rows = searchData.searchContents('web_vercode')
# 设置验证信号,初始为False,当核验成功则置为True
flag = False
for row in rows:
if row[1] == vercode and row[2] == 'False':
# 如果核验码有效,则将该核验码失效
from web.models import VerCode
obj = VerCode.objects.get(id=row[0])
obj.status = 'True'
obj.save()
# 修改验证信号
flag = True
break
# 无效核验码时
if not flag:
ver_notice = '核验码无效'
# 当两个警告信息有一个不为空时,则说明输入有误
if psw_notice or ver_notice:
return render(request, 'register.html',
{'user_notice': user_notice, 'psw_notice': psw_notice, 'email_notice': email_notice,
'ver_notice': ver_notice, })
# 信息输入无误后,将注册信息传入申请表中,并返回登录界面
from web.models import Candidate
obj = Candidate.objects.create(
**{'name': name, 'username': username, 'password': password, 'email': email, 'verCode': vercode})
obj.save()
# 所有信息处理完毕,返回登录页
return redirect('/login')
有一些我自己写的脚本没有粘在此文档中,有需要可以自行查看往期文章,还有一些图片素材我没有放出,大家可以根据自己喜好查找素材。