Python实现员工管理系统(Django页面版 ) 八

        Hello 大家新年好。今天这篇博客是用来填补之前的登录系统的不足所遗留下来的坑点,你们知道的,我有坑是必补啊。

        首先我留的第一个坑点不知道大家有没有注意到,当我们没并没有登录的时候,但是如果我们事先知道一些内部测试的网站路由的话,我们可以跳过登录直接进入到里面。

         我们可以发现,明明我并没有进行登录,但是如果有人知道我的路由,它就可以直接进来,这肯定是不允许的,因此我要引用一个新的内容-------session与cookie

        Cookie是由服务器发送给浏览器的小型文本文件,存储在用户的计算机上。它包含有关用户的信息,如用户ID、首选项和购物车内容。当用户访问网站时,浏览器会将Cookie发送回服务器,以便服务器可以根据存储在Cookie中的信息来识别用户并提供个性化的服务。

        Session是服务器上存储用户会话数据的一种机制。当用户访问网站时,服务器会为每个会话创建一个唯一的ID,并将该ID存储在Cookie中或通过URL参数传递给浏览器。然后,服务器使用该ID来跟踪用户的会话数据,如登录状态、购物车内容等。与Cookie不同,Session数据保存在服务器上,而不是用户的计算机上。

        一般来讲,网站都是通过记录你的session和cookie来判断你是否登录过,如果网站记录过你存在的session和cookie记录,那么网站会让你直接进入而不需要再次登录,我们可以利用这个特点来进行判断当前是否存在该用户,如果没有则让其返回登录界面。

login.py

def login(request):
    if request.method == 'GET':
        form = LoginForm()
        return render(request,'login.html',{'form':form})

    form = LoginForm(data=request.POST)
    if form.is_valid():
        # 验证码验证
        user_input_code = form.cleaned_data.pop('code')
        # 没有值设置为空
        code = request.session.get('image_code','')
        # 对于验证码不区分大小写
        if user_input_code.upper() != code.upper():
            form.add_error('code','验证码错误')
            return render(request,'login.html',{'form':form})

        # 账号密码验证,数据库校验
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            # print(form.cleaned_data)
            form.add_error('password','用户名或者密码错误')
            return render(request,'login.html',{'form':form})
        # 生成字符串存储到cookie和session当中去
        info = {
            'id':admin_object.id,
            'name':admin_object.username,
            'role':admin_object.role
        }

        request.session['info'] = info

        # 时效性           ------ 一个点
        request.session.set_expiry(60 * 60 * 24)

        # request.session.set_expiry(10)

        return redirect('/')
    return render(request,'login.html',{'form':form})

         我们通过记录用户登录的数据来作为用户的session数据(为什么使用这个后面会有解释),然后对我们记录的session加一个时效性进行约束,过了这个时间session自动删除。

        现在我们开始写对于如何判断是否存在该用户,首先我先介绍一个苯的方法,随便找一个模块方法,例如部门列表:

depart_list:

        对于每一个模块我们都在里面进行一个对session进行一个判断,如果不存在就重定向到登录界面,但是这样的缺点就是会让我们的代码看上去非常的冗余且不容易维护,要是我们有100个这样的模块方法,那这样写我们就得写100个,当然我们肯定不会用这样的方法进行编写,那有没有办法让计算机自动为我们进行判断是否存在session的方法呢? 接下来我来介绍一种新的方式----中间件的使用。

 中间件(Middleware)是位于Web应用程序的请求和响应处理管道中的组件。它负责在处理请求之前和处理响应之后执行特定的任务。中间件可以用于许多不同的目的,如身份验证、日志记录、错误处理等。

中间件的特点和优势包括:

  1. 可重用性:中间件可以在多个不同的请求和应用程序中重复使用,提高了代码的可重用性。

  2. 可插拔性:中间件可以灵活地添加和移除,以满足不同的需求。这使得应用程序可以根据需要选择和配置适当的中间件。

  3. 解耦性:中间件可以将不同的功能和任务解耦,使得代码更加模块化和可维护。

  4. 可扩展性:由于中间件可以按照自定义的顺序链式调用,因此可以很容易地实现功能的扩展和组合。

         由于中间件具有可重用性这一优良特点,我们可以在中间件中对于session进行一个判断,然后将我们需要进行判断的模块放入到其中。

        创建一个新的文件夹为middleware(不能使用别的名称,不然得去配置修改),在其中创建一个auth模块用于检验。

