本脚手架包含模块:

  1. 用户登录模块

  2. jwt权限模块

  3. 用户管理模块

建表语句

操作日志表

DROP TABLE IF EXISTS `user_operate_log`;
CREATE TABLE `user_operate_log` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` varchar(800) DEFAULT NULL,
  `user_name` varchar(800) DEFAULT NULL,
  `current_page` varchar(800) DEFAULT NULL,
  `current_operate` varchar(800) DEFAULT NULL,
  `create_time` datetime(6) NOT NULL,
  `modify_time` datetime(6) NOT NULL,
  `is_delete` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3079 DEFAULT CHARSET=utf8mb3;

用户表

DROP TABLE IF EXISTS `user_data`;
CREATE TABLE `user_data` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` varchar(800) DEFAULT NULL,
  `user_name` varchar(800) DEFAULT NULL,
  `user_permission` varchar(800) DEFAULT NULL,
  `user_extension` varchar(800) DEFAULT NULL,
  `operator_id` varchar(800) DEFAULT NULL,
  `create_time` datetime(6) NOT NULL,
  `modify_time` datetime(6) NOT NULL,
  `is_delete` tinyint(1) NOT NULL,
  `user_password` varchar(1200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb3;

python核心代码

scaffolding app

settings.py

"""
Django settings for scaffolding project.

Generated by 'django-admin startproject' using Django 4.0.5.

For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
import os
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-#inhh^g7&9s5riqhbw*7zxft%)+&-*($tg9n%4nmnuov8^z^(o'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*', '0.0.0.0']

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'index.apps.IndexConfig',
    'user.apps.UserConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'scaffolding.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.i18n',
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'scaffolding.wsgi.application'

# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases

DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': BASE_DIR / 'db.sqlite3',
    # },
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
        'NAME': 'WORKSTATION',  # 你要存储数据的库名,创建的数据库mydb
        'USER': 'root',  # 数据库用户名,默认为root
        'PASSWORD': '123456',  # 密码,安装mysql时设定
        'HOST': '10.175.94.80',  # 主机
        'PORT': '7000',  # 数据库使用的端口
        'charset': 'utf8',
    }
}

# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True

LANGUAGES = (
    ('en-us', 'English'),
    ('zh-hans', '中文简体'),
    ('zh-hant', '中文繁体')
)

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/

STATIC_URL = 'static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
SILENCED_SYSTEM_CHECKS = ['mysql.W003']

# 日志
LOGGING = {
    'version': 1,  # 版本
    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器
    'formatters': {  # 日志信息显示的格式
        'verbose': {  # 详细
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {  # 简单
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(BASE_DIR, "log/all.log"),  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    }
}

# 设置为 True 来防止通过 JavaScript 访问存储数据。
SESSION_COOKIE_HTTPONLY = True

urls.py

from django.urls import path

from . import views

from django.conf.urls.static import static
from django.conf import settings
# from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt

app_name = 'index'
urlpatterns = [
    path(r'index/', views.index, name='index'),
]

__init__.py

import pymysql
pymysql.install_as_MySQLdb()

index app

urls.py

from django.urls import path

from . import views

from django.conf.urls.static import static
from django.conf import settings
# from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt

app_name = 'index'
urlpatterns = [
    path(r'index/', views.index, name='index'),
]

views.py

from django.shortcuts import render

# Create your views here.
from user.views import check_cookie_user_id


@check_cookie_user_id
def index(request):
    return render(request, "index.html")

user app

__init__.py

import pymysql
pymysql.install_as_MySQLdb()

models.py

from django.db import models


# Create your models here.
class User_Data(models.Model):
    # id
    id = models.AutoField(primary_key=True, unique=True, verbose_name='id')
    user_id = models.CharField(max_length=800, null=True, verbose_name='用户id')
    user_password = models.CharField(max_length=1200, null=True, verbose_name='用户密碼')
    user_name = models.CharField(max_length=800, null=True, verbose_name='用户姓名')
    user_permission = models.CharField(max_length=800, null=True, verbose_name='用户权限')
    user_extension = models.CharField(max_length=800, null=True, verbose_name='用户分机')
    operator_id = models.CharField(max_length=800, null=True, verbose_name='操作人工号')
    # 创建时间
    create_time = models.DateTimeField(auto_now_add=True)
    # 修改时间
    modify_time = models.DateTimeField(auto_now=True)
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    objects = models.Manager()

    class Meta:
        db_table = 'user_data'
        verbose_name = '用户管理'

    def __str__(self):
        return self.user_id


class User_Operate_Log(models.Model):
    # id
    id = models.AutoField(primary_key=True, unique=True, verbose_name='id')
    user_id = models.CharField(max_length=800, null=True, verbose_name='用户id')
    user_name = models.CharField(max_length=800, null=True, verbose_name='用户姓名')
    current_page = models.CharField(max_length=800, null=True, verbose_name='當前頁面')
    current_operate = models.CharField(max_length=800, null=True, verbose_name='當前操作')
    # 创建时间
    create_time = models.DateTimeField(auto_now_add=True)
    # 修改时间
    modify_time = models.DateTimeField(auto_now=True)
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    objects = models.Manager()

    class Meta:
        db_table = 'user_operate_log'
        verbose_name = '用户操作記錄表'

    def __str__(self):
        return self.user_id

Authority.py

from user.Jwt import Jwt
from .models import User_Data

# 白名单
white_list = ['F1237077']


class Authority:
    @staticmethod
    def get_auth(token):
        """
        获取当前登录操作者的工号和权限等级
        return user_id 工号 auth 权限登记
        """
        user_auth_dic = {"op": 1, "engineer": 2, "dri": 3, "manager": 4, "superuser": 5}
        result = Jwt.decode(token, "1234567")
        # 当前用户
        user_id = result['user_id']
        auth = user_auth_dic[result['authority']]
        return user_id, auth

    @staticmethod
    def get_update_user_auth(user_id):
        """
        通过工号获取用户权限等级
        """
        user_auth_dic = {"op": 1, "engineer": 2, "dri": 3, "manager": 4, "superuser": 5}
        user = User_Data.objects.get(user_id=user_id)
        auth = user_auth_dic[user.user_permission]
        return auth

    @staticmethod
    def get_white_list():
        """
        获取白名单列表
        """
        return white_list

forms.py

from django import forms


class UserLoginForm(forms.Form):
    username = forms.CharField(required=True, error_messages={
        'required': '账号必须填写',
    })
    password = forms.CharField(required=True, min_length=3, max_length=100, error_messages={
        'required': '密码必须填写',
        'min_length': '密码至少3位',
        'max_length': '密码不能超过100位'
    })

Jwt.py

import base64
import hmac
import time
import json
import copy


class Jwt:
    @staticmethod  # 静态方法的装饰器封装一下  专门负责做计算用的函数
    def encode(self_payload, key, exp=300):
        # self_payload  含有私有声明的字典
        # key 自定的key
        # exp 过期时间

        # 生成header
        header = {'typ': 'JWT', 'alg': 'HS256'}
        # header_json = json.dumps(header)  # 这样转为json串不行,有空格,损耗带宽
        header_json = json.dumps(header, separators=(',', ':'), sort_keys=True)
        # 这样逗号冒号前后就没有空格了,sort_keys=True 使出来的json串变的有序了,在做hmac或其他哈希的计算的时候,串值一定是稳定的
        # separators分割符 第一个参数代表的是每个键值对之间用什么分割,第二个参数是每个键和值之间用什么分割
        # sort_keys 生成有序的json串
        header_json_base64 = Jwt.b64encode(header_json.encode())

        # init payload
        self_payload_copy = copy.deepcopy(self_payload)  # 为了不污染传进来的字典
        # 给拷贝出来的字典中加入公有声明
        self_payload_copy["exp"] = time.time() + exp  # 过期时间
        self_payload_copy_json = json.dumps(self_payload_copy, separators=(',', ':'), sort_keys=True)
        self_payload_copy_json_base64 = Jwt.b64encode(self_payload_copy_json.encode())

        # init sign
        hm = hmac.new(key.encode(), header_json_base64 + b'.' + self_payload_copy_json_base64,
                      digestmod="SHA256")  # 两个都是字节码所以连接符*点*也要是字节码
        hm_base64 = Jwt.b64encode(hm.digest())  # 取hm的二进制结果,然后进行base64的转码

        # jwt token 诞生  字节码
        token = header_json_base64 + b'.' + self_payload_copy_json_base64 + b'.' + hm_base64
        return token.decode('utf-8')

    @staticmethod
    def b64encode(js):  # 为了将base64转换修改为urlsafe
        return base64.urlsafe_b64encode(js).replace(b"=", b"")

    @staticmethod
    def b64decode(bs):
        # 加回来等号
        rem = len(bs) % 4  # 取余
        if rem > 0:
            bs += b'=' * (4 - rem)

        return base64.urlsafe_b64decode(bs)

    @staticmethod
    def decode(token, key):
        # 返回结果
        result = {}
        try:
            # 传入jwt的值(令牌) 和只有调用者知道的key
            # 校验签名
            token = token.encode('utf-8')
            header_bs, payload_bs, signature_bs = token.split(b".")  # 因为是字节串
            hm = hmac.new(key.encode(), header_bs + b"." + payload_bs, digestmod="SHA256")
            if signature_bs != Jwt.b64encode(hm.digest()):  # 将签名结果和传过来的sign进行对比
                result['user_id'] = ' '
                result['message'] = '非法token'
                return result

            # 校验时间
            payload_js = Jwt.b64decode(payload_bs)  # 解码为json
            payload = json.loads(payload_js)  # 解码为字典

            now = time.time()  # 当前时间
            if int(now) > int(payload["exp"]):  # 登录时间过期
                result['user_id'] = ' '
                result['message'] = '登錄超時'
                return result
            result['user_id'] = payload['user_id']
            result['user_name'] = payload['user_name']
            result['authority'] = payload['authority']
            result['message'] = '登錄成功'
            return result  # 返回自定义内容
        except Exception as e:
            print(e)
            result['user_id'] = ' '
            result['user_name'] = ' '
            result['authority'] = ' '
            result['message'] = '非法token'
            return result


if __name__ == '__main__':
    # 测试
    s = Jwt.encode({"user_id": "F1238775","user_name": "魏华川"}, "1234567", 24*60*60)  # 制作令牌
    print(s)
    print(Jwt.decode(s, "1234567"))  # 校验令牌 返回payload明文 字典类型

UserChangeRecord.py

from user.models import *


class UserChangeRecord:
    @staticmethod
    def record(user_id, page_name, operation):
        """
        param: user_id 操作人工号
               page_name 当前页面名称
               operateion 当前操作
        """
        user_name = User_Data.objects.get(user_id=user_id).user_name
        User_Operate_Log.objects.create(
            user_id=user_id,
            user_name=user_name,
            current_page=page_name,
            current_operate=operation
        )

urls.py

from django.urls import path

from . import views
from user.views import *
app_name = 'user'
urlpatterns = [
    # 维护页面 维护的时候开启
    # path(r'', views.maintain, name='maintain'),
    path(r'login/', UserLoginView.as_view(), name='login'),
    path(r'logout/', views.logout, name='logout'),
    path(r'user_manage/', views.user_manage, name='user_manage'),  # 用户管理主界面
    path(r'find_user_detail/', views.find_user_detail, name='find_user_detail'),  # 通过工号查询用户信息
    path(r'add_or_update_user/', views.add_or_update_user, name='add_or_update_user'),  # 新增或者修改用户信息
    path(r'delete_user/', views.delete_user, name='delete_user'),  # 删除用户信息
]

views.py

import json
import logging
from datetime import datetime

from django.db.models import Q
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render, redirect, reverse

# Create your views here.
from django.views import View
from django.views.decorators.csrf import csrf_exempt

from user.Authority import Authority
from user.Jwt import Jwt
from user.UserChangeRecord import UserChangeRecord
from user.forms import UserLoginForm
from user.models import User_Data
logger = logging.getLogger(__name__)
user_auth_dic = {"op": 1, "engineer": 2, "dri": 3, "manager": 4, "superuser": 5}


def check_cookie_user_id(fun):
    """
    装饰器函数,用于检查当前用户的登陆状态
    """

    def check(*args, **kwargs):
        try:
            token = args[0].COOKIES.get('token', '')
        except AttributeError:
            token = args[1].COOKIES.get('token', '')
        result = Jwt.decode(token, "1234567")
        if result['user_id'] == ' ':
            # context = {'msg': '用户登陆已经过期,请重新登陆'}
            return redirect(reverse('user:login'))
        res = fun(*args, **kwargs)
        return res

    return check


class UserLoginView(View):
    @staticmethod
    def get(request):
        """显示登录页面"""
        # 判断是否记住了用户名
        log_year = datetime.today().year
        if 'username' in request.COOKIES:
            username = request.COOKIES.get('username')
            password = request.COOKIES.get('password')
            checked = 'checked'
        else:
            username, password, checked = '', '', ''
        return render(request, 'login.html', {
            'username': username, 'checked': checked, 'password': password, 'log_year': log_year
        })

    @csrf_exempt
    def post(self, request):
        user_login_form = UserLoginForm(request.POST)
        if user_login_form.is_valid():
            user_id = user_login_form.cleaned_data['username']
            user_password = user_login_form.cleaned_data['password']
            context = {"status": 0, "msg": ''}
            obj = User_Data.objects.filter(user_id=user_id, user_password=user_password, is_delete=False).first()
            if obj:
                context['status'] = 1
                token = Jwt.encode({"user_id": user_id, "user_name": obj.user_name, "authority": obj.user_permission},
                                   "1234567", 12 * 3600)  # 制作令牌
                # 默认跳转到首页
                next_url = request.GET.get('next', reverse('user:user_manage'))
                # 跳转到next_url
                ret = redirect(next_url)
                ret.set_cookie('token', token, 12 * 3600)
                return ret
            else:
                context['msg'] = '账号或密码错误,请重新输入'
                return render(request, 'login.html', context)
        else:
            return render(request, 'login.html', {
                'user_login_form': user_login_form
            })


@check_cookie_user_id
def logout(request):
    response = HttpResponseRedirect('/user/login/')
    response.delete_cookie('token')
    return response


@check_cookie_user_id
def user_manage(request):
    """
    param keyword
    返回用户管理界面所有用户的数据
    return context
    """
    context = {}
    # 获取前端传过来的keyword
    keyword = request.GET.get('keyword', '')
    user_data = User_Data.objects.filter(is_delete__exact=False)
    # 获取页面用户信息头数据
    comment_data = get_user_page_head(request)
    if keyword == '':
        context['user_data'] = user_data
        context['keyword'] = keyword
    else:
        user_data_filter = user_data.filter(Q(user_id__contains=keyword) | Q(user_name__contains=keyword) |
                                            Q(user_permission__contains=keyword) | Q(user_extension__contains=keyword))
        context['user_data'] = user_data_filter
        context['keyword'] = keyword
    context['comment_data'] = comment_data
    return render(request, 'user_manage.html', context)


def get_user_page_head(request):
    token = request.COOKIES.get('token', '')
    result = Jwt.decode(token, "1234567")
    result['datetime'] = datetime.now().strftime("%Y-%m-%d")
    # 将权限名称分级
    result['authority'] = user_auth_dic[result['authority']]
    return result


@csrf_exempt
def find_user_detail(request):
    """
    param: user_id
    获取用户的个人信息
    reusrn context dict
    """
    context = {'status': 0, 'msg': "查询失败", 'data': {}}
    if request.method == "POST":
        user_id = request.POST.get('user_id', '')
        if user_id == '':
            return context
        else:
            user_dict = get_user_data(user_id)
            context['data'] = user_dict
            context['status'] = 1
            context['msg'] = ""
            return JsonResponse(context)


def get_user_data(user_id):
    """
    通过user_id 从数据库查数据返回
    return user_dict
    """
    user_dict = {}
    try:
        user = User_Data.objects.get(user_id=user_id)
        user_dict["user_name"] = user.user_name
        user_dict["user_id"] = user.user_id
        user_dict["password"] = user.user_password
        user_dict["permission"] = user.user_permission
        user_dict["phone"] = user.user_extension
    except Exception as e:
        logger.error(e)
    return user_dict


@csrf_exempt
def add_or_update_user(request):
    """
    param: user_data
    修改或者新增用户
    return context dict
    """
    context = {'status': 0, 'msg': "操作失敗"}
    if request.method == "POST":
        try:
            # 获取当前用户的token
            token = request.COOKIES.get('token', '')
            # 获取当前用户的工号和权限等级
            operator_id, operator_auth = Authority.get_auth(token)
            # 获取前端操作标识
            flag = request.POST.get('flag')
            # 获取前端要跟新用户的数据
            user_data = json.loads(request.POST.get('data'))
            # todo 判空
            context = is_blank(user_data)
            if context['status'] == 0:
                return JsonResponse(context)
            if flag == 'update':
                context = update_user(user_data, operator_id, operator_auth)
            elif flag == 'add':
                context = add_user(user_data, operator_id, operator_auth)
        except Exception as e:
            logger.error(e)
        return JsonResponse(context)


def update_user(user_data, operator_id, operator_auth):
    user_id = user_data['user_id']
    try:
        # todo 校验
        user_auth = Authority.get_update_user_auth(user_id)
        # 要赋予的权限
        to_auth = user_auth_dic[user_data['authority']]
        flag = is_authority(operator_auth, user_id, user_auth, to_auth)
        if flag:
            user = User_Data.objects.get(user_id=user_data['user_id'])
            user.user_id = user_data['user_id']
            user.user_name = user_data['user_name']
            user.user_permission = user_data['authority']
            user.user_extension = user_data['phone']
            user.user_password = user_data['password']
            user.save()
            UserChangeRecord.record(operator_id, "用户管理界面", "修改%s成功" % user_id)
            context = {'status': 1, 'msg': "修改人員成功"}
        else:
            UserChangeRecord.record(operator_id, "用户管理界面", "修改%s失败" % user_id)
            context = {'status': 0, 'msg': "無權限修改"}
    except Exception as e:
        UserChangeRecord.record(operator_id, "用户管理界面", "修改%s失败" % user_id)
        logger.error(e)
        context = {'status': 0, 'msg': "修改人員失敗"}
    return context


def add_user(user_data, operator_id, operator_auth):
    context = {'status': 0, 'msg': "新增人員失敗"}
    user_id = user_data['user_id']
    user_auth = user_auth_dic[user_data['authority']]
    try:
        # todo 权限校验
        flag = is_authority(operator_auth, user_id, user_auth)
        if flag:
            # 判断要创建的人是否存在
            user = User_Data.objects.filter(user_id=user_data['user_id']).first()
            if user:
                if user.is_delete is True:
                    user.is_delete = False
                    user.user_id = user_data['user_id']
                    user.user_name = user_data['user_name']
                    user.user_permission = user_data['authority']
                    user.user_extension = user_data['phone']
                    user.user_password = user_data['password']
                    user.save()
                    UserChangeRecord.record(operator_id, "用户管理界面", "新增%s成功" % user_id)
                    context = {'status': 1, 'msg': "新增人員成功"}
                else:
                    context['msg'] = "用户已经存在"
            else:
                User_Data.objects.create(
                    user_id=user_data['user_id'],
                    user_name=user_data['user_name'],
                    user_permission=user_data['authority'],
                    user_extension=user_data['phone'],
                    user_password=user_data['password'],
                    operator_id=operator_id
                )
                UserChangeRecord.record(operator_id, "用户管理界面", "新增%s成功" % user_id)
                context = {'status': 1, 'msg': "新增人員成功"}
        else:
            UserChangeRecord.record(operator_id, "用户管理界面", "新增%s失败" % user_id)
            context = {'status': 0, 'msg': "無權限新增"}
    except Exception as e:
        UserChangeRecord.record(operator_id, "用户管理界面", "新增%s失败" % user_id)
        logger.error(e)
        context = {'status': 0, 'msg': "新增人員失敗"}
    return context


@csrf_exempt
def delete_user(request):
    """
    param: user_id
    删除用户 (假删除 其数据会在数据库中保存)
    return context dict
    """
    context = {'status': 0, 'msg': "刪除人員失敗"}
    if request.method == "POST":
        try:
            # 获取当前用户的token
            token = request.COOKIES.get('token', '')
            # 获取当前用户的工号和权限等级
            operator_id, operator_auth = Authority.get_auth(token)
            # 获取要删除人的工号
            user_id = request.POST.get('user_id')
            context = del_user(user_id, operator_id, operator_auth)
        except Exception as e:
            logger.error(e)
        return JsonResponse(context)


def del_user(user_id, operator_id, operator_auth):
    """
    删除用户数据库操作
    param: user_id被删除人工号 operator_id 操作人工号 operator_auth 操作人权限
    return: dict 状态码 和 信息
    """
    try:
        # todo 权限校验
        user_auth = Authority.get_update_user_auth(user_id)
        # 要赋予的权限 这里无意义
        # to_auth = Authority.get_update_user_auth(user_id)
        flag = is_authority(operator_auth, user_id, user_auth)
        if flag:
            # 删除用户 标记删除
            user = User_Data.objects.get(user_id=user_id)
            user.is_delete = True
            user.operator_id = operator_id
            user.save()
            UserChangeRecord.record(operator_id, "用户管理界面", '删除%s成功' % user_id)
            context = {'status': 1, 'msg': "刪除人員成功"}
        else:
            UserChangeRecord.record(operator_id, "用户管理界面", '删除%s失败' % user_id)
            context = {'status': 0, 'msg': "無權限刪除"}
    except Exception as e:
        UserChangeRecord.record(operator_id, "用户管理界面", '删除%s失败' % user_id)
        logger.error(e)
        context = {'status': 0, 'msg': "刪除人員失敗"}
    return context


def is_authority(operator_auth, user_id, user_auth, to_auth=0):
    """
    判断操作人是否有权限操作被操作人
    param: operator_auth, user_auth,user_id  操作者权限、被操作者权限、被操作人id
    return boolean
    """
    if user_id in Authority.get_white_list():
        return False
    if operator_auth == 5:
        return True
    elif operator_auth == 3 or operator_auth == 4:
        if operator_auth > user_auth and operator_auth > to_auth:
            return True
        else:
            return False
    else:
        return False


def is_blank(user_data):
    context = {'status': 1, 'msg': ""}
    if user_data['user_name'] == '':
        context['status'] = 0
        context['msg'] = '姓名不能為空!'
        return context
    if user_data['user_id'] == '':
        context['status'] = 0
        context['msg'] = '工號不能為空!'
        return context
    if user_data['authority'] is None or user_data['authority'] == '':
        context['status'] = 0
        context['msg'] = '權限不能為空!'
        return context
    if user_data['password'] == '':
        context['status'] = 0
        context['msg'] = '密碼不能為空!'
        return context
    return context


def edit_token(request, auth):
    # 获取token信息
    token = request.COOKIES.get('token', '')
    result = Jwt.decode(token, "1234567")
    token = Jwt.encode({"user_id": result['user_id'], "user_name": result['user_name'], "authority": auth},
                       "1234567", 12 * 3600)  # 制作令牌
    return token

HTML

login.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    {% load static %}
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <link rel="shortcut icon" href="{% static 'img/eerf_logo_blue.svg' %}">
    <link rel="stylesheet" href="{% static 'css/ITSS.css' %}">
</head>
<body>
    <div class="login_background">
        <div class="locating_platform">
            <div id="login_main_box">
                <!-- 登录框装饰 -->
                <div class="department_logo">
                    <div class="logo"></div>
                    <div class="name"></div>
                </div>
                <div class="illustration"></div>
                <div class="img_left_1"></div>
                <div class="img_left_2"></div>
                <div class="img_right_1"></div>
                <!-- 登录框主体 -->
                <div class="login_box">
                    <form action="{% url 'user:login' %}" method="post" autocomplete="off">
                        {% csrf_token %}
                        <div class="login_title"></div>
                        <div class="message">{{ msg }}</div>
                        <div class="username_box">
                            <div id="icon_user"></div>
                            <input id="username" type="text" placeholder="請輸入您的賬號" name='username'>
                        </div>
                        <div class="password_box">
                            <div id="icon_pass"></div>
                            <input id="password" type="password" placeholder="請輸入您的密碼" name="password">
                        </div>
                        <button class="login">登錄</button>
                        <div class="department_describe">( FATP-DATA  &  FATP-CoEx )</div>
                    </form>
                </div>
            </div>
        </div>
    </div>
{#    <script src="../static/js/jquery-3.6.0.min.js"></script>#}
{#    <script src="../static/js/login.js"></script>#}
    <script src="{% static '/js/jquery-3.6.0.min.js' %}"></script>
    <script src="{% static '/js/class_all.js' %}"></script>
    <script src="{% static '/js/login.js' %}"></script>
</body>
</html>

index.html

<!DOCTYPE html>
<html>
{% load static %}
<head>
    <title>index</title>
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    <link rel="stylesheet" type="text/css" href="{% static 'css/index.css' %}">
</head>

<body>
    <div class="main">
        <div class="first">
            <span class="Check_time">Check_time</span>
            <input class="input" id="Check_time" >
        </div>
        <div class="second">
            <span class="Work_time">Work_time</span>
            <input class="input" id="Work_time" >
        </div>
        <div class="third">
            <span class="Add_SN">Add_SN</span>
            <input class="input" id="Add_SN" >
            <button value="新增" class="add">新增</button>
        </div>
        <div class="forth">
            <span class="Del_SN">Del_SN</span>
            <input class="input" id="Del_SN">
            <button value="删除" class="remove">删除</button>
        </div>
        <div class="fifth">
            <textarea type="text" class="result"></textarea>
        </div>
    </div>
    
</body>
</body>


<script src="{% static 'js/index.js' %}"></script>
</html>

user_manager.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    {% load static %}
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <link rel="shortcut icon" href="{% static 'img/eerf_logo_blue.svg' %}">
    <link rel="stylesheet" href="{% static 'css/ITSS.css' %}">
</head>
<body>
<div class="main_background">
    <div id="head_nav">
        <div id="head_user_date_info">
            <div class="userinfo_group">
                <div class="user_portrait"></div>
                <div class="user_info">
                    <div class="user_name" id="head_user_name">谢宇豪豪</div>
                    <div class="user_id" id="head_user_id">F1230313</div>
                </div>
                <div class="log_out"></div>
            </div>
            <div class="dateinfo">
                <div class="date_title">TODAY</div>
                <div class="date">2022-12-31</div>
            </div>
            <div id="show_current_time" class="show_time"></div>
        </div>
    </div>
    <div id="column_nav">
        <div class="nav_title"></div>
        <div class="nav_group">
            <a href="{% url 'user:user_manage' %}" class="nav_item activate">
                <div class="nav_ico user_manage"></div>
                <div class="nav_name">用户管理</div>
            </a>
        </div>
    </div>
    <div id="main_area">
        <div class="function_select">
            {% if comment_data.authority == 3 or comment_data.authority == 5 or comment_data.authority == 4 %}
                <div class="function_button_group">
                    <button onclick="show_pop_div('user_add')">新增</button>
                </div>
            {% else %}
                <div></div>
            {% endif %}

            <div id="search_mod">
                <span class="icon"></span>
                <input id="search_input" type="text" placeholder="search" maxlength="50"
                       {% if keyword != '' %}value={{ keyword }}{% endif %}>
                <div class="search" id="btn_search">搜索</div>
            </div>
        </div>
        <div id="user_manage_table" class="table_show activate">
            <div class="table_head">
                <table>
                    <thead>
                    <tr>
                        <th width="1%">姓名</th>
                        <th width="1%">工號</th>
                        <th width="1%">權限類別</th>
                        <th width="1%">分機</th>
                        {% if comment_data.authority == 3 or comment_data.authority == 5 or comment_data.authority == 4 %}
                            <th width="1%">操作</th>
                        {% endif %}
                    </tr>
                    </thead>
                </table>
            </div>
            <div class="table_body scrollbar_style_1">
                <table>
                    <tbody>
                    {% for user in user_data %}
                        <tr>
                            <td width="1%">{{ user.user_name }}</td>
                            <td class="tb_user_id" width="1%">{{ user.user_id }}</td>
                            <td width="1%">{{ user.user_permission }}</td>
                            <td width="1%">{{ user.user_extension }}</td>
                            {% if comment_data.authority == 3 or comment_data.authority == 5 or comment_data.authority == 4 %}
                                <td width="1%">
                                    <div class="table_function">
                                        <div class="edit" onclick="edit(this)">
                                            <span class="icon"></span>
                                            <span class="text">修改</span>
                                        </div>
                                        <div class="delete" onclick="del(this)">
                                            <span class="icon"></span>
                                            <span class="text">刪除</span>
                                        </div>
                                    </div>
                                </td>
                            {% endif %}

                        </tr>
                    {% endfor %}
                    {#                    <tr>#}
                    {#                        <td width="1%">李可愛</td>#}
                    {#                        <td width="1%">F1231527</td>#}
                    {#                        <td width="1%">user</td>#}
                    {#                        <td width="1%">955668</td>#}
                    {#                        <td width="1%">#}
                    {#                            <div class="table_function">#}
                    {#                                <div class="edit" onclick="show_pop_div('user_edit')">#}
                    {#                                    <span class="icon"></span>#}
                    {#                                    <span class="text">修改</span>#}
                    {#                                </div>#}
                    {#                                <div class="delete" onclick="show_pop_div('user_delete')">#}
                    {#                                    <span class="icon"></span>#}
                    {#                                    <span class="text">刪除</span>#}
                    {#                                </div>#}
                    {#                            </div>#}
                    {#                        </td>#}
                    {#                    </tr>#}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>
<!-- 模态框 -->
<div id="user_add" class="modal user_add_edit">
    <div class="modal_close" onclick="close_add_div()"></div>
    <div class="modal_title">人員新增</div>
    <form>
        <div class="user_name_group">
            <label for="add_user_name">姓名:</label>
            <input id="add_user_name" type="text" name="user_name">
        </div>
        <div class="user_id_group">
            <label for="add_user_id">工號:</label>
            <input id="add_user_id" type="text" name="user_id">
        </div>
        <div class="phone_num_group">
            <label for="add_phone_num">分機:</label>
            <input id="add_phone_num" type="text" name="phone_num">
        </div>
        <div class="user_password_group">
            <label for="add_user_password">密碼:</label>
            <input id="add_user_password" type="text" name="user_password">
        </div>
        <div class="authority_group">
            <label for="add_authority">權限:</label>
            <select id="add_authority" name="authority">
                {% if comment_data.authority == 3 %}
                    <option value="op" selected="selected">op</option>
                    <option value="engineer">engineer</option>
                {% elif comment_data.authority == 4 %}
                    <option value="op" selected="selected">op</option>
                    <option value="engineer">engineer</option>
                    <option value="dri">dri</option>
                {% elif comment_data.authority == 5 %}
                    <option value="op" selected="selected">op</option>
                    <option value="engineer">engineer</option>
                    <option value="dri">dri</option>
                    <option value="manager">manager</option>
                    <option value="superuser">superuser</option>
                {% endif %}
            </select>
        </div>
        <div class="message" id="add_message"></div>
        <div class="button_group">
            <button type="button" onclick="close_add_div()">取消</button>
            <button class="confirm" type="submit">确定</button>
        </div>
    </form>
</div>
<div id="user_edit" class="modal user_add_edit">
    <div class="modal_close" onclick="close_pop_div('user_edit')"></div>
    <div class="modal_title">人員修改</div>
    <form>
        <div class="user_name_group">
            <label for="edit_user_name">姓名:</label>
            <input id="edit_user_name" type="text" name="user_name">
        </div>
        <div class="user_id_group">
            <label for="edit_user_id">工號:</label>
            <input id="edit_user_id" type="text" name="user_id">
        </div>
        <div class="phone_num_group">
            <label for="edit_phone_num">分機:</label>
            <input id="edit_phone_num" type="text" name="phone_num">
        </div>
        <div class="user_password_group">
            <label for="edit_user_password">密碼:</label>
            <input id="edit_user_password" type="text" name="user_password">
        </div>
        <div class="authority_group">
            <label for="edit_authority">權限:</label>
            <select id="edit_authority" name="authority">
                <option value="op">op</option>
                <option value="engineer">engineer</option>
                <option value="dri">dri</option>
                <option value="manager">manager</option>
                <option value="superuser">superuser</option>
            </select>
        </div>
        <div class="message" id="edit_message"></div>
        <div class="button_group">
            <button type="button" onclick="close_pop_div('user_edit')">取消</button>
            <button class="confirm" type="submit">确定</button>
        </div>
    </form>
</div>
<div id="user_delete" class="modal reconfirm_popup">
    <div class="modal_close" onclick="close_pop_div('user_delete')"></div>
    <div class="confirm_content">
        <div class="message" id="del_message">提示信息提示信息提示信息提示信息</div>
        <div class="button_group">
            <button type="button" onclick="close_pop_div('user_delete')">取消</button>
            <button class="confirm" type="button" id="del_btn">确定</button>
        </div>
    </div>
</div>
<script src="{% static '/js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static '/js/jquery.cookie.min.js' %}"></script>
<script src="{% static '/js/class_all.js' %}"></script>
<script src="{% static '/js/user_manage.js' %}"></script>
</body>
</html>