feat: 账号锁定功能

This commit is contained in:
H0nGzA1
2023-04-12 01:58:34 +08:00
parent 953fcc3437
commit 592bc947a0
3 changed files with 90 additions and 93 deletions

View File

@@ -1,11 +1,9 @@
import base64
import hashlib
from datetime import datetime, timedelta
from captcha.views import CaptchaStore, captcha_image
from django.contrib import auth
from django.contrib.auth import login
from django.contrib.auth.hashers import make_password, check_password
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _
from drf_yasg import openapi
@@ -14,9 +12,7 @@ from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from application import dispatch
from dvadmin.system.models import Users
from dvadmin.utils.json_response import ErrorResponse, DetailResponse
@@ -58,6 +54,7 @@ class LoginSerializer(TokenObtainPairSerializer):
captcha = serializers.CharField(
max_length=6, required=False, allow_null=True, allow_blank=True
)
class Meta:
model = Users
fields = "__all__"
@@ -86,6 +83,11 @@ class LoginSerializer(TokenObtainPairSerializer):
else:
self.image_code and self.image_code.delete()
raise CustomValidationError("图片验证码错误")
user = Users.objects.get(username=attrs['username'])
if not user.is_active:
raise CustomValidationError("账号被锁定")
data = super().validate(attrs)
data["name"] = self.user.name
data["userId"] = self.user.id
@@ -107,6 +109,7 @@ class LoginSerializer(TokenObtainPairSerializer):
save_login_log(request=request)
return {"code": 2000, "msg": "请求成功", "data": data}
class LoginView(TokenObtainPairView):
"""
登录接口

View File

@@ -1,15 +1,12 @@
import * as api from './api';
import { dict, PageQuery, AddReq, DelReq, EditReq, CrudExpose, CrudOptions, compute } from '@fast-crud/fast-crud';
import { dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud';
import { request } from '/@/utils/service';
import { dictionary } from '/@/utils/dictionary';
import { successMessage } from '/@/utils/message';
import { inject } from 'vue';
interface CreateCrudOptionsTypes {
crudOptions: CrudOptions;
}
export const createCrudOptions = function ({ crudExpose }: { crudExpose: CrudExpose }): CreateCrudOptionsTypes {
const pageRequest = async (query: PageQuery) => {
export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet {
const pageRequest = async (query: UserPageQuery) => {
return await api.GetList(query);
};
const editRequest = async ({ form, row }: EditReq) => {

View File

@@ -7,11 +7,11 @@
部门列表
<el-tooltip effect="dark" :content="content" placement="right">
<el-icon>
<QuestionFilled/>
<QuestionFilled />
</el-icon>
</el-tooltip>
</p>
<el-input v-model="filterText" :placeholder="placeholder"/>
<el-input v-model="filterText" :placeholder="placeholder" />
<el-tree
ref="treeRef"
class="font-mono font-bold leading-6 text-7xl"
@@ -30,9 +30,7 @@
</el-col>
<el-col xs="24" :sm="16" :md="18" :lg="20" :xl="20" class="p-1">
<el-card :body-style="{ height: '100%' }">
<fs-crud ref="crudRef" v-bind="crudBinding"></fs-crud>
</el-card>
</el-col>
</el-row>
@@ -40,14 +38,15 @@
</template>
<script lang="ts" setup>
import {useExpose, useCrud} from '@fast-crud/fast-crud';
import {createCrudOptions} from './crud';
import { useExpose, useCrud } from '@fast-crud/fast-crud';
import { createCrudOptions } from './crud';
import * as api from './api';
import {ElTree} from 'element-plus';
import {ref, onMounted, watch, toRaw, defineAsyncComponent} from 'vue';
import { ElTree } from 'element-plus';
import { ref, onMounted, watch, toRaw, defineAsyncComponent } from 'vue';
import XEUtils from 'xe-utils';
import {errorMessage, successMessage} from '../../../utils/message';
import {GetDept} from "./api";
import { errorMessage, successMessage } from '../../../utils/message';
import { GetDept } from './api';
import { dictionary } from '/@/utils/dictionary';
interface Tree {
id: number;
@@ -70,7 +69,7 @@ const treeRef = ref<InstanceType<typeof ElTree>>();
const treeProps = {
children: 'children',
label: 'name',
icon: 'icon'
icon: 'icon',
};
watch(filterText, (val) => {
@@ -82,7 +81,6 @@ const filterNode = (value: string, data: Tree) => {
return toRaw(data).name.indexOf(value) !== -1;
};
let data = ref([]);
const content = `
@@ -95,18 +93,17 @@ const getData = () => {
const result = XEUtils.toArrayTree(responseData, {
parentKey: 'parent',
children: 'children',
strict: true
strict: true,
});
console.log(result)
data.value = result;
});
};
//树形点击事件
const onTreeNodeClick = (node: any) => {
const {id} = node
crudExpose.doSearch({form: {dept: id}})
}
const { id } = node;
crudExpose.doSearch({ form: { dept: id } });
};
// 页面打开后获取列表数据
onMounted(() => {
@@ -118,11 +115,11 @@ const crudRef = ref();
// crud 配置的ref
const crudBinding = ref();
// 暴露的方法
const {crudExpose} = useExpose({crudRef, crudBinding});
const { crudExpose } = useExpose({ crudRef, crudBinding });
// 你的crud配置
const {crudOptions} = createCrudOptions({crudExpose});
const { crudOptions } = createCrudOptions({ crudExpose });
// 初始化crud配置
const {resetCrudOptions} = useCrud({crudExpose, crudOptions});
const { resetCrudOptions } = useCrud({ crudExpose, crudOptions });
// 页面打开后获取列表数据
onMounted(() => {