在其中创建一个中间件类,导入相关模块

# -*- coding:utf-8 -*-
from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings

from django.utils.deprecation import MiddlewareMixin

class AuthMiddleware(MiddlewareMixin):
    def process_request(self,request):
        print('这是入口')

    def process_response(self,request,response):
        print('这是出口')

然后进入setting.py中,添加创建的中间件模块

        各位读者可以自行测试一下这个中间件,随便进入一个模块,然后看一下控制台输入了什么,就可以明白其工作原理啦。

# -*- coding:utf-8 -*-
from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings

from django.utils.deprecation import MiddlewareMixin

class AuthMiddleware(MiddlewareMixin):
    def process_request(self,request):
        if request.path_info in ['/login/','/logout/','/image/code/']:
            return

        return redirect('/login/')


    def process_response(self,request,response):
        return response

        为什么要对登录和退出以及验证码进行一个额外的判断,因为如果你不能加入这个的话,如果此时你并没有登录,那么你就会一直对于登录重定向,始终也不会到达登录界面,这个大家自行检验,如果把这个if删掉会发生什么。

        现在我们开始最开始的操作,如果我在不登录的前提下,我通过路由进入部门列表会发生什么。

         我们可以通过验证码注意到,我们其实又回到了登录界面,刷新了一下界面也就是进行了一个重定向操作。

        现在我们输入账号和密码进入到我们的系统里面,然后我们开始讲解我埋下的第二个坑点----用户权限划分。

        首先我现在是一个普通员工,但是我发现我现在可以进行与管理员一样的操作,可以对数据进行删除和修改,这要是遇到有素质的还好,这要是是一个对公司有意见的,我直接给你全删了,或者给你修改数据,这肯定是不行的。首先我先讲解一个简单的方法-----直接从前端做判断处理

        我们在前面写中间件的时候,如果我们能够存储登录的信息的话,然后将这些信息附加到我们每次的请求中去,然后我们通过这些信息进行一个判断,我们是不是可以得出我们想要的界面呢。

auth.py

# -*- coding:utf-8 -*-
from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings

from django.utils.deprecation import MiddlewareMixin

class AuthMiddleware(MiddlewareMixin):
    def process_request(self,request):
        if request.path_info in ['/login/','/logout/','/image/code/']:
            return


        info_dict = request.session.get('info')
        if info_dict:
            # 权限划分板块
            request.unicom_userid = info_dict['id']
            request.unicom_username = info_dict['name']
            request.unicom_role = info_dict['role']
            # print(request.unicom_userid,request.unicom_username,request.unicom_role)
            return
        return redirect('/login/')


    def process_response(self,request,response):
        return response

        就如我刚刚说的,如果我是一个普通员工,那我肯定只能看到普通员工才能看到的画面,如果我是管理员,那么我就应该看到管理员应该看到的。

layout.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
</head>
{#<body background="{% static 'img/image.jpg' %}" STYLE="background-repeat: no-repeat;background-attachment: fixed;background-size: 100% 100%">#}
<body>
<div class="navbar navbar-default">
    <div class="container">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="http://127.0.0.1:8000/">管理系统</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                {% if request.unicom_role == 'user' %}
                    <li><a href="/user/list/">员工列表</a></li>
                    <li><a href="/pretty/list/">账号列表</a></li>
                {% endif %}
                {% if request.unicom_role == 'boss' %}
                    <li><a href="/depart/list">部门列表</a></li>
                    <li><a href="/user/list/">员工列表</a></li>
                    <li><a href="/pretty/list">账号管理</a></li>
                {% endif %}
                {% if request.unicom_role == 'admin' %}
                    <li><a href="/user/list/">员工列表</a></li>
                    <li><a href="/depart/list">部门列表</a></li>
                    <li><a href="/pretty/list">账号管理</a></li>
                    <li><a href="/admin/list">用户账号</a></li>
                {% endif %}
  

            </ul>

            <ul class="nav navbar-nav navbar-right">
                {#                <li><a href="#">登录</a></li>#}
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">{{ request.session.info.name }} <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="/logout/"> 退出登录 </a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</div>

<div>
    {#用于其他html代码进行代码复写#}
    {% block content %}
    {% endblock %}
</div>

{# 引入js代码 #}
<script src="{% static 'js/jquery-3.7.1.js' %}"></script>
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
<script src="{% static 'laydate/laydate.js' %}"></script>

{% block js %}

{% endblock %}

</body>
</html>

        我们通过这样写是不是就能保证每一种级别的员工都只能看到他们自己能看到的,然后我们找一个普通级别的账号试试效果。

        那么这初步的用户权限划分就结束了。。。。。

        啊?你们不会真的以为结束了吧 ,我还没码完怎么可能就这样结束。。。。。这里面还有坑我的朋友们,现在我们在普通员工页面里面可以发现它是没有部门列表的,如果我现在在里面输入部门列表会发生什么?

         可以发现它居然给我们跳转到部门列表了,啊这。。。。。不过细心的朋友可能发现了,这不是跟我们刚刚的登录是一回事嘛,所以我们还是得用到中间件,接下来我们处理用户权限的细节处理。

这里我们首先要对路由进行一个修改,对路由的信息做一个标记

urls.py

from django.contrib import admin
from project_manage import views
from project_manage.views import depart, user, pretty,admin,login,demo,perform,image

urlpatterns = [
    # 首页
    path('', depart.index, name="index"),
    # 部门列表
    path('depart/list/', depart.depart_list, name="depart_list"),

    # 增加部门
    path('depart/add/', depart.depart_add, name="depart_add"),

    # 删除部门
    path('depart/delete/', depart.depart_delete, name="depart_delete"),

    # 修改部门
    path('depart/<int:nid>/modify/', depart.depart_modify, name="depart_modify"),

    # 员工列表
    path('user/list/', user.user_list, name="user_list"),

    # 员工删除
    # path('user/delete/', views.user_delete),
    path('user/<int:nid>/delete/', user.user_delete, name="user_delete"),

    # 员工增加
    path('user/add/', user.user_add, name="user_add"),

    # 员工增加ModelForm
    path('user/model/form/add/', user.user_model_form_add, name="user_model_form_add"),

    # 员工修改ModelForm
    path('user/<int:nid>/modify/', user.user_modify, name="user_modify"),

    # 账号列表
    path('pretty/list/', pretty.pretty_list, name="pretty_list"),

    # 账号添加
    path('pretty/add/', pretty.pretty_add, name="pretty_add"),

    # 账号编辑
    path('pretty/<int:nid>/modify/', pretty.pretty_modify, name="pretty_modify"),

    # 账号删除
    path('pretty/<int:nid>/delete/', pretty.pretty_delete, name="pretty_delete"),

    # 用户账号列表
    path('admin/list/', admin.admin_list, name="admin_list"),

    # 用户账号添加
    path('admin/add/', admin.admin_add, name="admin_add"),

    # 用户账号编辑
    path('admin/<int:nid>/modify/', admin.admin_modify, name="admin_modify"),

    # 用户账号删除
    path('admin/<int:nid>/delete/', admin.admin_delete, name="admin_delete"),

    # 用户密码重置
    path('admin/<int:nid>/reset/', admin.admin_reset, name="admin_reset"),

    # 登录页面
    path('login/',login.login),

    # 退出登录
    path('logout/',login.logout),

    # 验证码
    path('image/code/',login.image_code,name='image_code'),

]

        在路由后面对每一个路由命名,然后打开setting.py,在其中新建一个变量用于存储不同级别的用户可以进行的操作

UNICOM_PERMISSION = {
    "admin": ["index", "depart_list", "depart_add", "depart_delete", "depart_modify",
              "user_list", "user_delete", "user_add", "user_model_form_add", "user_modify",
              "pretty_list", "pretty_add", "pretty_modify", "pretty_delete", "admin_list",
              "admin_add", "admin_modify", "admin_delete", "admin_reset",'demo_list','demo_add',
              'demo_delete','demo_modify', 'demo_content_modify',
              'perform_list','perform_add','perform_delete','perform_modify','perform_content_modify',
              'image_list','media','image_delete'

              ],
    "boss": ["index", "depart_list", "depart_add", "depart_delete", "depart_modify",
             "user_list", "user_delete", "user_add", "user_model_form_add", "user_modify",
             "pretty_list", "pretty_add", "pretty_modify", "pretty_delete", "admin_list", "admin_modify"
             ],
    "user": ["index", "user_list", "pretty_list",'perform_list','image_list','media']
}

然后对于中间件重新编写

# -*- coding:utf-8 -*-
from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings

from django.utils.deprecation import MiddlewareMixin

class AuthMiddleware(MiddlewareMixin):
    def process_request(self,request):
        if request.path_info in ['/login/','/logout/','/image/code/']:
            return


        info_dict = request.session.get('info')
        if info_dict:
            # 权限划分板块
            request.unicom_userid = info_dict['id']
            request.unicom_username = info_dict['name']
            request.unicom_role = info_dict['role']
            # print(request.unicom_userid,request.unicom_username,request.unicom_role)
            return
        return redirect('/login/')

    # 权限校验板块
    def process_view(self,request,view_func,args,kwargs):
        # 无需校验登录和退出  ------测试点
        if request.path_info in ['/login/','/logout/','/image/code/']:
            return
        # print(request.resolver_match)

        # 当前用户的角色
        role = request.unicom_role
        # print(role)
        # 角色具备的权限
        user_permission_list = settings.UNICOM_PERMISSION[role]
        # print(user_permission_list)
        if request.resolver_match.url_name in user_permission_list:
            # print(request.resolver_match.url_name)
            return

        return render(request,'error.html')

    def process_response(self,request,response):
        return response

        其中如果发现该用户没有这个权限时,我们就会让其返回到一个错误界面中。

在templates中新建一个error.html文件

error.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>404</title>

    <style>
        html, body {
            height: 100%;
            min-height: 450px;
            font-size: 32px;
            font-weight: 500;
            color: #5d7399;
            margin: 0;
            padding: 0;
            border: 0;
        }

        .content {
            height: 100%;
            position: relative;
            z-index: 1;
            background-color: #d2e1ec;
            background-image: -webkit-linear-gradient(top, #bbcfe1 0%, #e8f2f6 80%);
            background-image: linear-gradient(to bottom, #bbcfe1 0%, #e8f2f6 80%);
            overflow: hidden;
        }

        .snow {
            position: absolute;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 20;
        }

        .main-text {
            padding: 20vh 20px 0 20px;
            text-align: center;
            line-height: 2em;
            font-size: 5vh;
        }

        .main-text h1 {
            font-size: 45px;
            line-height: 48px;
            margin: 0;
            padding: 0;
        }

        .main-text-a {
            height: 32px;
            margin-left: auto;
            margin-right: auto;
            text-align: center;
        }

        .main-text-a a {
            font-size: 16px;
            text-decoration: none;
            color: #0066CC;
        }

        .main-text-a a:hover {
            color: #000;
        }

        .home-link {
            font-size: 0.6em;
            font-weight: 400;
            color: inherit;
            text-decoration: none;
            opacity: 0.6;
            border-bottom: 1px dashed rgba(93, 115, 153, 0.5);
        }

        .home-link:hover {
            opacity: 1;
        }

        .ground {
            height: 160px;
            width: 100%;
            position: absolute;
            bottom: 0;
            left: 0;
            background: #f6f9fa;
            box-shadow: 0 0 10px 10px #f6f9fa;
        }

        .ground:before, .ground:after {
            content: '';
            display: block;
            width: 250px;
            height: 250px;
            position: absolute;
            top: -62.5px;
            z-index: -1;
            background: transparent;
            -webkit-transform: scaleX(0.2) rotate(45deg);
            transform: scaleX(0.2) rotate(45deg);
        }

        .ground:after {
            left: 50%;
            margin-left: -166.66667px;
            box-shadow: -340px 260px 15px #8193b2, -620px 580px 15px #8193b2, -900px 900px 15px #b0bccf, -1155px 1245px 15px #b4bed1, -1515px 1485px 15px #8193b2, -1755px 1845px 15px #8a9bb8, -2050px 2150px 15px #91a1bc, -2425px 2375px 15px #bac4d5, -2695px 2705px 15px #a1aec6, -3020px 2980px 15px #8193b2, -3315px 3285px 15px #94a3be, -3555px 3645px 15px #9aa9c2, -3910px 3890px 15px #b0bccf, -4180px 4220px 15px #bac4d5, -4535px 4465px 15px #a7b4c9, -4840px 4760px 15px #94a3be;
        }

        .ground:before {
            right: 50%;
            margin-right: -166.66667px;
            box-shadow: 325px -275px 15px #b4bed1, 620px -580px 15px #adb9cd, 925px -875px 15px #a1aec6, 1220px -1180px 15px #b7c1d3, 1545px -1455px 15px #7e90b0, 1795px -1805px 15px #b0bccf, 2080px -2120px 15px #b7c1d3, 2395px -2405px 15px #8e9eba, 2730px -2670px 15px #b7c1d3, 2995px -3005px 15px #9dabc4, 3285px -3315px 15px #a1aec6, 3620px -3580px 15px #8193b2, 3880px -3920px 15px #aab6cb, 4225px -4175px 15px #9dabc4, 4510px -4490px 15px #8e9eba, 4785px -4815px 15px #a7b4c9;
        }

        .mound {
            margin-top: -80px;
            font-weight: 800;
            font-size: 180px;
            text-align: center;
            color: #dd4040;
            pointer-events: none;
        }

        .mound:before {
            content: '';
            display: block;
            width: 600px;
            height: 200px;
            position: absolute;
            left: 50%;
            margin-left: -300px;
            top: 50px;
            z-index: 1;
            border-radius: 100%;
            background-color: #e8f2f6;
            background-image: -webkit-linear-gradient(top, #dee8f1, #f6f9fa 60px);
            background-image: linear-gradient(to bottom, #dee8f1, #f6f9fa 60px);
        }

        .mound:after {
            content: '';
            display: block;
            width: 28px;
            height: 6px;
            position: absolute;
            left: 50%;
            margin-left: -150px;
            top: 68px;
            z-index: 2;
            background: #dd4040;
            border-radius: 100%;
            -webkit-transform: rotate(-15deg);
            transform: rotate(-15deg);
            box-shadow: -56px 12px 0 1px #dd4040, -126px 6px 0 2px #dd4040, -196px 24px 0 3px #dd4040;
        }

        .mound_text {
            -webkit-transform: rotate(6deg);
            transform: rotate(6deg);
        }

        .mound_spade {
            display: block;
            width: 35px;
            height: 30px;
            position: absolute;
            right: 50%;
            top: 42%;
            margin-right: -250px;
            z-index: 0;
            -webkit-transform: rotate(35deg);
            transform: rotate(35deg);
            background: #dd4040;
        }

        .mound_spade:before, .mound_spade:after {
            content: '';
            display: block;
            position: absolute;
        }

        .mound_spade:before {
            width: 40%;
            height: 30px;
            bottom: 98%;
            left: 50%;
            margin-left: -20%;
            background: #dd4040;
        }

        .mound_spade:after {
            width: 100%;
            height: 30px;
            top: -55px;
            left: 0%;
            box-sizing: border-box;
            border: 10px solid #dd4040;
            border-radius: 4px 4px 20px 20px;
        }
    </style>

</head>

<body translate="no">
<div class="content">
    <canvas class="snow" id="snow" width="1349" height="400"></canvas>
    <div class="main-text">
        <h1>404 天呐!出错了 ~<br><br>您好像去了一个不存在的地方! (灬ꈍ ꈍ灬)</h1>
        <div class="main-text-a"><a href="/">< 返回 首页</a></div>
    </div>
    <div class="ground">
        <div class="mound">
            <div class="mound_text">404</div>
            <div class="mound_spade"></div>
        </div>
    </div>
</div>


<script>
    (function () {
        function ready(fn) {
            if (document.readyState != 'loading') {
                fn();
            } else {
                document.addEventListener('DOMContentLoaded', fn);
            }
        }

        function makeSnow(el) {
            var ctx = el.getContext('2d');
            var width = 0;
            var height = 0;
            var particles = [];

            var Particle = function () {
                this.x = this.y = this.dx = this.dy = 0;
                this.reset();
            }

            Particle.prototype.reset = function () {
                this.y = Math.random() * height;
                this.x = Math.random() * width;
                this.dx = (Math.random() * 1) - 0.5;
                this.dy = (Math.random() * 0.5) + 0.5;
            }

            function createParticles(count) {
                if (count != particles.length) {
                    particles = [];
                    for (var i = 0; i < count; i++) {
                        particles.push(new Particle());
                    }
                }
            }

            function onResize() {
                width = window.innerWidth;
                height = window.innerHeight;
                el.width = width;
                el.height = height;

                createParticles((width * height) / 10000);
            }

            function updateParticles() {
                ctx.clearRect(0, 0, width, height);
                ctx.fillStyle = '#f6f9fa';

                particles.forEach(function (particle) {
                    particle.y += particle.dy;
                    particle.x += particle.dx;

                    if (particle.y > height) {
                        particle.y = 0;
                    }

                    if (particle.x > width) {
                        particle.reset();
                        particle.y = 0;
                    }

                    ctx.beginPath();
                    ctx.arc(particle.x, particle.y, 5, 0, Math.PI * 2, false);
                    ctx.fill();
                });

                window.requestAnimationFrame(updateParticles);
            }

            onResize();
            updateParticles();
        }

        ready(function () {
            var canvas = document.getElementById('snow');
            makeSnow(canvas);
        });
    })();
</script>

</body>
</html>

        因为本人对于前端代码写的不是特别好,因此在网上找的一个错误界面代码,但是忘记标记在哪找的了,如果涉及到抄袭不允许的话,作者可以私聊我,我可以进行删除,sorry~。

这样我们重新运行我们的代码然后重新进入部门列表

         因此我们的权限划分就到此结束啦。

         最后再祝大家新年快乐啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/331324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端公共组件库优化

背景 前段时间入职了新公司后&#xff0c;做一些内部前端基建的工作&#xff0c;其中一个工作就是优化现有的frontend-common公共组件库。之前的组件库一直是以源码依赖的形式存在&#xff0c;即各个项目通过git submodule的方式将该仓库引入到各个项目中&#xff0c;作为一个…

Win32 字符串表达式计算

简单表达式计算实用类 支持的运算如表所示 运算符号释义例子加法1024512-减法1024-512*乘法1024*1024/除法1024/128^平方1024^2%取模(求余数)10%3(优先级左括号(1024512)*8)优先级右括号(1024512)*8 表达式示例: 表达式有效性备注2(2-7)*2*(8-2)/2有效1024^3有效1024的3次方…

头像空白问题

当用户没有设置头像时&#xff0c;我们可以使用用户名第一个字来当头像 主要涉及一个截取&#xff0c;截取字符串第一个字 变量名.charAt(0) 如果变量名为null或者undefine 那么就会报错 使用可选链操作符 &#xff1f; 当前面的值为nul或undefine时&#xff0c;就不会执行…

CSS||选择器

目录 作用 分类 基础选择器 标签选择器 ​编辑类选择器 id选择器 通配符选择器 作用 选择器&#xff08;选择符&#xff09;就是根据不同需求把不同的标签选出来这就是选择器的作用。 简单来说&#xff0c;就是选择标签用的。 选择器的使用一共分为两步&#xff1a; 1.…

代码随想录算法训练营第23天 | 669. 修剪二叉搜索树 + 108.将有序数组转换为二叉搜索树 + 538.把二叉搜索树转换为累加树

今日任务 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结篇 669. 修剪二叉搜索树 - Medium 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你二叉搜索树的根节点 root &#xf…

代码随想录算法训练营29期|day 22 任务以及具体安排

235. 二叉搜索树的最近公共祖先 class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root null) return null;//向左遍历if(root.val > p.val && root.val > q.val){TreeNode left lowestCommonAncestor(roo…

MySQL表的基本插入查询操作详解

博学而笃志&#xff0c;切问而近思 文章目录 插入插入更新 替换查询全列查询指定列查询查询字段为表达式查询结果指定别名查询结果去重 WHERE 条件基本比较逻辑运算符使用LIKE进行模糊匹配使用IN进行多个值匹配 排序筛选分页结果更新数据删除数据截断表聚合函数COUNTSUMAVGMAXM…

C语言——atoi函数解析

目录 前言 atoi函数的介绍 atoi函数的使用 atoi函数的模拟实现 前言 对于atoi函数大家可能会有些陌生&#xff0c;不过当你选择并阅读到这里时&#xff0c;请往下阅读&#xff0c;我相信你能对atoi函数熟悉该函数的头文件为<stdlib.h> 或 <cstdlib> atoi函数的…

被遗忘在角落的RPA,成了提升AI Agent执行能力的天选神器

LLM&#xff08;Large Language Models&#xff09;刚爆发之时&#xff0c;很多人认为RPA要完了&#xff0c;自然语言交互API操作足以干掉任何UI自动化工具。 然而&#xff0c;大语言模型应用发展到AI Agent这一步&#xff0c;大家才发现API并不是万能的。Agent平台雨后春笋一…

【开源项目】经典开源项目实景三维数字孪生泰山

飞渡科技数字孪生文旅运营中心&#xff0c;基于文旅单位的运营管理、服务质量以及游客需求&#xff0c;通过数字孪生、AR/VR、大数据分析等技术&#xff0c;为景区打造虚实融合、超沉浸体验的专属虚拟数字场景&#xff0c;实现文旅领域的数据可视化、产业数字化以及智能化管理。…

Django Web开发(day4)——数据模型使用与填充网站数据(对数据库的基本操作)

本博客将会涉及: Django 数据模型的使用视频数据的导入admin 后台的使用 1、Django 数据模型的使用 在上一篇中完成了网站的数据模型的创建,在数据模型创建之后,Django 会为我们的数据模型创建一套数据库抽象的 API 接口,以供我们进行检索数据、创建数据、更新和修改数据…

vim 编辑器如何同时注释多行以及将多行进行空格

当然可以&#xff0c;以下是我对您的文字进行润色后的版本&#xff1a; 一、场景 YAML文件对空格的要求非常严格&#xff0c;因此在修改YAML时&#xff0c;我们可能需要批量添加空格。 二、操作步骤 请注意&#xff1a;您的所有操作都将以第一行为基准。也就是说&#xff0…

滚动菜单ListView

activity_main.xml <include layout"layout/title"/> 引用上章自定义标题栏 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app&qu…

BigeMap在Unity3d中的应用,助力数字孪生

1. 首先需要用到3个软件&#xff0c;unity&#xff0c;gis office 和 bigemap离线服务器 Unity下载地址:点击前往下载页面(Unity需要 Unity 2021.3.2f1之后的版本) Gis office下载地址:点击前往下载页面 Bigemap离线服务器 下载地址: 点击前往下载页面 Unity用于数字孪生项…

计算机系统基础知识揭秘:硬件、处理器和校验码

计算机系统基础知识揭秘&#xff1a;硬件、处理器和校验码 一、计算机系统基础知识的重要性二、计算机系统硬件2.1、内存和存储设备2.2、输入输出设备 三、中央处理器&#xff08;CPU&#xff09;3.1、运算器3.2、控制器3.3、寄存器组3.4、多核CPU 四、数据表示4.1、原码、反码…

前端项目配置 Dockerfile 打包后镜像部署无法访问

Dockerfile 配置如下&#xff1a; FROM node:lts-alpineWORKDIR /app COPY . . RUN npm install RUN npm run buildEXPOSE 3001CMD ["npm", "run", "preview"]构建镜像 docker build -t vite-clarity-project .启动镜像容器 docker run -p 30…

《C++入门篇》——弥补C不足

文章目录 前言一.命名空间二.缺省参数三.函数重载四.引用4.1引用做参数4.2引用做返回值 五.内联函数六.小语法6.1auto6.2范围for6.3空指针 前言 C是业内一门久负盛名的计算机语言&#xff0c;从C语言发展起来的它&#xff0c;不仅支持C语言的语法&#xff0c;还新添加了面向对…

MySQL之视图索引

学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept) 学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键 课程表&#xff1a;Course (Cno, Cname,) 课程号&#xff0c;课程名 Cno为主键 学生选课表&#xff1a;SC (Sno, Cno, Score)…

华为设备NAT的配置

实现内网外网地址转换 静态转换 AR1&#xff1a; sys int g0/0/0 ip add 192.168.10.254 24 int g0/0/1 ip add 22.33.44.55 24 //静态转换 nat static global 22.33.44.56 inside 192.168.10.1 动态转换 最多有两台主机同时访问外网 AR1&#xff1a; sys int g0/0/0 ip add…

C语言之【函数】篇章以及例题分析

文章目录 前言一、函数是什么&#xff1f;二、C语言中函数的分类1、库函数2、自定义函数 三、函数的参数1、实际参数&#xff08;实参&#xff09;2、形式参数&#xff08;形参&#xff09; 四、函数的调用1、传值调用2、传址调用3、专项练习3.1 素数判断3.2 闰年判断3.3 二分查…
最新文章